info.jtrac.maven.AntPropsMojo.java Source code

Java tutorial

Introduction

Here is the source code for info.jtrac.maven.AntPropsMojo.java

Source

/*
 * Copyright 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package info.jtrac.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolver;
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;

/**
 * base class for our mojos
 */
public abstract class AntPropsMojo extends AbstractMojo {

    //======================== MOJO ===============================
    /**
     * @parameter expression="${project}"
     */
    protected MavenProject project;

    /**
     * @parameter expression="${localRepository}"
     */
    private ArtifactRepository localRepository;

    /**
     * @component role="org.apache.maven.artifact.resolver.ArtifactResolver"
     */
    private ArtifactResolver artifactResolver;

    /**
     * @parameter expression="${project.remoteArtifactRepositories}"
     */
    private List remoteArtifactRepositories;

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

    /**
     * @component role="org.apache.maven.project.MavenProjectBuilder"
     */
    private MavenProjectBuilder mavenProjectBuilder;

    //======================== CONFIG ================================

    /**
     * Things that will be added to the "test.jars" master classpath
     * @parameter
     */
    private List testPaths;

    /**
     * Things that are not related to build / test and run but other
     * stuff like checkstyle, code coverage etc.
     * @parameter
     */
    private List extraPaths;

    //======================== PRIVATE ===============================
    /**
     * properties initialized at the top e.g. "m2.repo"
     */
    protected Map buildProperties = new LinkedHashMap();

    /**
     * this collects paths resolved from the input "testPaths" parameter
     */
    protected Map testClassPaths = new LinkedHashMap();

    /**
     * this collects paths resolved from the input "extraPaths" parameter
     */
    protected Map extraClassPaths = new LinkedHashMap();

    /**
     * this collects the list of files that go into WEB-INF/lib
     */
    protected Set runtimeFiles;

    /** 
     * hack to hold paths flagged as filesets and that should be output as
     * (relativePath1,relativePath2) not classpaths like (absolutePath1:absolutePath2)
     * ideally we should have extended the Value Objects instead of using Maps above
     */
    protected Set filesets = new HashSet();

    //========================== MAIN ================================

    public void execute() throws MojoExecutionException {
        if (testPaths == null) {
            testPaths = new ArrayList();
        }
        if (extraPaths == null) {
            extraPaths = new ArrayList();
        }
        String repoBaseDir = localRepository.getBasedir().replace('\\', '/');
        try {
            buildProperties.put("m2.repo", repoBaseDir);
            //========================================================
            Collection runtimeArtifacts = project.getArtifacts();
            runtimeFiles = getRelativePaths(getFiles(runtimeArtifacts), repoBaseDir);
            //========================================================
            Set testArtifacts = project.getDependencyArtifacts();
            testArtifacts.addAll(project.getTestArtifacts());
            Collection testFiles = getFiles(testArtifacts);
            testClassPaths.put("m2.repo", getRelativePaths(testFiles, repoBaseDir));
            //========================================================
            Properties props = loadProperties();
            for (Iterator i = testPaths.iterator(); i.hasNext();) {
                TestPath testPath = (TestPath) i.next();
                String baseDirProperty = testPath.getBaseDirProperty();
                String baseDirPath = props.getProperty(baseDirProperty);
                if (baseDirPath == null) {
                    getLog().warn("baseDirProperty + '" + baseDirProperty + "' does not exist in build.properties");
                    break;
                }
                File baseDir = new File(baseDirPath);
                if (!baseDir.exists() || !baseDir.isDirectory()) {
                    getLog().warn("path + '" + baseDirPath + "' is not valid directory");
                    break;
                }
                buildProperties.put(baseDirProperty, baseDirPath);
                Set filePaths = new TreeSet();
                for (Iterator j = testPath.getPaths().iterator(); j.hasNext();) {
                    String path = (String) j.next();
                    File file = new File(baseDirPath + "/" + path);
                    if (!file.exists()) {
                        getLog().warn("additional test path: '" + file.getPath() + "' does not exist");
                        continue;
                    }
                    if (file.isDirectory()) {
                        File[] files = file.listFiles();
                        for (int x = 0; x < files.length; x++) {
                            filePaths.add(getRelativePath(files[x], baseDir.getPath()));
                        }
                    } else {
                        filePaths.add(getRelativePath(file, baseDir.getPath()));
                    }
                }
                testClassPaths.put(baseDirProperty, filePaths);
            }
            //========================================================
            for (Iterator i = extraPaths.iterator(); i.hasNext();) {
                ExtraPath ep = (ExtraPath) i.next();
                Set paths = new TreeSet();
                Collection files = new ArrayList();
                for (Iterator j = ep.getDependencies().iterator(); j.hasNext();) {
                    Dependency d = (Dependency) j.next();
                    if (d.isResolve()) {
                        files.addAll(getFiles(d.getGroupId(), d.getArtifactId(), d.getVersion()));
                    } else {
                        Artifact a = getArtifact(d.getGroupId(), d.getArtifactId(), d.getVersion());
                        files.add(resolveArtifact(a));
                    }
                }
                paths.addAll(getRelativePaths(files, repoBaseDir));
                extraClassPaths.put(ep.getName(), paths);
                if (ep.isFileset()) {
                    filesets.add(ep.getName());
                }
            }
            //========================================================
            generate();
        } catch (Exception e) {
            e.printStackTrace();
            throw new MojoExecutionException(e.getLocalizedMessage());
        }
    }

