io.sarl.maven.compiler.AbstractSarlBatchCompilerMojo.java Source code

Java tutorial

Introduction

Here is the source code for io.sarl.maven.compiler.AbstractSarlBatchCompilerMojo.java

Source

/*
 * $Id$
 *
 * SARL is an general-purpose agent programming language.
 * More details on http://www.sarl.io
 *
 * Copyright (C) 2014-2017 the original authors 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 io.sarl.maven.compiler;

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

import javax.inject.Provider;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Injector;
import org.apache.log4j.Logger;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.utils.io.DirectoryScanner;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.apache.maven.toolchain.ToolchainPrivate;
import org.apache.maven.toolchain.java.JavaToolChain;
import org.arakhne.afc.vmutil.locale.Locale;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.xtext.xbase.lib.util.ReflectExtensions;

import io.sarl.lang.SARLStandaloneSetup;
import io.sarl.lang.compiler.batch.SarlBatchCompiler;
import io.sarl.maven.compiler.MavenLogger.MavenLoggerFactory;

/** Abstract mojo that is able to use the SARL batch compiler.
 *
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 */
public abstract class AbstractSarlBatchCompilerMojo extends AbstractSarlMojo {

    private Injector injector;

    private Provider<SarlBatchCompiler> sarlBatchCompilerProvider;

    private ReflectExtensions reflect;

    @Component
    private ToolchainManager toolchainManager;

    @Parameter(readonly = true, defaultValue = "${basedir}/.settings/io.sarl.lang.SARL.prefs")
    private String propertiesFileLocation;

    @Override
    public void prepareExecution() throws MojoExecutionException {
        if (this.injector == null) {
            this.injector = SARLStandaloneSetup.doSetup();
        }
        if (this.sarlBatchCompilerProvider == null) {
            this.sarlBatchCompilerProvider = this.injector.getProvider(SarlBatchCompiler.class);
        }
        if (this.reflect == null) {
            this.reflect = this.injector.getInstance(ReflectExtensions.class);
        }
        if (this.sarlBatchCompilerProvider == null || this.reflect == null) {
            throw new MojoExecutionException(
                    Locale.getString(AbstractSarlBatchCompilerMojo.class, "INJECTION_ERROR")); //$NON-NLS-1$
        }
    }

    /** Replies the batch compiler for SARL.
     *
     * @return the batch compiler.
     */
    protected SarlBatchCompiler getBatchCompiler() {
        return this.sarlBatchCompilerProvider.get();
    }

    /** Replies the current project.
     *
     * @return the current project.
     */
    protected MavenProject getProject() {
        return this.mavenHelper.getSession().getCurrentProject();
    }

    /** Replies the version of the source.
     *
     * @return the source version.
     */
    protected abstract String getSourceVersion();

    /** Replies the encoding of the source.
     *
     * @return the encoding.
     */
    protected abstract String getEncoding();

    /** Replies if the Java compiler must be called at post-running stage.
     *
     * @return <code>true</code> for running the java compiler.
     */
    protected abstract boolean getPostRunningOfJavaCompiler();

    /** Replies if the inline annotations must be generated by the SARL compiler.
     *
     * @return <code>true</code> for generating the inline annotations.
     */
    protected abstract boolean getGenerateInlines();

    /** Replies if the trace files must be generated by the SARL compiler.
     *
     * @return <code>true</code> for generating the trace files.
     */
    protected abstract boolean getGenerateTraceFiles();

    /** Replies if the storage files must be generated by the SARL compiler.
     *
     * @return <code>true</code> for generating the storage files.
     */
    protected abstract boolean getGenerateStorageFiles();

