org.nuxeo.build.maven.AntBuildMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.nuxeo.build.maven.AntBuildMojo.java

Source

/*
 * (C) Copyright 2006-2013 Nuxeo SA (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     bstefanescu, jcarsique, slacoin
 */
package org.nuxeo.build.maven;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactCollector;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.DefaultArtifactCollector;
import org.apache.maven.artifact.resolver.ResolutionListener;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.model.Profile;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.settings.MavenSettingsBuilder;
import org.apache.tools.ant.BuildException;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.nuxeo.build.ant.AntClient;
import org.nuxeo.build.ant.artifact.Expand;
import org.nuxeo.build.ant.profile.AntProfileManager;
import org.nuxeo.build.maven.filter.TrueFilter;
import org.nuxeo.build.maven.graph.Graph;
import org.nuxeo.build.maven.graph.Node;

/**
 *
 * @goal build
 * @phase package
 *
 * @requiresDependencyResolution runtime
 *
 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
 *
 */
public class AntBuildMojo extends AbstractMojo implements MavenClient {

    protected Graph graph;

    protected AntProfileManager antProfileManager;

    /**
     * Location of the build file, if unique
     *
     * @parameter expression="${buildFile}"
     */
    protected File buildFile;

    /**
     * Location of the build files.
     *
     * @parameter expression="${buildFiles}"
     */
    protected File[] buildFiles;

    /**
     * Ant target to call on build file(s).
     *
     * @parameter expression="${target}"
     */
    protected String target;

    /**
     * Ant targets to call on build file(s).
     *
     * @since 1.6
     * @parameter expression="${targets}"
     */
    protected String[] targets;

    /**
     * How many levels the graph must be expanded before running ant.
     *
     * @parameter expression="${expand}" default-value="0"
     */
    protected String expand;

    /**
     * Location of the file.
     *
     * @parameter expression="${project}"
     * @required
     */
    protected MavenProject project;

    /**
     * Maven ProjectHelper
     *
     * @component
     * @readonly
     */
    protected MavenProjectHelper projectHelper;

    /**
     * Location of the local repository.
     *
     * @parameter expression="${localRepository}"
     * @readonly
     * @required
     */
    protected org.apache.maven.artifact.repository.ArtifactRepository localRepository;

    /**
     * List of Remote Repositories used by the resolver
     *
     * @parameter expression="${project.remoteArtifactRepositories}"
     * @readonly
     * @required
     */
    protected java.util.List<ArtifactRepository> remoteRepositories;

    /**
     * Used to look up Artifacts in the remote repository.
     *
     * @component
     * @required
     * @readonly
     */
    protected org.apache.maven.artifact.factory.ArtifactFactory factory;

    /**
     * Used to look up Artifacts in the remote repository.
     *
     * @component
     * @required
     * @readonly
     */
    protected org.apache.maven.artifact.resolver.ArtifactResolver resolver;

    /**
     *
     * @component
     * @readonly
     */
    protected MavenProjectBuilder projectBuilder;

    /**
     * @component
     * @readonly
     */
    protected ArtifactMetadataSource metadataSource;

    /**
     * The character encoding scheme to be applied.
     *
     * @parameter expression="${encoding}"
     *            default-value="${project.reporting.outputEncoding}"
     */
    private String encoding;

    /**
     * @component
     * @readonly
     * @since 1.12
     */
    protected WagonManager wagonManager;

    /**
     * @component
     * @readonly
     * @since 1.12
     */
    protected MavenSettingsBuilder settingsBuilder;

    public String getEncoding() {
        if (StringUtils.isEmpty(encoding)) {
            getLog().warn("File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
                    + ", i.e. build is platform dependent!");
            encoding = ReaderFactory.FILE_ENCODING;
        }
        return encoding;
    }

    private Logger logger;

