de.zalando.mojo.aspectj.AjcHelper.java Source code

Java tutorial

Introduction

Here is the source code for de.zalando.mojo.aspectj.AjcHelper.java

Source

package de.zalando.mojo.aspectj;

/**
 * The MIT License
 *
 * Copyright 2005-2006 The Codehaus.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

/**
 * A helper class for creating classpaths for the compilers and report mojos
 *
 * @author <a href="mailto:kaare.nilsen@gmail.com">Kaare Nilsen</a>
 */
public class AjcHelper {
    public static final String DEFAULT_INCLUDES = "**/*.java, **/*.aj";

    public static final String DEFAULT_EXCLUDES = "";

    /**
     * List holding all accepted values for the {@code complianceLevel} parameter.
     */
    public static final List<String> ACCEPTED_COMPLIANCE_LEVEL_VALUES = Arrays.asList("1.3", "1.4", "1.5", "1.6",
            "1.7", "1.8");

    /**
     * Checks if the given complianceLevel value is valid.
     *
     * @param complianceLevel A complianceLevel
     * @return {@code true} if the supplied complianceLevel is valid, implying that it is defined within the
     * {@code ACCEPTED_COMPLIANCE_LEVEL_VALUES} List.
     * @see #ACCEPTED_COMPLIANCE_LEVEL_VALUES
     */
    public static boolean isValidComplianceLevel(String complianceLevel) {
        return ACCEPTED_COMPLIANCE_LEVEL_VALUES.contains(complianceLevel);
    }

    /**
     * Constructs AspectJ compiler classpath string
     *
     * @param project the Maven Project
     * @param pluginArtifacts the plugin Artifacts
     * @param outDirs the outputDirectories
     * @return a os spesific classpath string
     */
    @SuppressWarnings("unchecked")
    public static String createClassPath(MavenProject project, List<Artifact> pluginArtifacts,
            List<String> outDirs) {
        String cp = new String();
        Set<Artifact> classPathElements = Collections.synchronizedSet(new LinkedHashSet<Artifact>());
        Set<Artifact> dependencyArtifacts = project.getDependencyArtifacts();
        classPathElements
                .addAll(dependencyArtifacts == null ? Collections.<Artifact>emptySet() : dependencyArtifacts);
        classPathElements.addAll(project.getArtifacts());
        classPathElements.addAll(pluginArtifacts == null ? Collections.<Artifact>emptySet() : pluginArtifacts);
        for (Artifact classPathElement : classPathElements) {
            File artifact = classPathElement.getFile();
            if (null != artifact) {
                cp += classPathElement.getFile().getAbsolutePath();
                cp += File.pathSeparatorChar;
            }
        }
        Iterator<String> outIter = outDirs.iterator();
        while (outIter.hasNext()) {
            cp += outIter.next();
            cp += File.pathSeparatorChar;
        }

        if (cp.endsWith("" + File.pathSeparatorChar)) {
            cp = cp.substring(0, cp.length() - 1);
        }

        cp = StringUtils.replace(cp, "//", "/");
        return cp;
    }

    /**
     * Based on a AJDT build properties file resolves the combination of all
     * include and exclude statements and returns a set of all the files to be
     * compiled and weaved.
     *
     * @param ajdtBuildDefFile the ajdtBuildDefFile
     * @param basedir the baseDirectory
     * @return
     * @throws MojoExecutionException
     */
    public static Set<String> getBuildFilesForAjdtFile(String ajdtBuildDefFile, File basedir)
            throws MojoExecutionException {
        Set<String> result = new LinkedHashSet<String>();

        Properties ajdtBuildProperties = new Properties();
        try {
            ajdtBuildProperties.load(new FileInputStream(new File(basedir, ajdtBuildDefFile)));
        } catch (FileNotFoundException e) {
            throw new MojoExecutionException("Build properties file specified not found", e);
        } catch (IOException e) {
            throw new MojoExecutionException("IO Error reading build properties file specified", e);
        }
        result.addAll(resolveIncludeExcludeString(ajdtBuildProperties.getProperty("src.includes"), basedir));
        Set<String> exludes = resolveIncludeExcludeString(ajdtBuildProperties.getProperty("src.excludes"), basedir);
        result.removeAll(exludes);

        return result;
    }

    /**
     * Based on a set of sourcedirs, apply include and exclude statements and
     * returns a set of all the files to be compiled and weaved.
     *
     * @param sourceDirs
     * @param includes
     * @param excludes
     * @return
     * @throws MojoExecutionException
     */
    public static Set<String> getBuildFilesForSourceDirs(List<String> sourceDirs, String[] includes,
            String[] excludes) throws MojoExecutionException {
        Set<String> result = new LinkedHashSet<String>();

        for (String sourceDir : sourceDirs) {
            try {
                if (FileUtils.fileExists(sourceDir)) {
                    result.addAll(FileUtils.getFileNames(new File(sourceDir),
                            (null == includes || 0 == includes.length) ? DEFAULT_INCLUDES : getAsCsv(includes),
                            (null == excludes || 0 == excludes.length) ? DEFAULT_EXCLUDES : getAsCsv(excludes),
                            true));
                }
            } catch (IOException e) {
                throw new MojoExecutionException("IO Error resolving sourcedirs", e);
            }
        }
        // We might need to check if some of these files are already included through the weaveDirectories.

        return result;
    }

