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

Java tutorial

Introduction

Here is the source code for io.sarl.maven.compiler.CompileMojo.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.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import com.google.common.base.Strings;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.arakhne.afc.vmutil.locale.Locale;

import io.sarl.lang.SARLVersion;

/** Mojo for compiling SARL.
 *
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 */
@Mojo(name = "compile", defaultPhase = LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.COMPILE)
public class CompileMojo extends AbstractSarlBatchCompilerMojo {

    private static final String STUB_FOLDER = "sarl-temp"; //$NON-NLS-1$

    /** Version of the Java specification used for the source files.
     */
    @Parameter(defaultValue = SARLVersion.MINIMAL_JDK_VERSION, required = false)
    private String source;

    /** Encoding.
     */
    @Parameter(required = false)
    private String encoding;

    /**
     * Location of the temporary compiler directory.
     */
    @Parameter
    private File tempDirectory;

    /** Indicates if the Java compiler must be invoked by the SARL maven plugin.
     */
    @Parameter(defaultValue = "true", required = false)
    private boolean runJavaCompiler;

    /** Indicates if the inline annotations must be generated by the SARL maven plugin.
     */
    @Parameter(defaultValue = "true", required = false)
    private boolean generateInlines;

    /** Indicates if the trace files should be generated.
     */
    @Parameter(defaultValue = "true", required = false)
    private boolean generateTraceFiles;

    /** Indicates if the storage files should be generated.
     */
    @Parameter(defaultValue = "true", required = false)
    private boolean generateStorageFiles;

    /** Indicates if the classpath is provided by Tycho.
     */
    @Parameter(defaultValue = "false", required = false)
    private boolean tycho;

    @Override
    protected String getSourceVersion() {
        return this.source;
    }

    @Override
    protected String getEncoding() {
        return this.encoding == null || this.encoding.isEmpty() ? Charset.defaultCharset().displayName()
                : this.encoding;
    }

    @Override
    protected File getTempDirectory() {
        if (this.tempDirectory == null) {
            final File targetDir = new File(getProject().getBuild().getDirectory());
            return makeAbsolute(new File(targetDir, STUB_FOLDER));
        }
        return makeAbsolute(this.tempDirectory);
    }

    @Override
    protected boolean getPostRunningOfJavaCompiler() {
        return this.runJavaCompiler;
    }

    @Override
    protected boolean getGenerateInlines() {
        return this.generateInlines;
    }

    @Override
    protected boolean getGenerateTraceFiles() {
        return this.generateTraceFiles;
    }

    @Override
    protected boolean getGenerateStorageFiles() {
        return this.generateStorageFiles;
    }

    @Override
    protected void buildPropertyString(StringBuilder buffer) {
        super.buildPropertyString(buffer);
        buffer.append("source = ").append(this.source).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
        buffer.append("encoding = ").append(this.encoding).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
        buffer.append("tempDirectory = ").append(this.tempDirectory).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
        buffer.append("runJavaCompiler = ").append(this.runJavaCompiler).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
        buffer.append("generateInlines = ").append(this.generateInlines).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
        buffer.append("generateTraceFiles = ").append(this.generateTraceFiles).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
        buffer.append("generateStorageFiles = ").append(this.generateStorageFiles).append("\n"); //$NON-NLS-1$//$NON-NLS-2$
    }

    @Override
    protected void ensureDefaultParameterValues() {
        super.ensureDefaultParameterValues();
        if (Strings.isNullOrEmpty(this.encoding)) {
            final Properties properties = this.mavenHelper.getSession().getCurrentProject().getProperties();
            this.encoding = properties.getProperty("project.build.sourceEncoding", null); //$NON-NLS-1$
            if (Strings.isNullOrEmpty(this.encoding)) {
                this.encoding = Charset.defaultCharset().name();
            }
        }
    }

    @Override
    protected void executeMojo() throws MojoExecutionException, MojoFailureException {
        ensureSARLVersions();
        validateDependencyVersions();
        compileSARL();
    }

    @SuppressWarnings("unchecked")
    private static boolean containsVersion(ArtifactVersion version, ArtifactVersion rangeMin,
            ArtifactVersion rangeMax) {
        return (version.compareTo(rangeMin) >= 0) && (version.compareTo(rangeMax) < 0);
    }

