org.eclipse.xtend.maven.AbstractXtendCompilerMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.xtend.maven.AbstractXtendCompilerMojo.java

Source

/*******************************************************************************
 * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.xtend.maven;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.newArrayList;
import static org.eclipse.xtext.util.Strings.concat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.apache.maven.toolchain.java.DefaultJavaToolChain;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.xtend.core.compiler.batch.XtendBatchCompiler;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import com.google.inject.Provider;

/**
 * @author Michael Clay - Initial contribution and API
 */
public abstract class AbstractXtendCompilerMojo extends AbstractXtendMojo {
    protected static final Predicate<String> FILE_EXISTS = new Predicate<String>() {

        public boolean apply(String filePath) {
            return new File(filePath).exists();
        }
    };

    /**
     * Create Java Source Code that is compatible to this Java version.
     * 
     * Supported values: 1.5, 1.6, 1.7, and 1.8
     *
     * @parameter expression="${maven.compiler.source}" default-value="1.6"
     */
    private String javaSourceVersion;

    /**
     * @component
     */
    private ToolchainManager toolchainManager;

    /**
     * The current build session instance. This is used for toolchain manager API calls.
     *
     * @parameter expression="${session}"
     * @required
     * @readonly
     */
    private MavenSession session;

    /**
     * Xtend-File encoding argument for the compiler.
     * 
     * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
     */
    private String encoding;

    /**
     * Set this to false to suppress the creation of *._trace files.
     * 
     * @parameter default-value="true" expression="${writeTraceFiles}"
     */
    private boolean writeTraceFiles;

    /**
     * Location of the Xtend settings file.
     * 
     * @parameter default-value="${basedir}/.settings/org.eclipse.xtend.core.Xtend.prefs"
     * @readonly
     */
    private String propertiesFileLocation;

    /**
     * Whether <code>@SuppressWarnings</code> shall be generated for non-nested types.
     * 
     * @parameter default-value="true"
     */
    private boolean generateSyntheticSuppressWarnings;

    /**
     * Whether <code>@Generated</code> shall be generated for non-nested types.
     * 
     * @parameter default-value="false"
     */
    private boolean generateGeneratedAnnotation;

    /**
     * Whether the current time shall be added to <code>@Generated</code> annotations.
     * 
     * @parameter default-value="false"
     */
    private boolean includeDateInGeneratedAnnotation;

    /**
     * The comment that is added to <code>@Generated</code> annotations, also supports variables:
     * <ul>
     * <li><code>${sourcefile}</code></li>
     * </ul>
     * 
     * @parameter
     */
    private String generatedAnnotationComment;

    @Inject
    private Provider<XtendBatchCompiler> xtendBatchCompilerProvider;

    protected XtendBatchCompiler getBatchCompiler() {
        return xtendBatchCompilerProvider.get();
    }

    protected void compile(String classPath, List<String> sourcePaths, String outputPath)
            throws MojoExecutionException {
        XtendBatchCompiler compiler = getBatchCompiler();
        Log log = getLog();
        compiler.setResourceSetProvider(new MavenProjectResourceSetProvider(project));
        Iterable<String> filtered = filter(sourcePaths, FILE_EXISTS);
        if (Iterables.isEmpty(filtered)) {
            String dir = Iterables.toString(sourcePaths);
            log.info("skip compiling sources because the configured directory '" + dir + "' does not exist.");
            return;
        }
        String baseDir = project.getBasedir().getAbsolutePath();
        log.debug("Set Java Compliance Level: " + javaSourceVersion);
        compiler.setJavaSourceVersion(javaSourceVersion);
        log.debug("Set generateSyntheticSuppressWarnings: " + generateSyntheticSuppressWarnings);
        compiler.setGenerateSyntheticSuppressWarnings(generateSyntheticSuppressWarnings);
        log.debug("Set generateGeneratedAnnotation: " + generateGeneratedAnnotation);
        compiler.setGenerateGeneratedAnnotation(generateGeneratedAnnotation);
        log.debug("Set includeDateInGeneratedAnnotation: " + includeDateInGeneratedAnnotation);
        compiler.setIncludeDateInGeneratedAnnotation(includeDateInGeneratedAnnotation);
        log.debug("Set generatedAnnotationComment: " + generatedAnnotationComment);
        compiler.setGeneratedAnnotationComment(generatedAnnotationComment);
        log.debug("Set baseDir: " + baseDir);
        compiler.setBasePath(baseDir);
        log.debug("Set temp directory: " + getTempDirectory());
        compiler.setTempDirectory(getTempDirectory());
        log.debug("Set DeleteTempDirectory: " + false);
        compiler.setDeleteTempDirectory(false);
        log.debug("Set classpath: " + classPath);
        compiler.setClassPath(classPath);
        String bootClassPath = getBootClassPath();
        log.debug("Set bootClasspath: " + bootClassPath);
        compiler.setBootClassPath(bootClassPath);
        log.debug("Set source path: " + concat(File.pathSeparator, newArrayList(filtered)));
        compiler.setSourcePath(concat(File.pathSeparator, newArrayList(filtered)));
        log.debug("Set output path: " + outputPath);
        compiler.setOutputPath(outputPath);
        log.debug("Set encoding: " + encoding);
        compiler.setFileEncoding(encoding);
        log.debug("Set writeTraceFiles: " + writeTraceFiles);
        compiler.setWriteTraceFiles(writeTraceFiles);
        if (!compiler.compile()) {
            String dir = concat(File.pathSeparator, newArrayList(filtered));
            throw new MojoExecutionException("Error compiling xtend sources in '" + dir + "'.");
        }
    }

