diff --git a/src/it/MCOMPILER-374_mrjar/invoker.properties b/src/it/MCOMPILER-374_mrjar/invoker.properties
new file mode 100644
index 000000000..4b2641284
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.java.version = 11+
diff --git a/src/it/MCOMPILER-374_mrjar/pom.xml b/src/it/MCOMPILER-374_mrjar/pom.xml
new file mode 100644
index 000000000..3cb9cfd8f
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+ 4.0.0
+
+ org.maven.bug
+ mcompiler374
+ 1.0-SNAPSHOT
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ @project.version@
+
+ 8
+ 11
+
+
+
+ java9
+ compile
+
+ compile
+
+
+ 9
+
+ ${project.basedir}/src/main/java9
+
+ true
+
+
+
+ java11
+ compile
+
+ compile
+
+
+ 11
+
+ ${project.basedir}/src/main/java11
+
+ true
+
+
+
+
+
+
+
diff --git a/src/it/MCOMPILER-374_mrjar/src/main/java/org/maven/bug/A.java b/src/it/MCOMPILER-374_mrjar/src/main/java/org/maven/bug/A.java
new file mode 100644
index 000000000..7360b4a51
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/main/java/org/maven/bug/A.java
@@ -0,0 +1,25 @@
+/*
+ * 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.maven.bug;
+
+public class A {
+ static int getCount() {
+ return 1;
+ }
+}
diff --git a/src/it/MCOMPILER-374_mrjar/src/main/java/org/maven/bug/B.java b/src/it/MCOMPILER-374_mrjar/src/main/java/org/maven/bug/B.java
new file mode 100644
index 000000000..aec29939d
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/main/java/org/maven/bug/B.java
@@ -0,0 +1,25 @@
+/*
+ * 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.maven.bug;
+
+public class B {
+ static int getCount() {
+ return A.getCount() + 1;
+ }
+}
diff --git a/src/it/MCOMPILER-374_mrjar/src/main/java11/module-info.java b/src/it/MCOMPILER-374_mrjar/src/main/java11/module-info.java
new file mode 100644
index 000000000..b8dbb6c29
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/main/java11/module-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+module mrjar {
+ exports org.maven.bug;
+}
diff --git a/src/it/MCOMPILER-374_mrjar/src/main/java11/org/maven/bug/B.java b/src/it/MCOMPILER-374_mrjar/src/main/java11/org/maven/bug/B.java
new file mode 100644
index 000000000..94356bc9b
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/main/java11/org/maven/bug/B.java
@@ -0,0 +1,29 @@
+/*
+ * 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.maven.bug;
+
+public class B {
+ static int getCount() {
+ return A9.getCount() + 2;
+ }
+
+ static int getVersion() {
+ return 11;
+ }
+}
diff --git a/src/it/MCOMPILER-374_mrjar/src/main/java9/org/maven/bug/A9.java b/src/it/MCOMPILER-374_mrjar/src/main/java9/org/maven/bug/A9.java
new file mode 100644
index 000000000..4b56281d3
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/main/java9/org/maven/bug/A9.java
@@ -0,0 +1,25 @@
+/*
+ * 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.maven.bug;
+
+public class A9 {
+ static int getCount() {
+ return A.getCount() + 1;
+ }
+}
diff --git a/src/it/MCOMPILER-374_mrjar/src/main/java9/org/maven/bug/B.java b/src/it/MCOMPILER-374_mrjar/src/main/java9/org/maven/bug/B.java
new file mode 100644
index 000000000..1e54a47e0
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/main/java9/org/maven/bug/B.java
@@ -0,0 +1,25 @@
+/*
+ * 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.maven.bug;
+
+public class B {
+ static int getCount() {
+ return A9.getCount() + 1;
+ }
+}
diff --git a/src/it/MCOMPILER-374_mrjar/src/test/java/org/maven/bug/MrJarTest.java b/src/it/MCOMPILER-374_mrjar/src/test/java/org/maven/bug/MrJarTest.java
new file mode 100644
index 000000000..7e7bceb3e
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/src/test/java/org/maven/bug/MrJarTest.java
@@ -0,0 +1,25 @@
+/*
+ * 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.maven.bug;
+
+class MrJarTest {
+ static int getCount() {
+ return A.getCount() + A9.getCount() + B.getVersion();
+ }
+}
diff --git a/src/it/MCOMPILER-374_mrjar/verify.groovy b/src/it/MCOMPILER-374_mrjar/verify.groovy
new file mode 100644
index 000000000..1f5c7beb6
--- /dev/null
+++ b/src/it/MCOMPILER-374_mrjar/verify.groovy
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+assert new File(basedir, 'target/classes/org/maven/bug/A.class').exists()
+assert new File(basedir, 'target/classes/org/maven/bug/B.class').exists()
+assert new File(basedir, 'target/classes/META-INF/versions/9/org/maven/bug/A9.class').exists()
+assert new File(basedir, 'target/classes/META-INF/versions/9/org/maven/bug/B.class').exists()
+assert new File(basedir, 'target/classes/META-INF/versions/11/module-info.class').exists()
+assert new File(basedir, 'target/classes/META-INF/versions/11/org/maven/bug/B.class').exists()
+assert new File(basedir, 'target/test-classes/org/maven/bug/MrJarTest.class').exists()
diff --git a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
index edb9ad7ed..3fd460892 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
@@ -701,6 +701,32 @@ protected final Optional getModuleDeclaration(final Set sourceFiles)
return Optional.empty();
}
+ /**
+ * Returns existing multirelease JAR output directories through the given release in descending order.
+ * The base output directory is returned last.
+ */
+ protected static List getProjectOutputDirectories(File outputDirectory, int release) {
+ List directories = new ArrayList<>();
+ File versionsFolder = new File(outputDirectory, "META-INF/versions");
+
+ for (int version = release; version >= 9; version--) {
+ File versionSubFolder = new File(versionsFolder, String.valueOf(version));
+ if (versionSubFolder.isDirectory()) {
+ directories.add(versionSubFolder);
+ }
+ }
+
+ directories.add(outputDirectory);
+ return directories;
+ }
+
+ /**
+ * Returns the major Java version from its legacy or current string representation.
+ */
+ protected static int getJavaMajorVersion(String version) {
+ return Integer.parseInt(version.startsWith("1.") ? version.substring(2) : version);
+ }
+
private boolean targetOrReleaseSet;
@Override
diff --git a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
index 0638d2991..101762020 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
@@ -32,6 +32,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.StringJoiner;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
@@ -257,6 +258,7 @@ protected void preparePaths(Set sourceFiles) {
// assert compilePath != null;
Optional moduleDeclaration = getModuleDeclaration(sourceFiles);
+ List projectOutputDirectories = getProjectOutputDirectories(getProject());
if (moduleDeclaration.isPresent()) {
// For now only allow named modules. Once we can create a graph with ASM we can specify exactly the modules
@@ -269,7 +271,8 @@ protected void preparePaths(Set sourceFiles) {
ResolvePathsResult resolvePathsResult;
try {
- Collection dependencyArtifacts = getCompileClasspathElements(getProject());
+ Collection dependencyArtifacts =
+ getCompileClasspathElements(getProject(), projectOutputDirectories);
ResolvePathsRequest request = ResolvePathsRequest.ofFiles(dependencyArtifacts)
.setIncludeStatic(true)
@@ -307,13 +310,15 @@ protected void preparePaths(Set sourceFiles) {
for (File file : resolvePathsResult.getClasspathElements()) {
classpathElements.add(file.getPath());
+ }
- if (multiReleaseOutput) {
- if (getOutputDirectory().toPath().startsWith(file.getPath())) {
- compilerArgs.add("--patch-module");
- compilerArgs.add(String.format("%s=%s", moduleDescriptor.name(), file.getPath()));
- }
+ if (multiReleaseOutput) {
+ StringJoiner patchPath = new StringJoiner(PS);
+ for (File directory : projectOutputDirectories) {
+ patchPath.add(directory.getPath());
}
+ compilerArgs.add("--patch-module");
+ compilerArgs.add(moduleDescriptor.name() + '=' + patchPath);
}
for (File file : resolvePathsResult.getModulepathElements().keySet()) {
@@ -329,7 +334,7 @@ protected void preparePaths(Set sourceFiles) {
}
} else {
classpathElements = new ArrayList<>();
- for (File element : getCompileClasspathElements(getProject())) {
+ for (File element : getCompileClasspathElements(getProject(), projectOutputDirectories)) {
classpathElements.add(element.getPath());
}
modulepathElements = Collections.emptyList();
@@ -362,23 +367,23 @@ private void detectFilenameBasedAutomodules(
}
}
- private List getCompileClasspathElements(MavenProject project) {
- // 3 is outputFolder + 2 preserved for multirelease
- List list = new ArrayList<>(project.getArtifacts().size() + 3);
+ /**
+ * Returns the project output directories visible to the current compilation. For a multi-release output, existing
+ * earlier release directories are returned in descending order before the base output directory.
+ */
+ private List getProjectOutputDirectories(MavenProject project) {
+ File outputDirectory = new File(project.getBuild().getOutputDirectory());
if (multiReleaseOutput) {
- File versionsFolder = new File(project.getBuild().getOutputDirectory(), "META-INF/versions");
-
- // in reverse order
- for (int version = Integer.parseInt(getRelease()) - 1; version >= 9; version--) {
- File versionSubFolder = new File(versionsFolder, String.valueOf(version));
- if (versionSubFolder.exists()) {
- list.add(versionSubFolder);
- }
- }
+ return getProjectOutputDirectories(outputDirectory, getJavaMajorVersion(getRelease()) - 1);
}
- list.add(new File(project.getBuild().getOutputDirectory()));
+ return Collections.singletonList(outputDirectory);
+ }
+
+ private List getCompileClasspathElements(MavenProject project, List projectOutputDirectories) {
+ List list = new ArrayList<>(project.getArtifacts().size() + projectOutputDirectories.size());
+ list.addAll(projectOutputDirectories);
for (Artifact a : project.getArtifacts()) {
if (a.getArtifactHandler().isAddedToClasspath()) {
diff --git a/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java
index 1e0b76ea8..6983e5a92 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java
@@ -21,6 +21,7 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
@@ -31,6 +32,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.StringJoiner;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -235,11 +237,14 @@ protected File getOutputDirectory() {
protected void preparePaths(Set sourceFiles) {
File mainOutputDirectory = new File(getProject().getBuild().getOutputDirectory());
- File mainModuleDescriptorClassFile = new File(mainOutputDirectory, "module-info.class");
+ List mainOutputDirectories =
+ getProjectOutputDirectories(mainOutputDirectory, getEffectiveTestJavaVersion());
+ File mainModuleDescriptorClassFile = getModuleDescriptor(mainOutputDirectories);
JavaModuleDescriptor mainModuleDescriptor = null;
File testModuleDescriptorJavaFile = new File("module-info.java");
JavaModuleDescriptor testModuleDescriptor = null;
+ List effectiveTestPath = testPath;
// Go through the source files to respect includes/excludes
for (File sourceFile : sourceFiles) {
@@ -251,11 +256,14 @@ protected void preparePaths(Set sourceFiles) {
}
// Get additional information from the main module descriptor, if available
- if (mainModuleDescriptorClassFile.exists()) {
+ if (mainModuleDescriptorClassFile != null) {
ResolvePathsResult result;
try {
- ResolvePathsRequest request = ResolvePathsRequest.ofStrings(testPath)
+ // LocationManager needs the directory containing the selected descriptor to recognize the main module.
+ effectiveTestPath = replacePathElement(
+ testPath, mainOutputDirectory, mainModuleDescriptorClassFile.getParentFile());
+ ResolvePathsRequest request = ResolvePathsRequest.ofStrings(effectiveTestPath)
.setIncludeStatic(true)
.setMainModuleDescriptor(mainModuleDescriptorClassFile.getAbsolutePath());
@@ -294,7 +302,7 @@ protected void preparePaths(Set sourceFiles) {
ResolvePathsResult result;
try {
- ResolvePathsRequest request = ResolvePathsRequest.ofStrings(testPath)
+ ResolvePathsRequest request = ResolvePathsRequest.ofStrings(effectiveTestPath)
.setMainModuleDescriptor(testModuleDescriptorJavaFile.getAbsolutePath());
Toolchain toolchain = getToolchain();
@@ -331,7 +339,7 @@ protected void preparePaths(Set sourceFiles) {
}
if (testModuleDescriptor != null) {
- modulepathElements = testPath;
+ modulepathElements = effectiveTestPath;
classpathElements = Collections.emptyList();
if (mainModuleDescriptor != null) {
@@ -342,23 +350,22 @@ protected void preparePaths(Set sourceFiles) {
}
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('=');
-
+ List mainSourceRoots = new ArrayList<>();
for (String root : getProject().getCompileSourceRoots()) {
if (Files.exists(Paths.get(root))) {
- patchModuleValue.append(root).append(PS);
+ mainSourceRoots.add(root);
}
}
- compilerArgs.add(patchModuleValue.toString());
+ // Tests in the main module need the layered MR-JAR output and the main sources as one patch.
+ List outputPatches =
+ mainOutputDirectories.size() > 1 ? mainOutputDirectories : Collections.emptyList();
+ addPatchModule(testModuleDescriptor.name(), outputPatches, mainSourceRoots);
} else {
+ // Patch all output layers in multirelease lookup order so newer classes shadow older ones.
+ if (mainOutputDirectories.size() > 1) {
+ addPatchModule(mainModuleDescriptor.name(), mainOutputDirectories, Collections.emptyList());
+ }
getLog().debug("Black-box testing - all is ready to compile");
}
} else {
@@ -375,20 +382,8 @@ protected void preparePaths(Set sourceFiles) {
}
} 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());
+ // Unnamed tests are compiled as a patch of the layered main module.
+ addPatchModule(mainModuleDescriptor.name(), mainOutputDirectories, compileSourceRoots);
compilerArgs.add("--add-reads");
compilerArgs.add(mainModuleDescriptor.name() + "=ALL-UNNAMED");
@@ -399,6 +394,57 @@ protected void preparePaths(Set sourceFiles) {
}
}
+ private int getEffectiveTestJavaVersion() {
+ String version = StringUtils.isNotEmpty(getRelease()) ? getRelease() : getTarget();
+ return getJavaMajorVersion(version);
+ }
+
+ static File getModuleDescriptor(List outputDirectories) {
+ for (File outputDirectory : outputDirectories) {
+ File descriptor = new File(outputDirectory, "module-info.class");
+ if (descriptor.isFile()) {
+ return descriptor;
+ }
+ }
+ return null;
+ }
+
+ private static List replacePathElement(List path, File element, File replacement) {
+ List result = new ArrayList<>(path.size());
+ Path elementPath = element.toPath().toAbsolutePath().normalize();
+ boolean replaced = false;
+
+ for (String value : path) {
+ if (Paths.get(value).toAbsolutePath().normalize().equals(elementPath)) {
+ result.add(replacement.getAbsolutePath());
+ replaced = true;
+ } else {
+ result.add(value);
+ }
+ }
+ if (!replaced) {
+ result.add(0, replacement.getAbsolutePath());
+ }
+ return result;
+ }
+
+ private void addPatchModule(String moduleName, List outputDirectories, Collection sourceRoots) {
+ if (compilerArgs == null) {
+ compilerArgs = new ArrayList<>();
+ }
+
+ StringJoiner patchPath = new StringJoiner(PS);
+ for (File dir : outputDirectories) {
+ patchPath.add(dir.getPath());
+ }
+ for (String sourceRoot : sourceRoots) {
+ patchPath.add(sourceRoot);
+ }
+
+ compilerArgs.add("--patch-module");
+ compilerArgs.add(moduleName + '=' + patchPath);
+ }
+
protected SourceInclusionScanner getSourceInclusionScanner(int staleMillis) {
SourceInclusionScanner scanner;
@@ -438,11 +484,7 @@ protected SourceInclusionScanner getSourceInclusionScanner(String inputFileEndin
}
static boolean isOlderThanJDK9(String version) {
- if (version.startsWith("1.")) {
- return Integer.parseInt(version.substring(2)) < 9;
- }
-
- return Integer.parseInt(version) < 9;
+ return getJavaMajorVersion(version) < 9;
}
protected String getSource() {
diff --git a/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java b/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java
index 20bc7eafc..42f537d42 100644
--- a/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java
+++ b/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java
@@ -19,10 +19,12 @@
package org.apache.maven.plugin.compiler;
import java.io.File;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
@@ -30,6 +32,7 @@
import org.apache.maven.api.plugin.testing.MojoTest;
import org.apache.maven.plugin.compiler.stubs.CompilerManagerStub;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -204,4 +207,26 @@ static Stream olderThanJDK9() {
void olderThanJDK9(String version, boolean expected) {
assertEquals(expected, TestCompilerMojo.isOlderThanJDK9(version));
}
+
+ @Test
+ void shouldSelectApplicableModuleDescriptor(@TempDir Path temporaryDirectory) throws Exception {
+ Path outputDirectory = temporaryDirectory.resolve("classes");
+ Path version9 = Files.createDirectories(outputDirectory.resolve("META-INF/versions/9"));
+ Path version11 = Files.createDirectories(outputDirectory.resolve("META-INF/versions/11"));
+ Files.createDirectories(outputDirectory.resolve("META-INF/versions/17"));
+
+ Path version9Descriptor = Files.createFile(version9.resolve("module-info.class"));
+ Path version11Descriptor = Files.createFile(version11.resolve("module-info.class"));
+ Path rootDescriptor = Files.createFile(outputDirectory.resolve("module-info.class"));
+
+ List outputDirectories = AbstractCompilerMojo.getProjectOutputDirectories(outputDirectory.toFile(), 11);
+ assertEquals(Arrays.asList(version11.toFile(), version9.toFile(), outputDirectory.toFile()), outputDirectories);
+ assertEquals(version11Descriptor.toFile(), TestCompilerMojo.getModuleDescriptor(outputDirectories));
+
+ Files.delete(version11Descriptor);
+ assertEquals(version9Descriptor.toFile(), TestCompilerMojo.getModuleDescriptor(outputDirectories));
+
+ Files.delete(version9Descriptor);
+ assertEquals(rootDescriptor.toFile(), TestCompilerMojo.getModuleDescriptor(outputDirectories));
+ }
}