    /**
     * Based on a set of weavedirs returns a set of all the files to be weaved.
     *
     * @return
     * @throws MojoExecutionException
     */
    public static Set<String> getWeaveSourceFiles(String[] weaveDirs) throws MojoExecutionException {
        Set<String> result = new HashSet<String>();

        for (int i = 0; i < weaveDirs.length; i++) {
            String weaveDir = weaveDirs[i];
            if (FileUtils.fileExists(weaveDir)) {
                try {
                    result.addAll(FileUtils.getFileNames(new File(weaveDir), "**/*.class", DEFAULT_EXCLUDES, true));
                } catch (IOException e) {
                    throw new MojoExecutionException("IO Error resolving weavedirs", e);
                }
            }
        }
        return result;
    }

    /**
     * Creates a file that can be used as input to the ajc compiler using the -argdfile flag.
     * Each line in these files should contain one option or filename.
     * Comments, as in Java, start with // and extend to the end of the line.
     *
     * @param arguments All arguments passed to ajc in this run
     * @param fileName the filename of the argfile
     * @param outputDir the build output area.
     * @throws IOException
     */
    public static void writeBuildConfigToFile(List<String> arguments, String fileName, File outputDir)
            throws IOException {
        FileUtils.forceMkdir(outputDir);
        File argFile = new File(outputDir, fileName);
        argFile.getParentFile().mkdirs();
        argFile.createNewFile();
        BufferedWriter writer = new BufferedWriter(new FileWriter(argFile));
        for (String argument : arguments) {
            writer.write(argument);
            writer.newLine();
        }
        writer.flush();
        writer.close();
    }

    /**
     * Reads a build config file, and returns the List of all compiler arguments.
     *
     * @param fileName the filename of the argfile
     * @param outputDir the build output area
     * @return
     * @throws IOException
     */
    public static List<String> readBuildConfigFile(String fileName, File outputDir) throws IOException {
        List<String> arguments = new ArrayList<String>();
        File argFile = new File(outputDir, fileName);
        if (FileUtils.fileExists(argFile.getAbsolutePath())) {
            FileReader reader = new FileReader(argFile);
            BufferedReader bufRead = new BufferedReader(reader);
            String line = null;
            do {
                line = bufRead.readLine();
                if (null != line) {
                    arguments.add(line);
                }
            } while (null != line);
        }
        return arguments;
    }

    /**
     * Convert a string array to a comma separated list
     *
     * @param strings
     * @return
     */
    protected static String getAsCsv(String[] strings) {
        String csv = "";
        if (null != strings) {
            for (int i = 0; i < strings.length; i++) {
                csv += strings[i];
                if (i < (strings.length - 1)) {
                    csv += ",";
                }
            }
        }
        return csv;
    }

    /**
     * Helper method to find all .java or .aj files specified by the
     * includeString. The includeString is a comma separated list over files, or
     * directories relative to the specified basedir. Examples of correct
     * listings
     *
     * <pre>
     *         src/main/java/
     *         src/main/java
     *         src/main/java/com/project/AClass.java
     *         src/main/java/com/project/AnAspect.aj
     *         src/main/java/com/project/AnAspect.java
     * </pre>
     *
     * @param input
     * @param basedir the baseDirectory
     * @return a list over all files inn the include string
     * @throws IOException
     */
    protected static Set<String> resolveIncludeExcludeString(String input, File basedir)
            throws MojoExecutionException {
        Set<String> inclExlSet = new LinkedHashSet<String>();
        try {
            if (null == input || input.trim().equals("")) {
                return inclExlSet;
            }
            String[] elements = input.split(",");
            if (null != elements) {

                for (int i = 0; i < elements.length; i++) {
                    String element = elements[i];
                    if (element.endsWith(".java") || element.endsWith(".aj")) {
                        inclExlSet.addAll(FileUtils.getFileNames(basedir, element, "", true));
                    } else {
                        File lookupBaseDir = new File(basedir, element);
                        if (FileUtils.fileExists(lookupBaseDir.getAbsolutePath())) {
                            inclExlSet.addAll(FileUtils.getFileNames(lookupBaseDir, DEFAULT_INCLUDES, "", true));
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new MojoExecutionException("Could not resolve java or aspect sources to compile", e);
        }
        return inclExlSet;
    }

}