org.clinigrid.capillary.maven.CapillaryMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.clinigrid.capillary.maven.CapillaryMojo.java

Source

/*******************************************************************************
 * GeneratorMojo.java
 * 
 * Copyright (c) 2011 Clinigrid.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * 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.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Contributors:
 *     Didier Villevalois - initial API and implementation
 ******************************************************************************/
package org.clinigrid.capillary.maven;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.clinigrid.capillary.maven.util.CastUtil;

/**
 * Goal which generate the Capillary artifacts.
 *
 * @goal generate
 * @phase generate-sources
 *
 * @requiresDependencyResolution compile+runtime
 */
public class CapillaryMojo extends AbstractMojo {

    /** @parameter */
    private File targetDirectory;

    /** @parameter */
    private Job[] jobs;

    /** @parameter default-value="${project}" */
    private MavenProject project;

    /** @component */
    private org.apache.maven.artifact.factory.ArtifactFactory artifactFactory;

    /** @component */
    private MavenProjectBuilder mavenProjectBuilder;

    /** @component */
    private org.apache.maven.artifact.resolver.ArtifactResolver resolver;

    /**@parameter default-value="${localRepository}" */
    private org.apache.maven.artifact.repository.ArtifactRepository localRepository;

    /** @parameter default-value="${project.remoteArtifactRepositories}" */
    private List<?> remoteRepositories;

    /** @component */
    private ArtifactMetadataSource artifactMetadataSource;

    /** @parameter expression="${plugin.artifacts}" */
    private List<?> pluginDependencies;

    public void execute() throws MojoExecutionException {
        if (targetDirectory == null)
            throw new MojoExecutionException("Target directory = null");

        if (jobs == null || jobs.length == 0)
            throw new MojoExecutionException("You have to at least specify one job to execute");

        for (Job job : Arrays.asList(jobs)) {
            job.setCapillaryMojo(this);
            job.setTargetDirectory(targetDirectory);
            job.execute();
        }
    }

    @SuppressWarnings("unchecked")
    <T extends Job> List<T> getJobsOfType(Class<T> jobClass) {
        List<T> selectedJobs = new ArrayList<T>();
        for (Job job : Arrays.asList(jobs)) {
            if (jobClass.isInstance(job)) {
                selectedJobs.add((T) job);
            }
        }
        return selectedJobs;
    }

    public Artifact getArtifact(String descriptor) throws MojoExecutionException {
        String[] splitDescriptor = descriptor.split(":");
        if (splitDescriptor.length == 2) {
            for (Artifact artifact : CastUtil.<Artifact>castSet(project.getDependencyArtifacts())) {
                if (artifact.getGroupId().equals(splitDescriptor[0])
                        && artifact.getArtifactId().equals(splitDescriptor[1])) {
                    return artifact;
                }
            }
            throw new MojoExecutionException(String.format("Can't find artifact '%s'", descriptor));
        } else if (splitDescriptor.length == 4) {
            Artifact artifact = artifactFactory.createBuildArtifact(splitDescriptor[0], splitDescriptor[1],
                    splitDescriptor[3], splitDescriptor[2]);
            try {
                resolver.resolve(artifact, remoteRepositories, localRepository);
                return artifact;
            } catch (ArtifactResolutionException e) {
                throw new MojoExecutionException(String.format("Can't find artifact '%s'", artifact.toString()), e);
            } catch (ArtifactNotFoundException e) {
                throw new MojoExecutionException(String.format("Can't find artifact '%s'", artifact.toString()), e);
            }
        } else {
            throw new MojoExecutionException(String.format("Can't find artifact '%s'", descriptor));
        }
    }

    public Set<Artifact> getDependenciesOf(Artifact artifact) throws MojoExecutionException {
        try {
            Artifact pomArtifact = artifactFactory.createArtifact(artifact.getGroupId(), artifact.getArtifactId(),
                    artifact.getVersion(), artifact.getClassifier(), "pom");
            MavenProject pomProject = mavenProjectBuilder.buildFromRepository(pomArtifact, remoteRepositories,
                    localRepository);

            Set<?> artifacts = pomProject.createArtifacts(artifactFactory, null, null);
            ArtifactFilter filter = new ScopeArtifactFilter("compile");
            ArtifactResolutionResult arr = resolver.resolveTransitively(artifacts, pomArtifact, localRepository,
                    remoteRepositories, artifactMetadataSource, filter);
            return CastUtil.castSet(arr.getArtifacts());
        } catch (ProjectBuildingException e) {
            throw new MojoExecutionException(String.format("Can't get depedencies of '%s'", artifact.toString()),
                    e);
        } catch (InvalidDependencyVersionException e) {
            throw new MojoExecutionException(String.format("Can't get depedencies of '%s'", artifact.toString()),
                    e);
        } catch (ArtifactResolutionException e) {
            throw new MojoExecutionException(String.format("Can't get depedencies of '%s'", artifact.toString()),
                    e);
        } catch (ArtifactNotFoundException e) {
            throw new MojoExecutionException(String.format("Can't get depedencies of '%s'", artifact.toString()),
                    e);
        }
    }