    private void ensureSARLVersions() throws MojoExecutionException, MojoFailureException {
        final String compilerVersionString = this.mavenHelper.getConfig("plugin.version"); //$NON-NLS-1$
        final ArtifactVersion compilerVersion = new DefaultArtifactVersion(compilerVersionString);
        final ArtifactVersion maxCompilerVersion = new DefaultArtifactVersion(
                compilerVersion.getMajorVersion() + "." //$NON-NLS-1$
                        + (compilerVersion.getMinorVersion() + 1) + ".0"); //$NON-NLS-1$
        getLog().info(Locale.getString(CompileMojo.class, "CHECK_SARL_SDK", compilerVersionString, //$NON-NLS-1$
                maxCompilerVersion));
        final StringBuilder classpath = new StringBuilder();
        final Set<String> foundVersions = findSARLLibrary(compilerVersion, maxCompilerVersion, classpath,
                this.tycho);
        if (foundVersions.isEmpty()) {
            throw new MojoFailureException(Locale.getString(CompileMojo.class, "NO_SARL_LIBRARY", //$NON-NLS-1$
                    classpath.toString()));
        }
        final StringBuilder versions = new StringBuilder();
        for (final String version : foundVersions) {
            if (versions.length() > 0) {
                versions.append(", "); //$NON-NLS-1$
            }
            versions.append(version);
        }
        if (foundVersions.size() > 1) {
            getLog().info(Locale.getString(CompileMojo.class, "TOO_MUCH_SARL_VERSIONS", versions)); //$NON-NLS-1$
        } else {
            getLog().info(Locale.getString(CompileMojo.class, "DETECTED_SARL_VERSION", versions)); //$NON-NLS-1$
        }
    }

    private Set<String> findSARLLibrary(ArtifactVersion compilerVersion, ArtifactVersion maxCompilerVersion,
            StringBuilder classpath, boolean enableTycho) throws MojoExecutionException, MojoFailureException {
        final String sarlLibGroupId = this.mavenHelper.getConfig("sarl-lib.groupId"); //$NON-NLS-1$
        final String sarlLibArtifactId = this.mavenHelper.getConfig("sarl-lib.artifactId"); //$NON-NLS-1$
        final String sarlLibGroupIdTycho = "p2.eclipse-plugin"; //$NON-NLS-1$
        final String sarlLibArtifactIdTycho = this.mavenHelper.getConfig("sarl-lib.osgiBundleId"); //$NON-NLS-1$
        final Set<String> foundVersions = new TreeSet<>();
        for (final Artifact dep : this.mavenHelper.getSession().getCurrentProject().getArtifacts()) {
            getLog().debug(Locale.getString(CompileMojo.class, "SCANNING_DEPENDENCY", //$NON-NLS-1$
                    dep.getGroupId(), dep.getArtifactId(), dep.getVersion()));
            if (classpath.length() > 0) {
                classpath.append(":"); //$NON-NLS-1$
            }
            classpath.append(ArtifactUtils.versionlessKey(dep));
            String gid = null;
            String aid = null;
            if (sarlLibGroupId.equals(dep.getGroupId()) && sarlLibArtifactId.equals(dep.getArtifactId())) {
                gid = sarlLibGroupId;
                aid = sarlLibArtifactId;
            } else if (enableTycho && sarlLibGroupIdTycho.equals(dep.getGroupId())
                    && sarlLibArtifactIdTycho.equals(dep.getArtifactId())) {
                gid = sarlLibGroupIdTycho;
                aid = sarlLibArtifactIdTycho;
            }
            if (gid != null && aid != null) {
                final ArtifactVersion dependencyVersion = new DefaultArtifactVersion(dep.getVersion());
                if (!containsVersion(dependencyVersion, compilerVersion, maxCompilerVersion)) {
                    final String shortMessage = Locale.getString(CompileMojo.class, "INCOMPATIBLE_VERSION_SHORT", //$NON-NLS-1$
                            gid, aid, dependencyVersion.toString(), compilerVersion.toString(),
                            maxCompilerVersion.toString());
                    final String longMessage = Locale.getString(CompileMojo.class, "INCOMPATIBLE_VERSION_LONG", //$NON-NLS-1$
                            sarlLibGroupId, sarlLibArtifactId, dependencyVersion.toString(),
                            compilerVersion.toString(), maxCompilerVersion.toString());
                    throw new MojoFailureException(this, shortMessage, longMessage);
                }
                foundVersions.add(dep.getVersion());
            }
        }
        return foundVersions;
    }