    /** Run compilation.
     *
     * @param classPath the classpath
     * @param sourcePaths the source paths.
     * @param outputPath the output path.
     * @throws MojoExecutionException if error.
     * @throws MojoFailureException if failure.
     */
    protected void compile(List<File> classPath, List<File> sourcePaths, File outputPath)
            throws MojoExecutionException, MojoFailureException {
        final SarlBatchCompiler compiler = getBatchCompiler();
        final MavenProject project = getProject();
        compiler.setResourceSetProvider(new MavenProjectResourceSetProvider(project));
        final Iterable<File> filtered = Iterables.filter(sourcePaths, (input) -> input.isDirectory());
        if (Iterables.isEmpty(filtered)) {
            final String dir = Iterables.toString(sourcePaths);
            getLog().info(Locale.getString(AbstractSarlBatchCompilerMojo.class, "ERROR_0", dir)); //$NON-NLS-1$
            return;
        }
        final String baseDir = project.getBasedir().getAbsolutePath();
        compiler.setJavaPostCompilationEnable(getPostRunningOfJavaCompiler());
        compiler.setClassOutputPath(makeAbsolute(new File(getProject().getBuild().getOutputDirectory())));
        compiler.setJavaSourceVersion(getSourceVersion());
        compiler.setBasePath(baseDir);
        compiler.setTempDirectory(getTempDirectory());
        compiler.setDeleteTempDirectory(false);
        compiler.setClassPath(classPath);
        final String bootClassPath = getBootClassPath();
        compiler.setBootClassPath(bootClassPath);
        final List<File> filteredSourcePaths = Lists.newArrayList(filtered);
        compiler.setSourcePath(filteredSourcePaths);
        compiler.setOutputPath(outputPath);
        compiler.setFileEncoding(getEncoding());
        compiler.setWriteTraceFiles(getGenerateTraceFiles());
        compiler.setWriteStorageFiles(getGenerateStorageFiles());
        compiler.setGenerateInlineAnnotation(getGenerateInlines());
        final Logger logger = Logger.getLogger(getClass().getName(), new MavenLoggerFactory(getLog()));
        compiler.setLogger(logger);
        compiler.setIssueMessageFormatter((issue, uriToProblem) -> {
            final String filename;
            if (uriToProblem != null) {
                filename = uriToProblem.toFileString();
            } else {
                filename = Locale.getString(AbstractSarlBatchCompilerMojo.class, "NO_FILE_NAME"); //$NON-NLS-1$
            }
            return Locale.getString(AbstractSarlBatchCompilerMojo.class, "ISSUE_MESSAGE", //$NON-NLS-1$
                    filename, issue.getLineNumber(), issue.getColumn(), issue.getMessage());
        });
        if (!compiler.compile()) {
            final StringBuilder dir = new StringBuilder();
            for (final File file : filtered) {
                if (dir.length() > 0) {
                    dir.append(File.pathSeparator);
                }
                dir.append(file.getAbsolutePath());
            }
            throw new MojoFailureException(Locale.getString(AbstractSarlBatchCompilerMojo.class, "ERROR_1")); //$NON-NLS-1$
        }
    }