    private String getBootClassPath() {
        Toolchain toolchain = toolchainManager.getToolchainFromBuildContext("jdk", session);
        if (toolchain instanceof DefaultJavaToolChain) {
            DefaultJavaToolChain javaToolChain = (DefaultJavaToolChain) toolchain;
            getLog().info("Using toolchain " + javaToolChain);

            String[] includes = { "jre/lib/*", "jre/lib/ext/*", "jre/lib/endorsed/*" };
            String[] excludes = new String[0];
            Xpp3Dom config = (Xpp3Dom) javaToolChain.getModel().getConfiguration();
            if (config != null) {
                Xpp3Dom bootClassPath = config.getChild("bootClassPath");
                if (bootClassPath != null) {
                    Xpp3Dom includeParent = bootClassPath.getChild("includes");
                    if (includeParent != null) {
                        includes = getValues(includeParent.getChildren("include"));
                    }
                    Xpp3Dom excludeParent = bootClassPath.getChild("excludes");
                    if (excludeParent != null) {
                        excludes = getValues(excludeParent.getChildren("exclude"));
                    }
                }
            }

            return scanBootclasspath(javaToolChain.getJavaHome(), includes, excludes);
        }
        return "";
    }

    private String scanBootclasspath(String javaHome, String[] includes, String[] excludes) {
        getLog().debug("Scanning bootClassPath:\n" + "\tjavaHome = " + javaHome + "\n" + "\tincludes = "
                + Arrays.toString(includes) + "\n" + "\texcludes = " + Arrays.toString(excludes));
        DirectoryScanner scanner = new DirectoryScanner();
        scanner.setBasedir(new File(javaHome));
        scanner.setIncludes(includes);
        scanner.setExcludes(excludes);
        scanner.scan();

        StringBuilder bootClassPath = new StringBuilder();
        String[] includedFiles = scanner.getIncludedFiles();
        for (int i = 0; i < includedFiles.length; i++) {
            if (i > 0) {
                bootClassPath.append(File.pathSeparator);
            }
            bootClassPath.append(new File(javaHome, includedFiles[i]).getAbsolutePath());
        }
        return bootClassPath.toString();
    }

    private String[] getValues(Xpp3Dom[] children) {
        String[] values = new String[children.length];
        for (int i = 0; i < values.length; i++) {
            values[i] = children[i].getValue();
        }
        return values;
    }

    protected abstract String getTempDirectory();

    protected void addDependencies(Set<String> classPath, List<Artifact> dependencies) {
        for (Artifact artifact : dependencies) {
            classPath.add(artifact.getFile().getAbsolutePath());
        }
    }

    protected void readXtendEclipseSetting(String sourceDirectory, Procedure1<String> fieldSetter) {
        if (propertiesFileLocation != null) {
            File f = new File(propertiesFileLocation);
            if (f.canRead()) {
                Properties xtendSettings = new Properties();
                try {
                    xtendSettings.load(new FileInputStream(f));
                    // TODO read Xtend setup to compute the properties file loc and property name
                    String xtendOutputDirProp = xtendSettings.getProperty("outlet.DEFAULT_OUTPUT.directory", null);
                    if (xtendOutputDirProp != null) {
                        File srcDir = new File(sourceDirectory);
                        getLog().debug("Source dir : " + srcDir.getPath() + " exists " + srcDir.exists());
                        if (srcDir.exists() && srcDir.getParent() != null) {
                            String path = new File(srcDir.getParent(), xtendOutputDirProp).getPath();
                            getLog().debug("Applying Xtend property: " + xtendOutputDirProp);
                            fieldSetter.apply(path);
                        }
                    }
                } catch (FileNotFoundException e) {
                    getLog().warn(e);
                } catch (IOException e) {
                    getLog().warn(e);
                }
            } else {
                getLog().info("Can't find Xtend properties under " + propertiesFileLocation
                        + ", maven defaults are used.");
            }
        }
    }

    protected String resolveToBaseDir(final String directory) throws MojoExecutionException {
        File outDir = new File(directory);
        if (!outDir.isAbsolute()) {
            outDir = new File(project.getBasedir(), directory);
        }
        return outDir.getAbsolutePath();
    }
}