    /**
     * Set up a classloader for the execution of the main class.
     *
     * @return the classloader
     * @throws MojoExecutionException if a problem happens
     */
    public ClassLoader getClassLoader() throws MojoExecutionException {
        List<URL> classpathURLs = new ArrayList<URL>();
        addRelevantProjectDependenciesToClasspath(classpathURLs);
        addRelevantPluginDependenciesToClasspath(classpathURLs);
        return new URLClassLoader(classpathURLs.toArray(new URL[classpathURLs.size()]),
                this.getClass().getClassLoader());
    }

    /**
     * Add any relevant project dependencies to the classpath.
     * Takes includeProjectDependencies into consideration.
     *
     * @param path classpath of {@link java.net.URL} objects
     * @throws MojoExecutionException if a problem happens
     */
    private void addRelevantProjectDependenciesToClasspath(List<URL> path) throws MojoExecutionException {
        try {
            getLog().debug("Project Dependencies will be included.");

            List<Artifact> artifacts = new ArrayList<Artifact>();
            List<File> theClasspathFiles = new ArrayList<File>();

            collectProjectArtifactsAndClasspath(artifacts, theClasspathFiles);

            for (Iterator<File> it = theClasspathFiles.iterator(); it.hasNext();) {
                URL url = it.next().toURI().toURL();
                getLog().debug("Adding to classpath : " + url);
                path.add(url);
            }

            Iterator<Artifact> iter = artifacts.iterator();
            while (iter.hasNext()) {
                Artifact classPathElement = iter.next();
                getLog().debug("Adding project dependency artifact: " + classPathElement.getArtifactId()
                        + " to classpath");
                path.add(classPathElement.getFile().toURI().toURL());
            }

        } catch (MalformedURLException e) {
            throw new MojoExecutionException("Error during setting up classpath", e);
        }
    }

    private void addRelevantPluginDependenciesToClasspath(List<URL> path) throws MojoExecutionException {
        try {
            getLog().debug("Plugin Dependencies will be included.");

            Iterator<Artifact> iter = CastUtil.<Artifact>castList(pluginDependencies).iterator();
            while (iter.hasNext()) {
                Artifact classPathElement = iter.next();
                getLog().debug(
                        "Adding plugin dependency artifact: " + classPathElement.getArtifactId() + " to classpath");
                path.add(classPathElement.getFile().toURI().toURL());
            }

        } catch (MalformedURLException e) {
            throw new MojoExecutionException("Error during setting up classpath", e);
        }
    }

    /**
    * Collects the project artifacts in the specified List and the project specific classpath (build output and build
    * test output) Files in the specified List, depending on the plugin classpathScope value.
    * 
    * @param artifacts the list where to collect the scope specific artifacts
    * @param theClasspathFiles the list where to collect the scope specific output directories
    */
    @SuppressWarnings("unchecked")
    protected void collectProjectArtifactsAndClasspath(List<Artifact> artifacts, List<File> theClasspathFiles) {

        artifacts.addAll(project.getCompileArtifacts());
        theClasspathFiles.add(new File(project.getBuild().getSourceDirectory()));
        theClasspathFiles.add(new File(project.getBuild().getOutputDirectory()));

        getLog().debug("Collected project artifacts " + artifacts);
        getLog().debug("Collected project classpath " + theClasspathFiles);
    }

    public String getRelativeSource(String sourceFilename) {
        String sourceFolder = project.getBuild().getSourceDirectory();
        String projectFolder = project.getBasedir().getAbsolutePath();
        String relativeSourceFolder = sourceFolder.substring(projectFolder.length() + 1);

        if (sourceFilename.startsWith(relativeSourceFolder)) {
            return sourceFilename.substring(relativeSourceFolder.length() + 1);
        }
        return sourceFilename;
    }
}