    @SuppressWarnings("unchecked")
    private void validateDependencyVersions() throws MojoExecutionException, MojoFailureException {
        getLog().info(Locale.getString(CompileMojo.class, "CHECK_DEPENDENCY_VERSIONS")); //$NON-NLS-1$
        final String sarlSdkGroupId = this.mavenHelper.getConfig("sarl-sdk.groupId"); //$NON-NLS-1$
        final String sarlSdkArtifactId = this.mavenHelper.getConfig("sarl-sdk.artifactId"); //$NON-NLS-1$

        boolean hasError = false;

        final Map<String, Artifact> artifacts = this.mavenHelper.getSession().getCurrentProject().getArtifactMap();
        final String sdkArtifactKey = ArtifactUtils.versionlessKey(sarlSdkGroupId, sarlSdkArtifactId);
        final Artifact sdkArtifact = artifacts.get(sdkArtifactKey);
        if (sdkArtifact != null) {
            final Map<String, ArtifactVersion> versions = new TreeMap<>();
            final Set<Artifact> dependencies = this.mavenHelper.resolveDependencies(sdkArtifactKey, false);
            for (final Artifact dependency : dependencies) {
                final ArtifactVersion dependencyVersion = new DefaultArtifactVersion(dependency.getVersion());
                final String dependencyKey = ArtifactUtils.versionlessKey(dependency);
                final ArtifactVersion currentVersion = versions.get(dependencyKey);
                if (currentVersion == null || dependencyVersion.compareTo(currentVersion) > 0) {
                    versions.put(dependencyKey, dependencyVersion);
                }
            }

            for (final Entry<String, ArtifactVersion> entry : versions.entrySet()) {
                final Artifact dependencyArtifact = artifacts.get(entry.getKey());
                if (dependencyArtifact != null) {
                    final ArtifactVersion dependencyVersion = new DefaultArtifactVersion(
                            dependencyArtifact.getVersion());
                    if (entry.getValue().compareTo(dependencyVersion) > 0) {
                        final String message = Locale.getString(CompileMojo.class,
                                "INVALID_SARL_SDK_DEPENDENCY_VERSION", //$NON-NLS-1$
                                dependencyArtifact.getGroupId(), dependencyArtifact.getArtifactId(),
                                dependencyArtifact.getVersion(), entry.getValue().toString());
                        getLog().error(message);
                        hasError = true;
                    }
                }
            }
        }

        if (hasError) {
            throw new MojoFailureException(
                    Locale.getString(CompileMojo.class, "INVALID_SARL_SDK_DEPENDENCY_VERSION_TITLE")); //$NON-NLS-1$
        }
    }

    private void compileSARL() throws MojoExecutionException, MojoFailureException {
        final Log log = getLog();
        File outputDirectory = getOutput();
        log.info(Locale.getString(CompileMojo.class, "COMPILING_SARL")); //$NON-NLS-1$
        if (log.isDebugEnabled()) {
            final StringBuilder properties = new StringBuilder();
            buildPropertyString(properties);
            log.debug(properties.toString());
        }
        // If output is not explicitly set try to read SARL prefs from eclipse .settings folder
        if (getDefaultOutput().equals(getOutput())) {
            final String settingsValue = readSarlEclipseSetting(getProject().getBuild().getSourceDirectory());
            if (settingsValue != null && !settingsValue.isEmpty()) {
                outputDirectory = new File(settingsValue);
                getLog().info(Locale.getString(CompileMojo.class, "OUTPUT_DIR_UPDATE", outputDirectory)); //$NON-NLS-1$
            }
        }
        final MavenProject project = getProject();
        final List<File> compileSourceRoots = new ArrayList<>();
        for (final String filename : project.getCompileSourceRoots()) {
            final File file = new File(filename);
            if (!file.equals(outputDirectory)) {
                compileSourceRoots.add(file);
            }
        }
        final List<File> classPath = getClassPath();
        project.addCompileSourceRoot(outputDirectory.getAbsolutePath());
        compile(classPath, compileSourceRoots, outputDirectory);
    }

}