diff --git a/pom.xml b/pom.xml index fab3358d..2f6fd21f 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ 4.0.0 org.vafer jdependency - 2.9.0 + 2.9.1-SNAPSHOT jdependency This project provides an API to analyse class dependencies http://github.com/tcurdt/jdependency @@ -41,6 +41,12 @@ krosenvold@apache.org + + + Niels Basjes + nielsbasjes@apache.org + + scm:git:git@github.com:tcurdt/jdependency.git scm:git:git@github.com:tcurdt/jdependency.git diff --git a/src/main/java/org/vafer/jdependency/Clazz.java b/src/main/java/org/vafer/jdependency/Clazz.java index 69a0931b..cbc5a42b 100644 --- a/src/main/java/org/vafer/jdependency/Clazz.java +++ b/src/main/java/org/vafer/jdependency/Clazz.java @@ -19,6 +19,10 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.apache.commons.io.FilenameUtils.separatorsToUnix; /** * A `Clazz` represents the single class identifier inside a classpath. @@ -32,16 +36,123 @@ public final class Clazz implements Comparable { private final Set references = new HashSet<>(); private final Map units = new HashMap<>(); + public static final class ClazzFile { + private ClazzpathUnit unit; + private String filename; + + public ClazzFile(ClazzpathUnit unit, String filename) { + this.unit = unit; + this.filename = filename; + } + + public ClazzpathUnit getUnit() { + return unit; + } + + public String getFilename() { + return filename; + } + + @Override + public String toString() { + return "ClazzFile{" + + "unit=" + unit + + ", filename='" + filename + '\'' + + '}'; + } + } + + // Usually a class is only in a single file. + // When using MultiRelease Jar files this can be multiple files, one for each java release specified. + // The default filename is under the key "8". + private final Map classFilenames = new HashMap<>(); + + // The name of the class (like "org.vafer.jdependency.Clazz") private final String name; public Clazz( final String pName ) { name = pName; } + private static final Pattern EXTRACT_MULTI_RELEASE_JAVA_VERSION = Pattern.compile("^(?:META-INF[\\/\\\\]versions[\\/\\\\](\\d+)[\\/\\\\])?([^.]+).class$"); + + public static final class ParsedFileName { + public String className; + public String forJava; + + @Override + public String toString() { + return "ParsedFileName{" + + "className='" + className + '\'' + + ", forJava='" + forJava + '\'' + + '}'; + } + } + + /** + * Determine the class name for the provided filename. + * + * @param pFileName The filename + * @return the class name for the provided filename OR null if it is not a .class file. + */ + public static ParsedFileName parseClassFileName(String pFileName) { + if (pFileName == null || !pFileName.endsWith(".class")) { + return null;// Not a class filename + } + // foo/bar/Foo.class -> // foo.bar.Foo + + Matcher matcher = EXTRACT_MULTI_RELEASE_JAVA_VERSION.matcher(pFileName); + if (!matcher.matches()) { + return null; + } + ParsedFileName result = new ParsedFileName(); + result.forJava = matcher.group(1); + result.className = separatorsToUnix(matcher.group(2)).replace('/', '.'); + + if (result.forJava == null || result.forJava.isEmpty()) { + if (result.className.contains("-")) { + return null; + } + result.forJava = "8"; + } + + return result; + } + + /** + * Determine if the provided filename is the name of a class that is specific for a java version. + * @param pFileName The filename to be evaluated + * @return true if this is a filename for a specific java version, false if it is not + */ + public static boolean isMultiReleaseClassFile(String pFileName) { + if (pFileName == null) { + return false; + } + Matcher matcher = EXTRACT_MULTI_RELEASE_JAVA_VERSION.matcher(pFileName); + if (!matcher.matches()) { + return false; + } + return matcher.group(1) != null && !matcher.group(1).isEmpty(); + } + + /** + * Record that this class name can be found at: + * @param pUnit The unit in which the class can be found + * @param pForJava For which Java version + * @param pFileName Under which filename in the jar. + */ + public void addMultiReleaseFile(ClazzpathUnit pUnit, String pForJava, String pFileName) { + classFilenames.put(pForJava, new ClazzFile(pUnit, pFileName)); + } + public String getName() { return name; } + public Map getFileNames() { + return classFilenames; + } + public void addClazzpathUnit( final ClazzpathUnit pUnit, final String pDigest ) { units.put(pUnit, pDigest); } @@ -116,7 +227,7 @@ public int compareTo( final Clazz pO ) { } public String toString() { - return name; + return name + " in " + classFilenames; } } diff --git a/src/main/java/org/vafer/jdependency/Clazzpath.java b/src/main/java/org/vafer/jdependency/Clazzpath.java index 12440256..c7776be3 100644 --- a/src/main/java/org/vafer/jdependency/Clazzpath.java +++ b/src/main/java/org/vafer/jdependency/Clazzpath.java @@ -23,17 +23,21 @@ import java.util.Map; import java.util.Set; import java.util.Base64; +import java.util.TreeMap; import java.util.jar.JarInputStream; import java.nio.file.Files; import java.nio.file.Path; import java.security.MessageDigest; +import org.apache.commons.io.input.MessageDigestInputStream; import org.objectweb.asm.ClassReader; -import org.apache.commons.io.input.MessageDigestCalculatingInputStream; import static org.apache.commons.io.FilenameUtils.normalize; import static org.apache.commons.io.FilenameUtils.separatorsToUnix; +import org.vafer.jdependency.Clazz.ParsedFileName; import org.vafer.jdependency.asm.DependenciesClassAdapter; + +import static org.vafer.jdependency.Clazz.parseClassFileName; import static org.vafer.jdependency.utils.StreamUtils.asStream; @@ -46,20 +50,16 @@ public final class Clazzpath { private final boolean versions; private abstract static class Resource { + public final String fileName; + public final String forJava; + public final String name; // Class name ! - private static final int ext = ".class".length(); - - public final String name; - - Resource( final String pName ) { + Resource( final String pFileName ) { super(); - - final int all = pName.length(); - - // foo/bar/Foo.class -> // foo.bar.Foo - this.name = separatorsToUnix(pName) - .substring(0, all - ext) - .replace('/', '.'); + this.fileName = pFileName; + ParsedFileName parsedFileName = parseClassFileName(pFileName); + forJava = parsedFileName.forJava; + name = parsedFileName.className; } abstract InputStream getInputStream() throws IOException; @@ -68,7 +68,7 @@ private abstract static class Resource { private static boolean isValidResourceName( final String pName ) { return pName != null && pName.endsWith(".class") - && !pName.contains( "-" ); + && ( !pName.contains( "-" ) || pName.contains("META-INF/versions/") ); } public Clazzpath() { @@ -86,7 +86,7 @@ public boolean removeClazzpathUnit( final ClazzpathUnit pUnit ) { for (Clazz clazz : unitClazzes) { clazz.removeClazzpathUnit(pUnit); if (clazz.getClazzpathUnits().size() == 0) { - clazzes.remove(clazz.toString()); + clazzes.remove(clazz.getName()); } } @@ -168,7 +168,8 @@ private ClazzpathUnit addClazzpathUnit( final Iterable resources, fina InputStream inputStream = resource.getInputStream(); try { final MessageDigest digest = MessageDigest.getInstance("SHA-256"); - final MessageDigestCalculatingInputStream calculatingInputStream = new MessageDigestCalculatingInputStream(inputStream, digest); + final MessageDigestInputStream calculatingInputStream = + MessageDigestInputStream.builder().setInputStream(inputStream).setMessageDigest(digest).get(); if (versions) { inputStream = calculatingInputStream; @@ -190,6 +191,7 @@ private ClazzpathUnit addClazzpathUnit( final Iterable resources, fina clazz = new Clazz(clazzName); } } + clazz.addMultiReleaseFile(unit, resource.forJava, resource.fileName); final String d = Base64.getEncoder().encodeToString(digest.digest()); clazz.addClazzpathUnit(unit, d); @@ -243,6 +245,10 @@ public Set getClazzes() { return new HashSet<>(clazzes.values()); } + public Map getClazzesMap() { + return new TreeMap<>(clazzes); + } + public Set getClashedClazzes() { final Set all = new HashSet<>(); for (Clazz clazz : clazzes.values()) { diff --git a/src/main/java/org/vafer/jdependency/ClazzpathUnit.java b/src/main/java/org/vafer/jdependency/ClazzpathUnit.java index 0ba835db..7f2d6dac 100644 --- a/src/main/java/org/vafer/jdependency/ClazzpathUnit.java +++ b/src/main/java/org/vafer/jdependency/ClazzpathUnit.java @@ -18,6 +18,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.TreeMap; public final class ClazzpathUnit { @@ -36,6 +37,10 @@ public Set getClazzes() { return new HashSet<>(clazzes.values()); } + public Map getClazzesMap() { + return new TreeMap<>(clazzes); + } + public Clazz getClazz( final String pClazzName ) { return clazzes.get(pClazzName); } diff --git a/src/test/java/org/vafer/jdependency/ClazzpathUnitTestCase.java b/src/test/java/org/vafer/jdependency/ClazzpathUnitTestCase.java index a105035e..e1104838 100644 --- a/src/test/java/org/vafer/jdependency/ClazzpathUnitTestCase.java +++ b/src/test/java/org/vafer/jdependency/ClazzpathUnitTestCase.java @@ -19,24 +19,40 @@ import java.io.File; import java.io.IOException; +import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; - +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.vafer.jdependency.Clazz.parseClassFileName; public class ClazzpathUnitTestCase { private static Path resourcePath( String filename ) { - return Paths.get(filename); + ClassLoader classLoader = ClazzpathUnitTestCase.class.getClassLoader(); + URL resource = classLoader.getResource(filename); + if (resource == null) { + return null; + } + return Paths.get(resource.getFile()); } private static File resourceFile( String filename ) { - return Paths.get(filename).toFile(); + ClassLoader classLoader = ClazzpathUnitTestCase.class.getClassLoader(); + URL resource = classLoader.getResource(filename); + if (resource == null) { + return null; + } + return new File(resource.getFile()); } @Test @@ -69,10 +85,8 @@ public void testIssue47() throws IOException { .flatMap( i -> i.getClazzpathUnits().stream() ) .map( i -> i.toString() ) .collect(Collectors.toSet()); - final Set unitse = new HashSet(Arrays.asList( - "woodstox-core-6.2.3.jar" - )); - assertEquals(unitse, units); + assertEquals(1, units.size()); + assertTrue(units.iterator().next().endsWith("/woodstox-core-6.2.3.jar")); } @Test @@ -153,13 +167,13 @@ public void testShouldHaveUnitId() throws IOException { final Clazzpath cp = new Clazzpath(); final ClazzpathUnit u1 = cp.addClazzpathUnit(resourceFile("jar1.jar")); - assertEquals(u1.toString(), "jar1.jar"); + assertTrue(u1.toString().endsWith("/jar1.jar")); final ClazzpathUnit u1e = cp.addClazzpathUnit(resourceFile("jar1.jar"), "jar1"); assertEquals(u1e.toString(), "jar1"); final ClazzpathUnit u2 = cp.addClazzpathUnit(resourcePath("jar2.jar")); - assertEquals(u2.toString(), "jar2.jar"); + assertTrue(u2.toString().endsWith("/jar2.jar")); final ClazzpathUnit u2e = cp.addClazzpathUnit(resourcePath("jar2.jar"), "jar2"); assertEquals(u2e.toString(), "jar2"); @@ -179,4 +193,88 @@ public void testDependencies() throws IOException { } + + private void verifyFileNameParsing(String fileName, String forJava, String className) { + Clazz.ParsedFileName result = parseClassFileName(fileName); + assertEquals(className, result.className); + assertEquals(forJava, result.forJava); + } + + private void verifyFileNameParsingInvalid(String fileName) { + assertNull(parseClassFileName(fileName)); + } + + @Test + public void testFileNameCheck(){ + assertFalse(Clazz.isMultiReleaseClassFile("org/vafer/multijdk/App.class")); + assertTrue(Clazz.isMultiReleaseClassFile("META-INF/versions/11/org/vafer/multijdk/App.class")); + assertTrue(Clazz.isMultiReleaseClassFile("META-INF/versions/1234/org/vafer/multijdk/App.class")); + } + + @Test + public void testFileNameParsing(){ + verifyFileNameParsing("org/vafer/multijdk/App.class", "8", "org.vafer.multijdk.App"); + verifyFileNameParsing("META-INF/versions/11/org/vafer/multijdk/App.class", "11", "org.vafer.multijdk.App"); + verifyFileNameParsing("META-INF/versions/1234/org/vafer/multijdk/App.class", "1234", "org.vafer.multijdk.App"); + + verifyFileNameParsingInvalid("org/vafer/multijdk/App.classsssss"); + verifyFileNameParsingInvalid("org/vafer/multijdk/App.txt"); + verifyFileNameParsingInvalid("META-INF/versions/xxx/org/vafer/multijdk/App.class"); + } + + private void verifyFileInClazz(Clazz clazz, String expectedFilename, String forJava, boolean mustBePresent) { + Clazz.ClazzFile actualClazzFile = clazz.getFileNames().get(forJava); + String actualFileName = actualClazzFile == null ? null : actualClazzFile.getFilename(); + if (mustBePresent) { + assertEquals("Incorrect filename for Java "+forJava, expectedFilename, actualFileName); + } else { + assertNull("Unexpected filename for Java "+forJava, actualFileName); + } + } + + private void verifyClazzFiles(Clazz clazz, boolean have8, boolean have11, boolean have17) { + String expectedFilename = clazz.getName().replace(".", "/")+".class"; + verifyFileInClazz(clazz, expectedFilename, "8", have8); + verifyFileInClazz(clazz, "META-INF/versions/11/" + expectedFilename, "11", have11); + verifyFileInClazz(clazz, "META-INF/versions/17/" + expectedFilename, "17", have17); + } + + @Test + public void testMultiReleaseJar() throws IOException { + final Clazzpath cp = new Clazzpath(); + + // The Application + final ClazzpathUnit app = cp.addClazzpathUnit(resourceFile("uses-multi-jdk-1.0.jar")); + Map appClazzes = app.getClazzesMap(); + + assertEquals(1, appClazzes.size()); + verifyClazzFiles(appClazzes.get("nl.example.Main"), true, false, false); + + // The multi release dependency + final ClazzpathUnit dependency = cp.addClazzpathUnit(resourceFile("multi-jdk-1.0.0.jar")); + Map dependencyClazzes = dependency.getClazzesMap(); + // Java 8, Java 11, Java 17 + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.Main"), true, false, false); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.App"), true, true, true); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.AbstractJavaVersion"), true, false, false); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.JavaVersion"), true, true, false); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.Unused"), true, true, true); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.OnlyUsedInJava17"), false, true, false); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.SpecificToJava11"), false, true, false); + verifyClazzFiles(dependencyClazzes.get("org.vafer.multijdk.SpecificToJava17"), false, false, true); + + // Check which are obsolete + final Set removable = cp.getClazzes(); + removable.removeAll(appClazzes.values()); + removable.removeAll(app.getTransitiveDependencies()); + + Map removableClazzes = removable + .stream() + .collect(Collectors.toMap(Clazz::getName, Function.identity())); + + assertEquals(2, removableClazzes.size()); + assertTrue(removableClazzes.containsKey("org.vafer.multijdk.Main")); + assertTrue(removableClazzes.containsKey("org.vafer.multijdk.Unused")); + } + } diff --git a/src/test/resources-src/README.md b/src/test/resources-src/README.md new file mode 100644 index 00000000..eca7f939 --- /dev/null +++ b/src/test/resources-src/README.md @@ -0,0 +1,3 @@ +These are the sources for some of the jar files used during testing. + +To recreate the jars specified in this subdirectory simply do `mvn clean install` and they will be copied to the `test/resources` directory. \ No newline at end of file diff --git a/src/test/resources-src/multi-jdk/pom.xml b/src/test/resources-src/multi-jdk/pom.xml new file mode 100644 index 00000000..fd69448a --- /dev/null +++ b/src/test/resources-src/multi-jdk/pom.xml @@ -0,0 +1,141 @@ + + + + + + 4.0.0 + + Multi Release Jar + + org.vafer + multi-jdk + 1.0.0 + + + UTF-8 + UTF-8 + + + 2023-11-11T12:34:56Z + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + java-11 + + compile + + + 11 + 11 + 11 + ${project.basedir}/src/main/java11 + true + + + + + java-17 + + compile + + + 17 + 17 + 17 + ${project.basedir}/src/main/java17 + true + + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.vafer.multijdk.Main + + + true + + + + + + + + + maven-resources-plugin + 3.3.1 + + + Install jar into resources directory + install + + copy-resources + + + + + target + + ${project.artifactId}-${project.version}.jar + + + + ${project.basedir}/../../resources/ + + + + + + + org.apache.maven.plugins + maven-artifact-plugin + 3.5.0 + + + Ensure reproducible + install + + compare + + + + + + + + diff --git a/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/AbstractJavaVersion.java b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/AbstractJavaVersion.java new file mode 100644 index 00000000..a23b255a --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/AbstractJavaVersion.java @@ -0,0 +1,32 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public abstract class AbstractJavaVersion { + + public abstract String getCodeVersion(); + public abstract String getJavaVersion(); + + public String getJavaMajorVersion() { + String version = getJavaVersion(); + String[] versionElements = version.split("\\."); + String majorVersion = versionElements[0]; + if ("1".equals(majorVersion)) { + majorVersion = versionElements[1]; + } + return majorVersion; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/App.java b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/App.java new file mode 100644 index 00000000..250fcd6e --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/App.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class App { + public String doSomething() { + return "base"; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/JavaVersion.java b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/JavaVersion.java new file mode 100644 index 00000000..a2cbfef5 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/JavaVersion.java @@ -0,0 +1,26 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class JavaVersion extends AbstractJavaVersion { + public String getCodeVersion() { + return "8"; + } + + public String getJavaVersion() { + return System.getProperty("java.version"); + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/Main.java b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/Main.java new file mode 100644 index 00000000..3e469b64 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/Main.java @@ -0,0 +1,26 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class Main { + public static void main(String[] args) { + JavaVersion javaVersion = new JavaVersion(); + System.out.println("Java detect: " + javaVersion.getCodeVersion()); + System.out.println("Java major : " + javaVersion.getJavaMajorVersion()); + System.out.println("App code : " + new App().doSomething()); + System.out.println("Unused : " + new Unused().doSomething()); + } +} \ No newline at end of file diff --git a/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/Unused.java b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/Unused.java new file mode 100644 index 00000000..0961fdfd --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java/org/vafer/multijdk/Unused.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class Unused { + public String doSomething() { + return "base"; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/App.java b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/App.java new file mode 100644 index 00000000..bbb93303 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/App.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class App { + public String doSomething() { + return new SpecificToJava11().doSomething() + " 11"; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/JavaVersion.java b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/JavaVersion.java new file mode 100644 index 00000000..3cb84629 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/JavaVersion.java @@ -0,0 +1,33 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +import java.util.stream.Collectors; + +public class JavaVersion extends AbstractJavaVersion { + public String getCodeVersion() { + return "11"; + } + + public String getJavaVersion() { + return Runtime.version() + .version() + .stream() + .limit(3) + .map(Object::toString) + .collect(Collectors.joining(".")); + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/OnlyUsedInJava17.java b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/OnlyUsedInJava17.java new file mode 100644 index 00000000..26c2fcb6 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/OnlyUsedInJava17.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class OnlyUsedInJava17 { + public String doSomething() { + return new JavaVersion().getJavaMajorVersion(); + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/SpecificToJava11.java b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/SpecificToJava11.java new file mode 100644 index 00000000..cfaaff71 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/SpecificToJava11.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class SpecificToJava11 { + public String doSomething() { + return "java"; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/Unused.java b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/Unused.java new file mode 100644 index 00000000..75339a81 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java11/org/vafer/multijdk/Unused.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class Unused { + public String doSomething() { + return "java 11"; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/App.java b/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/App.java new file mode 100644 index 00000000..8a918662 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/App.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class App { + public String doSomething() { + return new SpecificToJava17().doSomething() + " " + new OnlyUsedInJava17().doSomething(); + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/SpecificToJava17.java b/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/SpecificToJava17.java new file mode 100644 index 00000000..d927c18e --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/SpecificToJava17.java @@ -0,0 +1,22 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ + +public class SpecificToJava17 { + public String doSomething() { + return "java"; + } +} diff --git a/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/Unused.java b/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/Unused.java new file mode 100644 index 00000000..0c12f545 --- /dev/null +++ b/src/test/resources-src/multi-jdk/src/main/java17/org/vafer/multijdk/Unused.java @@ -0,0 +1,21 @@ +package org.vafer.multijdk; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ +public class Unused { + public String doSomething() { + return "java 17"; + } +} diff --git a/src/test/resources-src/pom.xml b/src/test/resources-src/pom.xml new file mode 100644 index 00000000..ca0e49dd --- /dev/null +++ b/src/test/resources-src/pom.xml @@ -0,0 +1,29 @@ + + + + + + 4.0.0 + nl.basjes + test-jars-parent + 1.0 + pom + + multi-jdk + uses-multi-jdk + + \ No newline at end of file diff --git a/src/test/resources-src/uses-multi-jdk/pom.xml b/src/test/resources-src/uses-multi-jdk/pom.xml new file mode 100644 index 00000000..49363727 --- /dev/null +++ b/src/test/resources-src/uses-multi-jdk/pom.xml @@ -0,0 +1,89 @@ + + + + + + 4.0.0 + + nl.example + uses-multi-jdk + 1.0 + + App using the Multi Release Jar + + + UTF-8 + UTF-8 + + + 2023-11-11T12:34:56Z + + + + + org.vafer + multi-jdk + 1.0.0 + + + + + + + maven-resources-plugin + 3.3.1 + + + Install jar into resources directory + install + + copy-resources + + + + + target + + ${project.artifactId}-${project.version}.jar + + + + ${project.basedir}/../../resources/ + + + + + + + org.apache.maven.plugins + maven-artifact-plugin + 3.4.1 + + + Ensure reproducible + install + + compare + + + + + + + + + diff --git a/src/test/resources-src/uses-multi-jdk/src/main/java/nl/example/Main.java b/src/test/resources-src/uses-multi-jdk/src/main/java/nl/example/Main.java new file mode 100644 index 00000000..0238131e --- /dev/null +++ b/src/test/resources-src/uses-multi-jdk/src/main/java/nl/example/Main.java @@ -0,0 +1,27 @@ +package nl.example; +/* + * Copyright 2010-2023 The jdependency developers. + * + * 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. + */ +import org.vafer.multijdk.JavaVersion; +import org.vafer.multijdk.App; + +public class Main { + public static void main(String[] args) { + JavaVersion javaVersion = new JavaVersion(); + System.out.println("Java detect: " + javaVersion.getCodeVersion()); + System.out.println("Java major : " + javaVersion.getJavaMajorVersion()); + System.out.println("App code : " + new App().doSomething()); + } +} \ No newline at end of file diff --git a/src/test/resources/multi-jdk-1.0.0.jar b/src/test/resources/multi-jdk-1.0.0.jar new file mode 100644 index 00000000..edde3a96 Binary files /dev/null and b/src/test/resources/multi-jdk-1.0.0.jar differ diff --git a/src/test/resources/uses-multi-jdk-1.0.jar b/src/test/resources/uses-multi-jdk-1.0.jar new file mode 100644 index 00000000..9d705f58 Binary files /dev/null and b/src/test/resources/uses-multi-jdk-1.0.jar differ