com.totsp.mavenplugin.gwt.util.BuildClasspathUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.totsp.mavenplugin.gwt.util.BuildClasspathUtil.java

Source

/*
 * 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
 */
package com.totsp.mavenplugin.gwt.util;

import com.totsp.mavenplugin.gwt.AbstractGWTMojo;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.ActiveProjectArtifact;

import java.io.File;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Util to consolidate classpath manipulation stuff in one place.
 * 
 * @author ccollins
 */
public class BuildClasspathUtil {

    public static Set<File> getSystemPaths(final AbstractGWTMojo mojo) {
        MavenProject project = mojo.getProject();
        Set<File> items = new LinkedHashSet<File>();
        // add system
        for (Artifact a : (Collection<Artifact>) project.getSystemArtifacts()) {
            items.add(a.getFile());
        }
        return items;
    }

    // TODO all over this class we have methods that manipulate input parameters, remove that
    // we should return values and/or let the object keep state, not manipulate params    

    /**
     * Build classpath list using either gwtHome (if present) or using *project* dependencies. Note
     * that this is ONLY used for the script/cmd writers (so the scopes are not for the compiler, or
     * war plugins, etc).
     * 
     * This is required so that the script writers can get the dependencies they need regardless of
     * the Maven scopes (still want to use the Maven scopes for everything else Maven, but for
     * GWT-Maven we need to access deps differently - directly at times).
     * 
     * 
     * @param mojo
     * @param scope
     * @return file collection for classpath
     * @throws DependencyResolutionRequiredException
     */
    public static Collection<File> buildClasspathList(final AbstractGWTMojo mojo, final DependencyScope scope)
            throws DependencyResolutionRequiredException, MojoExecutionException {
        mojo.getLog().info("establishing classpath list (buildClaspathList - scope = " + scope + ")");

        File gwtHome = mojo.getGwtHome();
        MavenProject project = mojo.getProject();

        Set<File> items = new LinkedHashSet<File>();

        // inject GWT jars and relative native libs for all scopes
        // (gwt-user and gwt-dev should be scoped provided to keep them out of
        // other maven stuff - not end up in war, etc - this util is only used for GWT-Maven
        // scripts)
        // TODO filter the rest of the stuff so we don't double add these
        if (gwtHome != null) {
            mojo.getLog().info("google.webtoolkit.home (gwtHome) set, using it for GWT dependencies - "
                    + gwtHome.getAbsolutePath());
            items.addAll(BuildClasspathUtil.injectGwtDepsFromGwtHome(gwtHome, mojo));
        } else {
            mojo.getLog()
                    .info("google.webtoolkit.home (gwtHome) *not* set, using project POM for GWT dependencies");
            items.addAll(BuildClasspathUtil.injectGwtDepsFromRepo(mojo));
        }

        // add sources
        if (mojo.getSourcesOnPath()) {
            BuildClasspathUtil.addSourcesWithActiveProjects(project, items, DependencyScope.COMPILE);
        }

        // add resources
        if (mojo.getResourcesOnPath()) {
            BuildClasspathUtil.addResourcesWithActiveProjects(project, items, DependencyScope.COMPILE);
        }

        // add classes dir
        items.add(new File(project.getBuild().getDirectory() + File.separator + "classes"));

        // if runtime add runtime
        if (scope == DependencyScope.RUNTIME) {
            // use Collection<Artifact> because sometimes it's LinkedHashSet, sometimes it's List, and NO TIMES is it documented
            for (Artifact a : (Collection<Artifact>) project.getRuntimeArtifacts()) {
                items.add(a.getFile());
            }
        }

        // if test add test
        if (scope == DependencyScope.TEST) {
            for (Artifact a : (Collection<Artifact>) project.getTestArtifacts()) {
                items.add(a.getFile());
            }

            // add test classes dir
            items.add(new File(project.getBuild().getDirectory() + File.separator + "test-classes"));

            // add test sources and resources
            BuildClasspathUtil.addSourcesWithActiveProjects(project, items, scope);
            BuildClasspathUtil.addResourcesWithActiveProjects(project, items, scope);
        }

        // add compile (even when scope is other than)
        for (Artifact a : (Collection<Artifact>) project.getCompileArtifacts()) {
            items.add(a.getFile());
        }

        // add all source artifacts
        for (Artifact a : (Collection<Artifact>) project.getArtifacts()) {
            if ("sources".equals(a.getClassifier())) {
                items.add(a.getFile());
            }
        }

        mojo.getLog().debug("SCRIPT INJECTION CLASSPATH LIST");

        for (File f : items) {
            mojo.getLog().debug("   " + f.getAbsolutePath());
        }

        return items;
    }

