This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-compiler-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 3bcda08  Two more test cases for multi-release integration tests (#951)
3bcda08 is described below

commit 3bcda086c21118901c08f445371bf29327f4f521
Author: Fridrich Strba <[email protected]>
AuthorDate: Wed Jul 16 17:40:25 2025 +0200

    Two more test cases for multi-release integration tests (#951)
    
    * Test case with multirelease and module-info.java in root directory
    
    * Test case with multi-release jar where module-info is in root and built 
in a separate execution
    
    Moreover the version 9 multirelease directory contains a class that is not 
in the base
    directory and that should be still accessible to the version 17 
multirelease classes
---
 .../singleproject-root/invoker.properties          |  17 +++
 .../singleproject-root/pom.xml                     | 141 ++++++++++++++++++
 .../src/main/java/base/Base.java                   |  26 ++++
 .../src/main/java/module-info.java                 |  22 +++
 .../singleproject-root/src/main/java/mr/A.java     |  32 ++++
 .../singleproject-root/src/main/java/mr/I.java     |  23 +++
 .../singleproject-root/src/main/java11/mr/A.java   |  34 +++++
 .../singleproject-root/src/main/java17/mr/A.java   |  34 +++++
 .../singleproject-root/src/test/java/mr/ATest.java |  48 ++++++
 .../singleproject-root/verify.groovy               |  82 ++++++++++
 .../invoker.properties                             |  17 +++
 .../singleproject-separate-moduleinfo/pom.xml      | 165 +++++++++++++++++++++
 .../src/main/java/base/Base.java                   |  26 ++++
 .../src/main/java/module-info.java                 |  22 +++
 .../src/main/java/mr/A.java                        |  32 ++++
 .../src/main/java/mr/I.java                        |  23 +++
 .../src/main/java17/mr/A.java                      |  34 +++++
 .../src/main/java9/mr/A.java                       |  34 +++++
 .../src/main/java9/mr/B.java                       |  25 ++++
 .../src/test/java/mr/ATest.java                    |  48 ++++++
 .../verify.groovy                                  |  86 +++++++++++
 21 files changed, 971 insertions(+)

diff --git a/src/it/multirelease-patterns/singleproject-root/invoker.properties 
b/src/it/multirelease-patterns/singleproject-root/invoker.properties
new file mode 100644
index 0000000..8e4e5be
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/invoker.properties
@@ -0,0 +1,17 @@
+# 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.goals = verify
diff --git a/src/it/multirelease-patterns/singleproject-root/pom.xml 
b/src/it/multirelease-patterns/singleproject-root/pom.xml
new file mode 100644
index 0000000..09e9a01
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/pom.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0                           
    http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>multirelease</groupId>
+
+  <artifactId>multirelease</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <name>Single Project :: Root</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>@project.version@</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>@version.maven-jar-plugin@</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-failsafe-plugin</artifactId>
+          <version>@version.maven-surefire@</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>@version.maven-surefire@</version>
+          <configuration>
+            <!-- this shows that the Java 9 code isn't tested -->
+            <testFailureIgnore>true</testFailureIgnore>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <!-- TODO: remove source and target after we identified where Maven 
inherits those values. -->
+          <source />
+          <target />
+          <release>9</release>
+        </configuration>
+        <executions>
+          <execution>
+            <id>multi-release-11</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+            <configuration>
+              <release>11</release>
+              <compileSourceRoots>
+                
<compileSourceRoot>${project.basedir}/src/main/java11</compileSourceRoot>
+              </compileSourceRoots>
+              <multiReleaseOutput>true</multiReleaseOutput>
+            </configuration>
+          </execution>
+          <execution>
+            <id>multi-release-17</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+            <configuration>
+              <release>17</release>
+              <compileSourceRoots>
+                
<compileSourceRoot>${project.basedir}/src/main/java17</compileSourceRoot>
+              </compileSourceRoots>
+              <multiReleaseOutput>true</multiReleaseOutput>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <!-- Rerun unittests with the multirelease jar, cannot be done with 
exploded directory of classes  -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>**/*Test.java</include>
+          </includes>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>integration-test</goal>
+              <goal>verify</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <configuration>
+              <archive>
+                <manifestEntries>
+                  <Multi-Release>true</Multi-Release>
+                </manifestEntries>
+              </archive>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/main/java/base/Base.java 
b/src/it/multirelease-patterns/singleproject-root/src/main/java/base/Base.java
new file mode 100644
index 0000000..19ec7d8
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-root/src/main/java/base/Base.java
@@ -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.
+ */
+package base;
+
+public class Base {
+
+    public static String get() {
+        return "BASE";
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/main/java/module-info.java
 
b/src/it/multirelease-patterns/singleproject-root/src/main/java/module-info.java
new file mode 100644
index 0000000..36f00e0
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-root/src/main/java/module-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 example.mrjar {
+    exports base;
+    exports mr;
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/main/java/mr/A.java 
b/src/it/multirelease-patterns/singleproject-root/src/main/java/mr/A.java
new file mode 100644
index 0000000..663a2ba
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/src/main/java/mr/A.java
@@ -0,0 +1,32 @@
+/*
+ * 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 mr;
+
+import base.Base;
+
+public class A implements I {
+    public static String getString() {
+        return Base.get() + " -> 9";
+    }
+
+    @Override
+    public Class<?> introducedClass() {
+        return java.time.LocalDateTime.class;
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/main/java/mr/I.java 
b/src/it/multirelease-patterns/singleproject-root/src/main/java/mr/I.java
new file mode 100644
index 0000000..a052326
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/src/main/java/mr/I.java
@@ -0,0 +1,23 @@
+/*
+ * 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 mr;
+
+public interface I {
+    Class<?> introducedClass();
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/main/java11/mr/A.java 
b/src/it/multirelease-patterns/singleproject-root/src/main/java11/mr/A.java
new file mode 100644
index 0000000..aa4e197
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/src/main/java11/mr/A.java
@@ -0,0 +1,34 @@
+/*
+ * 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 mr;
+
+import java.util.Optional;
+
+import base.Base;
+
+public class A implements I {
+    public static String getString() {
+        return Base.get() + " -> " + Optional.of("11").get();
+    }
+
+    @Override
+    public Class<?> introducedClass() {
+        return Module.class;
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/main/java17/mr/A.java 
b/src/it/multirelease-patterns/singleproject-root/src/main/java17/mr/A.java
new file mode 100644
index 0000000..c1dc066
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/src/main/java17/mr/A.java
@@ -0,0 +1,34 @@
+/*
+ * 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 mr;
+
+import java.util.Optional;
+
+import base.Base;
+
+public class A implements I {
+    public static String getString() {
+        return Base.get() + " -> " + Optional.of("17").get();
+    }
+
+    @Override
+    public Class<?> introducedClass() {
+        return Module.class;
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-root/src/test/java/mr/ATest.java 
b/src/it/multirelease-patterns/singleproject-root/src/test/java/mr/ATest.java
new file mode 100644
index 0000000..ab08e67
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-root/src/test/java/mr/ATest.java
@@ -0,0 +1,48 @@
+/*
+ * 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 mr;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeThat;
+
+public class ATest {
+
+    private static final String javaVersion = 
System.getProperty("java.version");
+
+    @Test
+    public void testGet9() throws Exception {
+        assumeThat(javaVersion, is("9"));
+
+        assertThat(A.getString(), is("BASE -> 9"));
+
+        assertThat(new A().introducedClass().getName(), 
is("java.time.LocalDateTime"));
+    }
+
+    @Test
+    public void testGet11() throws Exception {
+        assumeThat(javaVersion, is("11"));
+
+        assertThat(A.getString(), is("BASE -> 11"));
+
+        assertThat(new A().introducedClass().getName(), 
is("java.lang.Module"));
+    }
+}
diff --git a/src/it/multirelease-patterns/singleproject-root/verify.groovy 
b/src/it/multirelease-patterns/singleproject-root/verify.groovy
new file mode 100644
index 0000000..e321af1
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-root/verify.groovy
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+import java.util.jar.JarFile
+
+def baseVersion = 53 // Java 9
+def mr1Version = 55; // Java 11
+def mr2Version = 61; // Java 17
+
+def mrjar = new JarFile(new 
File(basedir,'target/multirelease-1.0.0-SNAPSHOT.jar'))
+
+assert (je = mrjar.getEntry('base/Base.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+assert (je = mrjar.getEntry('mr/A.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+assert (je = mrjar.getEntry('mr/I.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+assert (je = mrjar.getEntry('module-info.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+
+assert mrjar.manifest.mainAttributes.getValue('Multi-Release') == 'true'
+
+assert (je = mrjar.getEntry('META-INF/versions/11/mr/A.class')) != null
+assert mr1Version == getMajor(mrjar.getInputStream(je))
+
+assert (je = mrjar.getEntry('META-INF/versions/17/mr/A.class')) != null
+assert mr2Version == getMajor(mrjar.getInputStream(je))
+
+/*
+  base
+  base/Base.class
+  module-info.class
+  mr
+  mr/A.class
+  mr/I.class
+  META-INF
+  META-INF/MANFEST.MF
+  META-INF/versions
+  META-INF/versions/11
+  META-INF/versions/11/mr
+  META-INF/versions/11/mr/A.class
+  META-INF/versions/17
+  META-INF/versions/17/mr
+  META-INF/versions/17/mr/A.class
+  META-INF/maven
+  META-INF/maven/multirelease
+  META-INF/maven/multirelease/multirelease
+  META-INF/maven/multirelease/multirelease/pom.xml
+  META-INF/maven/multirelease/multirelease/pom.properties
+*/
+assert mrjar.entries().size() == 20
+
+int getMajor(InputStream is)
+{
+  def dis = new DataInputStream(is)
+  final String firstFourBytes = Integer.toHexString(dis.readUnsignedShort()) + 
Integer.toHexString(dis.readUnsignedShort())
+  if (!firstFourBytes.equalsIgnoreCase("cafebabe"))
+  {
+    throw new IllegalArgumentException(dataSourceName + " is NOT a Java .class 
file.")
+  }
+  final int minorVersion = dis.readUnsignedShort()
+  final int majorVersion = dis.readUnsignedShort()
+
+  is.close();
+  return majorVersion;
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/invoker.properties
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/invoker.properties
new file mode 100644
index 0000000..8e4e5be
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/invoker.properties
@@ -0,0 +1,17 @@
+# 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.goals = verify
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/pom.xml 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/pom.xml
new file mode 100644
index 0000000..091874c
--- /dev/null
+++ b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/pom.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0                           
    http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>multirelease</groupId>
+
+  <artifactId>multirelease</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <name>Single Project :: Separate Module Info</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>@project.version@</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>@version.maven-jar-plugin@</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-failsafe-plugin</artifactId>
+          <version>@version.maven-surefire@</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>@version.maven-surefire@</version>
+          <configuration>
+            <!-- this shows that the Java 9 code isn't tested -->
+            <testFailureIgnore>true</testFailureIgnore>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <!-- TODO: remove source and target after we identified where Maven 
inherits those values. -->
+          <source />
+          <target />
+        </configuration>
+        <executions>
+          <execution>
+            <id>default-compile</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+            <configuration>
+              <release>8</release>
+              <excludes>
+                <exclude>module-info.java</exclude>
+              </excludes>
+            </configuration>
+          </execution>
+          <execution>
+            <id>module-info</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+            <configuration>
+              <release>9</release>
+              <includes>
+                <include>module-info.java</include>
+              </includes>
+            </configuration>
+          </execution>
+          <execution>
+            <id>multi-release-9</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+            <configuration>
+              <release>9</release>
+              <compileSourceRoots>
+                
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
+              </compileSourceRoots>
+              <multiReleaseOutput>true</multiReleaseOutput>
+            </configuration>
+          </execution>
+          <execution>
+            <id>multi-release-17</id>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+            <configuration>
+              <release>17</release>
+              <compileSourceRoots>
+                
<compileSourceRoot>${project.basedir}/src/main/java17</compileSourceRoot>
+              </compileSourceRoots>
+              <multiReleaseOutput>true</multiReleaseOutput>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <!-- Rerun unittests with the multirelease jar, cannot be done with 
exploded directory of classes  -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>**/*Test.java</include>
+          </includes>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>integration-test</goal>
+              <goal>verify</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <configuration>
+              <archive>
+                <manifestEntries>
+                  <Multi-Release>true</Multi-Release>
+                </manifestEntries>
+              </archive>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/base/Base.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/base/Base.java
new file mode 100644
index 0000000..19ec7d8
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/base/Base.java
@@ -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.
+ */
+package base;
+
+public class Base {
+
+    public static String get() {
+        return "BASE";
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/module-info.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/module-info.java
new file mode 100644
index 0000000..36f00e0
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/module-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 example.mrjar {
+    exports base;
+    exports mr;
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/mr/A.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/mr/A.java
new file mode 100644
index 0000000..0e48eee
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/mr/A.java
@@ -0,0 +1,32 @@
+/*
+ * 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 mr;
+
+import base.Base;
+
+public class A implements I {
+    public static String getString() {
+        return Base.get() + " -> 8";
+    }
+
+    @Override
+    public Class<?> introducedClass() {
+        return java.time.LocalDateTime.class;
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/mr/I.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/mr/I.java
new file mode 100644
index 0000000..a052326
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java/mr/I.java
@@ -0,0 +1,23 @@
+/*
+ * 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 mr;
+
+public interface I {
+    Class<?> introducedClass();
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java17/mr/A.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java17/mr/A.java
new file mode 100644
index 0000000..f66f780
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java17/mr/A.java
@@ -0,0 +1,34 @@
+/*
+ * 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 mr;
+
+import java.util.Optional;
+
+import base.Base;
+
+public class A implements I {
+    public static String getString() {
+        return Base.get() + " -> " + Optional.of("17").get() + B.getString();
+    }
+
+    @Override
+    public Class<?> introducedClass() {
+        return Module.class;
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java9/mr/A.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java9/mr/A.java
new file mode 100644
index 0000000..5083e1c
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java9/mr/A.java
@@ -0,0 +1,34 @@
+/*
+ * 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 mr;
+
+import java.util.Optional;
+
+import base.Base;
+
+public class A implements I {
+    public static String getString() {
+        return Base.get() + " -> " + Optional.of("9").get();
+    }
+
+    @Override
+    public Class<?> introducedClass() {
+        return Module.class;
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java9/mr/B.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java9/mr/B.java
new file mode 100644
index 0000000..9032e4c
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/main/java9/mr/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 mr;
+
+public class B {
+    public static String getString() {
+        return "B";
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/test/java/mr/ATest.java
 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/test/java/mr/ATest.java
new file mode 100644
index 0000000..8c7f76b
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/src/test/java/mr/ATest.java
@@ -0,0 +1,48 @@
+/*
+ * 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 mr;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeThat;
+
+public class ATest {
+
+    private static final String javaVersion = 
System.getProperty("java.version");
+
+    @Test
+    public void testGet8() throws Exception {
+        assumeThat(javaVersion, is("8"));
+
+        assertThat(A.getString(), is("BASE -> 8"));
+
+        assertThat(new A().introducedClass().getName(), 
is("java.time.LocalDateTime"));
+    }
+
+    @Test
+    public void testGet9() throws Exception {
+        assumeThat(javaVersion, is("9"));
+
+        assertThat(A.getString(), is("BASE -> 9B"));
+
+        assertThat(new A().introducedClass().getName(), 
is("java.lang.Module"));
+    }
+}
diff --git 
a/src/it/multirelease-patterns/singleproject-separate-moduleinfo/verify.groovy 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/verify.groovy
new file mode 100644
index 0000000..30c0a55
--- /dev/null
+++ 
b/src/it/multirelease-patterns/singleproject-separate-moduleinfo/verify.groovy
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+import java.util.jar.JarFile
+
+def baseVersion = 52 // Java 8
+def mr1Version = 53; // Java 9
+def mr2Version = 61; // Java 17
+
+def mrjar = new JarFile(new 
File(basedir,'target/multirelease-1.0.0-SNAPSHOT.jar'))
+
+assert (je = mrjar.getEntry('base/Base.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+assert (je = mrjar.getEntry('mr/A.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+assert (je = mrjar.getEntry('mr/I.class')) != null
+assert baseVersion == getMajor(mrjar.getInputStream(je))
+
+assert (je = mrjar.getEntry('module-info.class')) != null
+assert mr1Version == getMajor(mrjar.getInputStream(je))
+
+assert mrjar.manifest.mainAttributes.getValue('Multi-Release') == 'true'
+
+assert (je = mrjar.getEntry('META-INF/versions/9/mr/A.class')) != null
+assert mr1Version == getMajor(mrjar.getInputStream(je))
+assert (je = mrjar.getEntry('META-INF/versions/9/mr/B.class')) != null
+assert mr1Version == getMajor(mrjar.getInputStream(je))
+
+assert (je = mrjar.getEntry('META-INF/versions/17/mr/A.class')) != null
+assert mr2Version == getMajor(mrjar.getInputStream(je))
+
+/*
+  base
+  base/Base.class
+  module-info.class
+  mr
+  mr/A.class
+  mr/I.class
+  META-INF
+  META-INF/MANFEST.MF
+  META-INF/versions
+  META-INF/versions/9
+  META-INF/versions/9/mr
+  META-INF/versions/9/mr/A.class
+  META-INF/versions/9/mr/B.class
+  META-INF/versions/17
+  META-INF/versions/17/mr
+  META-INF/versions/17/mr/A.class
+  META-INF/maven
+  META-INF/maven/multirelease
+  META-INF/maven/multirelease/multirelease
+  META-INF/maven/multirelease/multirelease/pom.xml
+  META-INF/maven/multirelease/multirelease/pom.properties
+*/
+assert mrjar.entries().size() == 21
+
+int getMajor(InputStream is)
+{
+  def dis = new DataInputStream(is)
+  final String firstFourBytes = Integer.toHexString(dis.readUnsignedShort()) + 
Integer.toHexString(dis.readUnsignedShort())
+  if (!firstFourBytes.equalsIgnoreCase("cafebabe"))
+  {
+    throw new IllegalArgumentException(dataSourceName + " is NOT a Java .class 
file.")
+  }
+  final int minorVersion = dis.readUnsignedShort()
+  final int majorVersion = dis.readUnsignedShort()
+
+  is.close();
+  return majorVersion;
+}


Reply via email to