All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.plugin.compiler.TestCompilerMojo Maven / Gradle / Ivy

There is a newer version: 4.0.0-beta-1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.maven.plugin.compiler;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.maven.plugin.MojoExecutionException;
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.shared.utils.StringUtils;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.java.DefaultJavaToolChain;
import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
import org.codehaus.plexus.languages.java.jpms.LocationManager;
import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;

/**
 * Compiles application test sources.
 *
 * @author Jason van Zyl
 * @since 2.0
 */
@Mojo(
        name = "testCompile",
        defaultPhase = LifecyclePhase.TEST_COMPILE,
        threadSafe = true,
        requiresDependencyResolution = ResolutionScope.TEST)
public class TestCompilerMojo extends AbstractCompilerMojo {
    /**
     * Set this to 'true' to bypass compilation of test sources.
     * Its use is NOT RECOMMENDED, but quite convenient on occasion.
     */
    @Parameter(property = "maven.test.skip")
    private boolean skip;

    /**
     * The source directories containing the test-source to be compiled.
     */
    @Parameter(defaultValue = "${project.testCompileSourceRoots}", readonly = true, required = true)
    private List compileSourceRoots;

    /**
     * The directory where compiled test classes go.
     */
    @Parameter(defaultValue = "${project.build.testOutputDirectory}", required = true, readonly = true)
    private File outputDirectory;

    /**
     * A list of inclusion filters for the compiler.
     */
    @Parameter
    private Set testIncludes = new HashSet<>();

    /**
     * A list of exclusion filters for the compiler.
     */
    @Parameter
    private Set testExcludes = new HashSet<>();

    /**
     * A list of exclusion filters for the incremental calculation.
     * @since 3.11
     */
    @Parameter
    private Set testIncrementalExcludes = new HashSet<>();

    /**
     * The -source argument for the test Java compiler.
     *
     * @since 2.1
     */
    @Parameter(property = "maven.compiler.testSource")
    private String testSource;

    /**
     * The -target argument for the test Java compiler.
     *
     * @since 2.1
     */
    @Parameter(property = "maven.compiler.testTarget")
    private String testTarget;

    /**
     * the -release argument for the test Java compiler
     *
     * @since 3.6
     */
    @Parameter(property = "maven.compiler.testRelease")
    private String testRelease;