    /**
     * Helper to inject gwt-user and gwt-dev into classpath from gwtHome, ONLY for compile and run
     * scripts.
     * 
     * @param mojo
     * @return
     */
    public static Collection<File> injectGwtDepsFromGwtHome(final File gwtHome, final AbstractGWTMojo mojo) {
        mojo.getLog().debug(
                "injecting gwt-user and gwt-dev for script classpath from google.webtoolkit.home (and expecting relative native libs)");

        Collection<File> items = new LinkedHashSet<File>();
        if (mojo.isUseOophm()) {
            File oophmJar = new File(gwtHome, "gwt-dev-oophm.jar");
            items.add(oophmJar);
        }
        File userJar = new File(gwtHome, "gwt-user.jar");
        File devJar = mojo.getGwtVersion().startsWith("2.") ? new File(gwtHome, "gwt-dev.jar")
                : new File(gwtHome, ArtifactNameUtil.guessDevJarName());
        items.add(userJar);
        items.add(devJar);

        return items;
    }

    /**
     * Helper to inject gwt-user and gwt-dev into classpath from repo, ONLY for compile and run
     * scripts.
     * 
     * @param mojo
     * @return
     */
    public static Collection<File> injectGwtDepsFromRepo(final AbstractGWTMojo mojo) throws MojoExecutionException {
        mojo.getLog().debug(
                "injecting gwt-user and gwt-dev for script classpath from local repository (and expecting relative native libs)");

        Collection<File> items = new LinkedHashSet<File>();

        Artifact gwtUser = mojo.getArtifactFactory().createArtifactWithClassifier("com.google.gwt", "gwt-user",
                mojo.getGwtVersion(), "jar", null);
        Artifact gwtDev = mojo.getGwtVersion().startsWith("2.")
                ? mojo.getArtifactFactory().createArtifactWithClassifier("com.google.gwt", "gwt-dev",
                        mojo.getGwtVersion(), "jar", null)
                : mojo.getArtifactFactory().createArtifactWithClassifier("com.google.gwt", "gwt-dev",
                        mojo.getGwtVersion(), "jar", ArtifactNameUtil.getPlatformName());
        Artifact oophm = null;
        if (mojo.isUseOophm()) {
            oophm = mojo.getArtifactFactory().createArtifactWithClassifier("com.google.gwt", "gwt-dev-oophm",
                    mojo.getGwtVersion(), "jar", ArtifactNameUtil.getPlatformName());
        }
        List<ArtifactRepository> remoteRepositories = mojo.getRemoteRepositories();

        try {
            mojo.getResolver().resolve(gwtUser, remoteRepositories, mojo.getLocalRepository());
            mojo.getResolver().resolve(gwtDev, remoteRepositories, mojo.getLocalRepository());
            if (oophm != null) {
                mojo.getResolver().resolve(oophm, remoteRepositories, mojo.getLocalRepository());
                items.add(oophm.getFile());
            }
            items.add(gwtUser.getFile());
            items.add(gwtDev.getFile());
        } catch (ArtifactNotFoundException e) {
            throw new MojoExecutionException("artifact not found - " + e.getMessage(), e);
        } catch (ArtifactResolutionException e) {
            throw new MojoExecutionException("artifact resolver problem - " + e.getMessage(), e);
        }

        return items;
    }

    /**
     * Cut from MavenProject.java
     * 
     * @param groupId
     * @param artifactId
     * @param version
     * @return
     */
    private static String getProjectReferenceId(final String groupId, final String artifactId,
            final String version) {
        return groupId + ":" + artifactId + ":" + version;
    }

    /**
     * Get resources for specific scope.
     * 
     * @param project
     * @param scope
     * @return
     */
    @SuppressWarnings("unchecked")
    private static List<Resource> getResources(final MavenProject project, final DependencyScope scope) {
        if (DependencyScope.COMPILE.equals(scope)) {
            return project.getResources();
        } else if (DependencyScope.TEST.equals(scope)) {
            return project.getTestResources();
        } else {
            throw new RuntimeException("Not allowed scope " + scope);
        }
    }

    /**
     * Get artifacts for specific scope.
     * 
     * @param project
     * @param scope
     * @return
     */
    @SuppressWarnings("unchecked")
    private static List<Artifact> getScopeArtifacts(final MavenProject project, final DependencyScope scope) {
        if (DependencyScope.COMPILE.equals(scope)) {
            return project.getCompileArtifacts();
        } else if (DependencyScope.TEST.equals(scope)) {
            return project.getTestArtifacts();
        } else {
            throw new RuntimeException("Not allowed scope " + scope);
        }
    }

    /**
     * Get source roots for specific scope.
     * 
     * @param project
     * @param scope
     * @return
     */
    private static List<String> getSourceRoots(final MavenProject project, final DependencyScope scope) {
        if (DependencyScope.COMPILE.equals(scope)) {
            return project.getCompileSourceRoots();
        } else if (DependencyScope.TEST.equals(scope)) {
            return project.getTestCompileSourceRoots();
        } else {
            throw new RuntimeException("Not allowed scope " + scope);
        }
    }

    /**
     * Add source path and resource paths of the project to the list of classpath items.
     * 
     * @param items Classpath items.
     * @param resources
     */
    private static void addResources(final Set<File> items, final List<Resource> resources) {
        for (Resource r : resources) {
            items.add(new File(r.getDirectory()));
        }
    }

    /**
     * Add all sources and resources also with active (maven reactor active) referenced project
     * sources and resources. Addresses issue no. 147.
     * 
     * @param project
     * @param items
     * @param scope
     */
    private static void addResourcesWithActiveProjects(final MavenProject project, final Set<File> items,
            final DependencyScope scope) {
        final List<Artifact> scopeArtifacts = BuildClasspathUtil.getScopeArtifacts(project, scope);

        List<Resource> resources = BuildClasspathUtil.getResources(project, scope);
        BuildClasspathUtil.addResources(items, resources);

        for (Artifact artifact : scopeArtifacts) {
            if (artifact instanceof ActiveProjectArtifact) {
                MavenProject refProject = (MavenProject) project.getProjectReferences()
                        .get(BuildClasspathUtil.getProjectReferenceId(artifact.getGroupId(),
                                artifact.getArtifactId(), artifact.getVersion()));

                if (refProject != null) {
                    List<Resource> resourcesRef = BuildClasspathUtil.getResources(refProject, scope);
                    BuildClasspathUtil.addResources(items, resourcesRef);
                }
            }
        }
    }

    /**
     * Add source path and resource paths of the project to the list of classpath items.
     * 
     * @param items Classpath items.
     * @param sourceRoots
     */
    private static void addSources(final Set<File> items, final List<String> sourceRoots) {
        for (String s : sourceRoots) {
            items.add(new File(s));
        }
    }

    /**
     * Add all sources and resources also with active (maven reactor active) referenced project
     * sources and resources. Addresses issue no. 147.
     * 
     * @param project
     * @param items
     * @param scope
     */
    private static void addSourcesWithActiveProjects(final MavenProject project, final Set<File> items,
            final DependencyScope scope) {

        List<Artifact> scopeArtifacts = BuildClasspathUtil.getScopeArtifacts(project, scope);
        List<String> sourceRoots = BuildClasspathUtil.getSourceRoots(project, scope);
        BuildClasspathUtil.addSources(items, sourceRoots);

        for (Artifact artifact : scopeArtifacts) {
            if (artifact instanceof ActiveProjectArtifact) {
                MavenProject refProject = (MavenProject) project.getProjectReferences()
                        .get(BuildClasspathUtil.getProjectReferenceId(artifact.getGroupId(),
                                artifact.getArtifactId(), artifact.getVersion()));

                if (refProject != null) {
                    List<String> sourceRootsRef = BuildClasspathUtil.getSourceRoots(refProject, scope);
                    BuildClasspathUtil.addSources(items, sourceRootsRef);
                }
            }
        }
    }
}