    //========================== HELPER METHODS ======================

    /**
     * instantiate a single artifact using Maven, on the fly
     */
    private Artifact getArtifact(String groupId, String artifactId, String version) {
        return artifactFactory.createArtifact(groupId, artifactId, version, "", "jar");
    }

    /**
     * resolve dependencies for the given artifact details using Maven, on the fly
     */
    private Collection resolveDependencies(String groupId, String artifactId, String version) throws Exception {
        Artifact pomArtifact = getArtifact(groupId, artifactId, version);
        MavenProject pomProject = mavenProjectBuilder.buildFromRepository(pomArtifact, remoteArtifactRepositories,
                localRepository);
        Collection artifacts = pomProject.createArtifacts(artifactFactory, Artifact.SCOPE_TEST,
                new ScopeArtifactFilter(Artifact.SCOPE_TEST));
        Iterator i = artifacts.iterator();
        while (i.hasNext()) {
            Artifact a = (Artifact) i.next();
            resolveArtifact(a);
        }
        artifacts.add(pomArtifact);
        return artifacts;
    }

    /**
     * resolve single artifact to file, and resolve fully from repository if required
     */
    private File resolveArtifact(Artifact artifact) throws Exception {
        File f = artifact.getFile();
        if (f != null) {
            return f;
        }
        getLog().info("resolving artifact: " + artifact);
        artifactResolver.resolve(artifact, remoteArtifactRepositories, localRepository);
        return artifact.getFile();
    }

    /**
     * convert a collection of maven artifacts into a collection of files
     */
    private Collection getFiles(Collection artifacts) throws Exception {
        Collection files = new ArrayList();
        Iterator i = artifacts.iterator();
        while (i.hasNext()) {
            Artifact a = (Artifact) i.next();
            files.add(resolveArtifact(a));
        }
        return files;
    }

    /**
     * convenience combination of resolving and getting a bunch of files
     */
    private Collection getFiles(String groupId, String artifactId, String version) throws Exception {
        return getFiles(resolveDependencies(groupId, artifactId, version));
    }

    /**
     * function to return relative path given base path and the target file
     */
    private String getRelativePath(File file, String basePath) {
        String p = basePath.replace('\\', '/');
        int len = p.length() + 1;
        if (p.endsWith("/")) {
            len--;
        }
        return file.getPath().substring(len).replace('\\', '/');
    }

    /**
     * add path entries for the given bunch of files
     */
    private Set getRelativePaths(Collection files, String basePath) {
        Set paths = new TreeSet();
        Iterator i = files.iterator();
        while (i.hasNext()) {
            File f = (File) i.next();
            String path = getRelativePath(f, basePath);
            paths.add(path);
        }
        return paths;
    }

    /**
     * load properties from file
     */
    private Properties loadProperties() throws Exception {
        File file = new File("build.properties");
        Properties props = new Properties();
        if (!file.exists()) {
            getLog().warn("build.properties does not exist");
            return props;
        }
        InputStream is = null;
        try {
            is = new FileInputStream("build.properties");
            props.load(is);
        } finally {
            is.close();
        }
        return props;
    }

    protected abstract void generate() throws Exception;

    protected void generateBuildXml() {
        String projectName = project.getArtifactId();
        String projectNameTitleCase = Character.toUpperCase(projectName.charAt(0)) + projectName.substring(1);
        String buildSource = FileUtils.readFile(getClass(), "build.xml").toString();
        String buildTarget = buildSource.replace("@@project.name@@", projectName);
        buildTarget = buildTarget.replace("@@project.name.titleCase@@", projectNameTitleCase);
        FileUtils.writeFile(buildTarget, "build.xml", false);
        getLog().info("created 'build.xml'");
    }

}