    @Override
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void execute() throws MojoExecutionException, MojoFailureException {
        AntClient ant = new AntClient();
        MavenClientFactory.setInstance(this);
        wagonManager.setInteractive(false);

        logger = new Logger() {

            @Override
            public void debug(String message) {
                getLog().debug(message);
            }

            @Override
            public void debug(String message, Throwable error) {
                getLog().debug(message, error);
            }

            @Override
            public void error(String message) {
                getLog().error(message);
            }

            @Override
            public void error(String message, Throwable error) {
                getLog().error(message, error);
            }

            @Override
            public void info(String message) {
                getLog().info(message);
            }

            @Override
            public void info(String message, Throwable error) {
                getLog().info(message, error);
            }

            @Override
            public void warn(String message) {
                getLog().warn(message);
            }

            @Override
            public void warn(String message, Throwable error) {
                getLog().warn(message, error);
            }

            @Override
            public boolean isDebugEnabled() {
                return getLog().isDebugEnabled();
            }

            @Override
            public void info(Throwable error) {
                getLog().info(error);
            }

            @Override
            public void warn(Throwable error) {
                getLog().warn(error);
            }

            @Override
            public void error(Throwable error) {
                getLog().error(error);
            }

            @Override
            public void debug(Throwable error) {
                getLog().debug(error);
            }
        };
        antProfileManager = new AntProfileManager();

        HashMap<String, String> props = new HashMap<String, String>();
        // add project properties
        for (String key : project.getProperties().stringPropertyNames()) {
            props.put(key, project.getProperties().getProperty(key));
        }
        props.put("maven.basedir", project.getBasedir().getAbsolutePath());
        props.put("maven.project.name", project.getName());
        props.put("maven.project.artifactId", project.getArtifactId());
        props.put("maven.project.groupId", project.getGroupId());
        props.put("maven.project.version", project.getVersion());
        props.put("maven.project.packaging", project.getPackaging());
        props.put("maven.project.id", project.getId());
        props.put("maven.project.build.directory", project.getBuild().getDirectory());
        props.put("maven.project.build.outputDirectory", project.getBuild().getOutputDirectory());
        props.put("maven.project.build.finalName", project.getBuild().getFinalName());
        props.put("maven.offline", wagonManager.isOnline() ? "" : "-o");

        // add active Maven profiles to Ant
        List<Profile> profiles = getActiveProfiles();
        for (Profile profile : profiles) {
            antProfileManager.activateProfile(profile.getId(), true);
            // define a property for each activated profile
            props.put("maven.profile." + profile.getId(), "true");
            // add profile properties (overriding project ones)
            for (String key : profile.getProperties().stringPropertyNames()) {
                props.put(key, profile.getProperties().getProperty(key));
            }
        }
        // Finally add System properties (overriding project and profile ones)
        props.putAll((Map) System.getProperties());

        ant.setGlobalProperties(props);

        if (buildFile != null && buildFiles != null && buildFiles.length > 0) {
            throw new MojoExecutionException(
                    "The configuration parameters 'buildFile' and 'buildFiles' cannot both be used.");
        }
        if (buildFiles == null || buildFiles.length == 0) {
            if (buildFile == null) {
                buildFile = new File("build.xml");
            }
            buildFiles = new File[] { buildFile };
        }

        if (target != null && targets != null && targets.length > 0) {
            throw new MojoExecutionException(
                    "The configuration parameters 'target' and 'targets' cannot both be used.");
        }
        if ((targets == null || targets.length == 0) && target != null) {
            targets = new String[] { target };
        }
        for (File file : buildFiles) {
            newGraph();
            int depth = Expand.readExpand(expand);
            if (depth > 0) {
                for (Node rootNode : graph.getRoots()) {
                    graph.resolveDependencyTree(rootNode, new TrueFilter(), depth);
                }
            }

            try {
                if (targets != null && targets.length > 0) {
                    ant.run(file, Arrays.asList(targets));
                } else {
                    ant.run(file);
                }
            } catch (BuildException e) {
                throw new MojoExecutionException("Error occurred while running " + file + ": " + e.getMessage(), e);
            }
        }
    }

    /**
     * @since 1.10.2
     */
    @Override
    public Graph newGraph() {
        graph = new Graph(this);
        graph.addRootNode(project);
        return graph;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Profile> getActiveProfiles() {
        return project.getActiveProfiles();
    }

    public MavenProject getProject() {
        return project;
    }

    @Override
    public ArtifactFactory getArtifactFactory() {
        return factory;
    }

    @Override
    public ArtifactResolver getArtifactResolver() {
        return resolver;
    }

    @Override
    public ArtifactRepository getLocalRepository() {
        return localRepository;
    }

    @Override
    public MavenProjectBuilder getProjectBuilder() {
        return projectBuilder;
    }

    @Override
    public MavenProjectHelper getProjectHelper() {
        return projectHelper;
    }

    @Override
    public List<ArtifactRepository> getRemoteRepositories() {
        return remoteRepositories;
    }

    @Override
    public void resolve(Artifact artifact, List<ArtifactRepository> otherRemoteRepositories)
            throws ArtifactNotFoundException {
        try {
            resolver.resolve(artifact, otherRemoteRepositories, localRepository);
        } catch (ArtifactResolutionException e) {
            throw new RuntimeException(e);
        } catch (ArtifactNotFoundException e) {
            tryResolutionOnLocalBaseVersion(artifact, e);
        }
    }

    @Override
    public void resolve(Artifact artifact) throws ArtifactNotFoundException {
        try {
            resolver.resolve(artifact, remoteRepositories, localRepository);
        } catch (ArtifactResolutionException e) {
            throw new RuntimeException(e);
        } catch (ArtifactNotFoundException e) {
            tryResolutionOnLocalBaseVersion(artifact, e);
        }
    }

    /**
     * Try to locally resolve an artifact with its "unique" version.
     *
     * @since 1.11.1
     * @param artifact Artifact to resolve with its unique version
     * @param e ArtifactNotFoundException originally thrown
     * @throws ArtifactNotFoundException If alternate resolution failed.
     * @see Artifact#getBaseVersion()
     */
    protected void tryResolutionOnLocalBaseVersion(Artifact artifact, ArtifactNotFoundException e)
            throws ArtifactNotFoundException {
        String resolvedVersion = artifact.getVersion();
        artifact.updateVersion(artifact.getBaseVersion(), localRepository);
        File localFile = new File(localRepository.getBasedir(), localRepository.pathOf(artifact));
        if (localFile.exists()) {
            getLog().warn(String.format("Couldn't resolve %s, fallback on local install of unique version %s.",
                    resolvedVersion, artifact.getBaseVersion()));
            artifact.setResolved(true);
        } else {
            // No success, set back the previous version and raise an error
            artifact.updateVersion(resolvedVersion, localRepository);
            throw e;
        }
    }

    @Override
    public void resolveDependencyTree(Artifact artifact, ArtifactFilter filter, ResolutionListener listener)
            throws ArtifactResolutionException, ProjectBuildingException {
        MavenProject mavenProject = projectBuilder.buildFromRepository(artifact, remoteRepositories,
                localRepository);
        ArtifactCollector collector = new DefaultArtifactCollector();
        collector.collect(mavenProject.getDependencyArtifacts(), mavenProject.getArtifact(),
                mavenProject.getManagedVersionMap(), localRepository, mavenProject.getRemoteArtifactRepositories(),
                metadataSource, filter, Collections.singletonList(listener));
    }

    @Override
    public Graph getGraph() {
        return graph;
    }

    @Override
    public AntProfileManager getAntProfileManager() {
        return antProfileManager;
    }

    @Override
    public Logger getCommonLogger() {
        return logger;
    }

}