    private String getBootClassPath() throws MojoExecutionException {
        final Toolchain toolchain = this.toolchainManager.getToolchainFromBuildContext("jdk", //$NON-NLS-1$
                this.mavenHelper.getSession());
        if (toolchain instanceof JavaToolChain && toolchain instanceof ToolchainPrivate) {
            final JavaToolChain javaToolChain = (JavaToolChain) toolchain;
            final ToolchainPrivate privateJavaToolChain = (ToolchainPrivate) toolchain;
            getLog().info(Locale.getString(AbstractSarlBatchCompilerMojo.class, "USING_TOOLCHAIN", javaToolChain)); //$NON-NLS-1$

            String[] includes = { "jre/lib/*", "jre/lib/ext/*", "jre/lib/endorsed/*" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            String[] excludes = new String[0];
            final Xpp3Dom config = (Xpp3Dom) privateJavaToolChain.getModel().getConfiguration();
            if (config != null) {
                final Xpp3Dom bootClassPath = config.getChild("bootClassPath"); //$NON-NLS-1$
                if (bootClassPath != null) {
                    final Xpp3Dom includeParent = bootClassPath.getChild("includes"); //$NON-NLS-1$
                    if (includeParent != null) {
                        includes = getValues(includeParent.getChildren("include")); //$NON-NLS-1$
                    }
                    final Xpp3Dom excludeParent = bootClassPath.getChild("excludes"); //$NON-NLS-1$
                    if (excludeParent != null) {
                        excludes = getValues(excludeParent.getChildren("exclude")); //$NON-NLS-1$
                    }
                }
            }

            try {
                return scanBootclasspath(Objects.toString(this.reflect.invoke(javaToolChain, "getJavaHome")), //$NON-NLS-1$
                        includes, excludes);
            } catch (Exception e) {
                throw new MojoExecutionException(e.getLocalizedMessage(), e);
            }
        }
        return ""; //$NON-NLS-1$
    }

    private String scanBootclasspath(String javaHome, String[] includes, String[] excludes) {
        getLog().debug(Locale.getString(AbstractSarlBatchCompilerMojo.class, "BOOTCLASSPATH", //$NON-NLS-1$
                javaHome, Arrays.toString(includes), Arrays.toString(excludes)));
        final DirectoryScanner scanner = new DirectoryScanner();
        scanner.setBasedir(new File(javaHome));
        scanner.setIncludes(includes);
        scanner.setExcludes(excludes);
        scanner.scan();

        final StringBuilder bootClassPath = new StringBuilder();
        final 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 static String[] getValues(Xpp3Dom[] children) {
        final String[] values = new String[children.length];
        for (int i = 0; i < values.length; i++) {
            values[i] = children[i].getValue();
        }
        return values;
    }

    /** Replies temporary directory.
     *
     * @return the temporary directory.
     */
    protected abstract File getTempDirectory();

    /** Read the SARL Eclipse settings for the project if existing.
     *
     * @param sourceDirectory the source directory.
     * @return the path from the settings.
     */
    protected String readSarlEclipseSetting(String sourceDirectory) {
        if (this.propertiesFileLocation != null) {
            final File file = new File(this.propertiesFileLocation);
            if (file.canRead()) {
                final Properties sarlSettings = new Properties();
                try (FileInputStream stream = new FileInputStream(file)) {
                    sarlSettings.load(stream);
                    // TODO read SARL setup to compute the properties file loc and property name
                    final String sarlOutputDirProp = sarlSettings.getProperty("outlet.DEFAULT_OUTPUT.directory", //$NON-NLS-1$
                            null);
                    if (sarlOutputDirProp != null) {
                        final File srcDir = new File(sourceDirectory);
                        getLog().debug(Locale.getString(AbstractSarlBatchCompilerMojo.class, "SOURCE_DIR", //$NON-NLS-1$
                                srcDir.getPath(), srcDir.exists()));
                        if (srcDir.exists() && srcDir.getParent() != null) {
                            final String path = new File(srcDir.getParent(), sarlOutputDirProp).getPath();
                            getLog().debug(Locale.getString(AbstractSarlBatchCompilerMojo.class, "APPLY_PROPERTY", //$NON-NLS-1$
                                    sarlOutputDirProp));
                            return path;
                        }
                    }
                } catch (FileNotFoundException e) {
                    getLog().warn(e);
                } catch (IOException e) {
                    getLog().warn(e);
                }
            } else {
                getLog().debug(Locale.getString(AbstractSarlBatchCompilerMojo.class, "ERROR_2", //$NON-NLS-1$
                        this.propertiesFileLocation));
            }
        }
        return null;
    }

    /** Replies the current classpath.
     *
     * @return the current classpath.
     * @throws MojoExecutionException on failure.
     */
    protected List<File> getClassPath() throws MojoExecutionException {
        final Set<String> classPath = new LinkedHashSet<>();
        final MavenProject project = getProject();
        classPath.add(project.getBuild().getSourceDirectory());
        try {
            classPath.addAll(project.getCompileClasspathElements());
        } catch (DependencyResolutionRequiredException e) {
            throw new MojoExecutionException(e.getLocalizedMessage(), e);
        }
        for (final Artifact dep : project.getArtifacts()) {
            classPath.add(dep.getFile().getAbsolutePath());
        }
        classPath.remove(project.getBuild().getOutputDirectory());
        final List<File> files = new ArrayList<>();
        for (final String filename : classPath) {
            final File file = new File(filename);
            if (file.exists()) {
                files.add(file);
            } else {
                getLog().warn(Locale.getString(AbstractSarlBatchCompilerMojo.class, "ERROR_3", filename)); //$NON-NLS-1$
            }
        }
        return files;
    }

}