    /**
     * 

* Sets the arguments to be passed to test compiler (prepending a dash) if fork is set to true. *

*

* This is because the list of valid arguments passed to a Java compiler * varies based on the compiler version. *

* * @since 2.1 */ @Parameter private Map testCompilerArguments; /** *

* Sets the unformatted argument string to be passed to test compiler if fork is set to true. *

*

* This is because the list of valid arguments passed to a Java compiler * varies based on the compiler version. *

* * @since 2.1 */ @Parameter private String testCompilerArgument; /** *

* Specify where to place generated source files created by annotation processing. * Only applies to JDK 1.6+ *

* * @since 2.2 */ @Parameter(defaultValue = "${project.build.directory}/generated-test-sources/test-annotations") private File generatedTestSourcesDirectory; /** *

* When {@code true}, uses the module path when compiling with a release or target of 9+ and * module-info.java or module-info.class is present. * When {@code false}, always uses the class path. *

* * @since 3.11 */ @Parameter(defaultValue = "true") private boolean useModulePath; @Parameter(defaultValue = "${project.testClasspathElements}", readonly = true) private List testPath; /** * when forking and debug activated the commandline used will be dumped in this file * @since 3.10.0 */ @Parameter(defaultValue = "javac-test") private String debugFileName; final LocationManager locationManager = new LocationManager(); private Map pathElements; private Collection classpathElements; private Collection modulepathElements; public void execute() throws MojoExecutionException, CompilationFailureException { if (skip) { getLog().info("Not compiling test sources"); return; } super.execute(); } protected List getCompileSourceRoots() { return compileSourceRoots; } @Override protected Map getPathElements() { return pathElements; } protected List getClasspathElements() { return new ArrayList<>(classpathElements); } @Override protected List getModulepathElements() { return new ArrayList<>(modulepathElements); } protected File getOutputDirectory() { return outputDirectory; } @Override protected void preparePaths(Set sourceFiles) { File mainOutputDirectory = new File(getProject().getBuild().getOutputDirectory()); File mainModuleDescriptorClassFile = new File(mainOutputDirectory, "module-info.class"); JavaModuleDescriptor mainModuleDescriptor = null; File testModuleDescriptorJavaFile = new File("module-info.java"); JavaModuleDescriptor testModuleDescriptor = null; // Go through the source files to respect includes/excludes for (File sourceFile : sourceFiles) { // @todo verify if it is the root of a sourcedirectory? if ("module-info.java".equals(sourceFile.getName())) { testModuleDescriptorJavaFile = sourceFile; break; } } // Get additional information from the main module descriptor, if available if (mainModuleDescriptorClassFile.exists()) { ResolvePathsResult result; try { ResolvePathsRequest request = ResolvePathsRequest.ofStrings(testPath) .setIncludeStatic(true) .setMainModuleDescriptor(mainModuleDescriptorClassFile.getAbsolutePath()); Toolchain toolchain = getToolchain(); if (toolchain instanceof DefaultJavaToolChain) { request.setJdkHome(((DefaultJavaToolChain) toolchain).getJavaHome()); } result = locationManager.resolvePaths(request); for (Entry pathException : result.getPathExceptions().entrySet()) { Throwable cause = pathException.getValue(); while (cause.getCause() != null) { cause = cause.getCause(); } String fileName = Paths.get(pathException.getKey()).getFileName().toString(); getLog().warn("Can't extract module name from " + fileName + ": " + cause.getMessage()); } } catch (IOException e) { throw new RuntimeException(e); } mainModuleDescriptor = result.getMainModuleDescriptor(); pathElements = new LinkedHashMap<>(result.getPathElements().size()); pathElements.putAll(result.getPathElements()); modulepathElements = result.getModulepathElements().keySet(); classpathElements = result.getClasspathElements(); } // Get additional information from the test module descriptor, if available if (testModuleDescriptorJavaFile.exists()) { ResolvePathsResult result; try { ResolvePathsRequest request = ResolvePathsRequest.ofStrings(testPath) .setMainModuleDescriptor(testModuleDescriptorJavaFile.getAbsolutePath()); Toolchain toolchain = getToolchain(); if (toolchain instanceof DefaultJavaToolChain) { request.setJdkHome(((DefaultJavaToolChain) toolchain).getJavaHome()); } result = locationManager.resolvePaths(request); } catch (IOException e) { throw new RuntimeException(e); } testModuleDescriptor = result.getMainModuleDescriptor(); } if (!useModulePath) { pathElements = Collections.emptyMap(); modulepathElements = Collections.emptyList(); classpathElements = testPath; return; } if (StringUtils.isNotEmpty(getRelease())) { if (Integer.parseInt(getRelease()) < 9) { pathElements = Collections.emptyMap(); modulepathElements = Collections.emptyList(); classpathElements = testPath; return; } } else if (Double.parseDouble(getTarget()) < Double.parseDouble(MODULE_INFO_TARGET)) { pathElements = Collections.emptyMap(); modulepathElements = Collections.emptyList(); classpathElements = testPath; return; } if (testModuleDescriptor != null) { modulepathElements = testPath; classpathElements = Collections.emptyList(); if (mainModuleDescriptor != null) { if (getLog().isDebugEnabled()) { getLog().debug("Main and test module descriptors exist:"); getLog().debug(" main module = " + mainModuleDescriptor.name()); getLog().debug(" test module = " + testModuleDescriptor.name()); } if (testModuleDescriptor.name().equals(mainModuleDescriptor.name())) { if (compilerArgs == null) { compilerArgs = new ArrayList<>(); } compilerArgs.add("--patch-module"); StringBuilder patchModuleValue = new StringBuilder(); patchModuleValue.append(testModuleDescriptor.name()); patchModuleValue.append('='); for (String root : getProject().getCompileSourceRoots()) { if (Files.exists(Paths.get(root))) { patchModuleValue.append(root).append(PS); } } compilerArgs.add(patchModuleValue.toString()); } else { getLog().debug("Black-box testing - all is ready to compile"); } } else { // No main binaries available? Means we're a test-only project. if (!mainOutputDirectory.exists()) { return; } // very odd // Means that main sources must be compiled with -modulesource and -Xmodule: // However, this has a huge impact since you can't simply use it as a classpathEntry // due to extra folder in between throw new UnsupportedOperationException( "Can't compile test sources " + "when main sources are missing a module descriptor"); } } else { if (mainModuleDescriptor != null) { if (compilerArgs == null) { compilerArgs = new ArrayList<>(); } compilerArgs.add("--patch-module"); StringBuilder patchModuleValue = new StringBuilder(mainModuleDescriptor.name()) .append('=') .append(mainOutputDirectory) .append(PS); for (String root : compileSourceRoots) { patchModuleValue.append(root).append(PS); } compilerArgs.add(patchModuleValue.toString()); compilerArgs.add("--add-reads"); compilerArgs.add(mainModuleDescriptor.name() + "=ALL-UNNAMED"); } else { modulepathElements = Collections.emptyList(); classpathElements = testPath; } } } protected SourceInclusionScanner getSourceInclusionScanner(int staleMillis) { SourceInclusionScanner scanner; if (testIncludes.isEmpty() && testExcludes.isEmpty() && testIncrementalExcludes.isEmpty()) { scanner = new StaleSourceScanner(staleMillis); } else { if (testIncludes.isEmpty()) { testIncludes.add("**/*.java"); } Set excludesIncr = new HashSet<>(testExcludes); excludesIncr.addAll(this.testIncrementalExcludes); scanner = new StaleSourceScanner(staleMillis, testIncludes, excludesIncr); } return scanner; } protected SourceInclusionScanner getSourceInclusionScanner(String inputFileEnding) { SourceInclusionScanner scanner; // it's not defined if we get the ending with or without the dot '.' String defaultIncludePattern = "**/*" + (inputFileEnding.startsWith(".") ? "" : ".") + inputFileEnding; if (testIncludes.isEmpty() && testExcludes.isEmpty() && testIncrementalExcludes.isEmpty()) { testIncludes = Collections.singleton(defaultIncludePattern); scanner = new SimpleSourceInclusionScanner(testIncludes, Collections.emptySet()); } else { if (testIncludes.isEmpty()) { testIncludes.add(defaultIncludePattern); } Set excludesIncr = new HashSet<>(testExcludes); excludesIncr.addAll(this.testIncrementalExcludes); scanner = new SimpleSourceInclusionScanner(testIncludes, excludesIncr); } return scanner; } protected String getSource() { return testSource == null ? source : testSource; } protected String getTarget() { return testTarget == null ? target : testTarget; } @Override protected String getRelease() { return testRelease == null ? release : testRelease; } protected String getCompilerArgument() { return testCompilerArgument == null ? compilerArgument : testCompilerArgument; } protected Map getCompilerArguments() { return testCompilerArguments == null ? compilerArguments : testCompilerArguments; } protected File getGeneratedSourcesDirectory() { return generatedTestSourcesDirectory; } @Override protected String getDebugFileName() { return debugFileName; } @Override protected boolean isTestCompile() { return true; } @Override protected Set getIncludes() { return testIncludes; } @Override protected Set getExcludes() { return testExcludes; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy