From e99a6abe78af65572fe3d7d14e5213f312e426de Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Sat, 21 Sep 2024 12:17:47 +0200 Subject: [PATCH] Support classifier in coordinates notation (#146) Resolves #130 --- README.md | 13 ++++- .../ExtraJavaModuleInfoTransform.java | 19 ++++++- .../javamodule/moduleinfo/IdValidator.java | 2 +- .../javamodule/moduleinfo/ModuleSpec.java | 16 +++++- .../test/ClassifiedJarsFunctionalTest.groovy | 56 +++++++++++++++++++ 5 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 src/test/groovy/org/gradlex/javamodule/moduleinfo/test/ClassifiedJarsFunctionalTest.groovy diff --git a/README.md b/README.md index 4a4d81a..9b200a8 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,9 @@ extraJavaModuleInfo { module("commons-beanutils:commons-beanutils", "org.apache.commons.beanutils") { exports("org.apache.commons.beanutils") // or granuarly allowing access to a package by specific modules - // exports("org.apache.commons.beanutils", "org.mycompany.server", "org.mycompany.client") + // exports("org.apache.commons.beanutils", + // "org.mycompany.server", "org.mycompany.client") + // or simply export all packages // exportAllPackages() requiresTransitive("org.apache.commons.logging") @@ -81,7 +83,8 @@ extraJavaModuleInfo { // closeModule() // opens("org.apache.commons.beanutils") // or granuarly allowing runtime-only access to a package by specific modules - // opens("org.apache.commons.beanutils", "org.mycompany.server", "org.mycompany.client") + // opens("org.apache.commons.beanutils", + // "org.mycompany.server", "org.mycompany.client") // requiresTransitive(...) // requiresStatic(...) @@ -93,6 +96,12 @@ extraJavaModuleInfo { } module("commons-collections:commons-collections", "org.apache.commons.collections") automaticModule("commons-logging:commons-logging", "org.apache.commons.logging") + + // when the Jar has a classifier - 'linux-x86_64' in this example: + module("io.netty:netty-transport-native-epoll|linux-x86_64", + "io.netty.transport.epoll.linux.x86_64") + // when you somehow cannot address a Jar via coordinates, you may use the Jar name: + module("commons-logging-1.2.jar", "org.apache.commons.loggin") } ``` diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java index a30718d..ba67d68 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java @@ -65,6 +65,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipException; @@ -176,7 +177,19 @@ private ModuleSpec findModuleSpec(File originalJar) { Optional gaCoordinates = moduleSpecs.keySet().stream().filter(ga -> gaCoordinatesFromFilePathMatch(originalJar.toPath(), ga)).findFirst(); if (gaCoordinates.isPresent()) { - return moduleSpecs.get(gaCoordinates.get()); + String ga = gaCoordinates.get(); + if (moduleSpecs.containsKey(ga)) { + return moduleSpecs.get(ga); + } else { + // maybe with classifier + Stream idsWithClassifier = moduleSpecs.keySet().stream().filter(id -> id.startsWith(ga + "|")); + for (String idWithClassifier : idsWithClassifier.collect(Collectors.toList())) { + if (nameHasClassifier(originalJar, moduleSpecs.get(idWithClassifier))) { + return moduleSpecs.get(idWithClassifier); + } + } + } + return null; } String originalJarName = originalJar.getName(); @@ -513,6 +526,10 @@ private String moduleNameFromSharedMapping(String ga) { return null; } + private boolean nameHasClassifier(File jar, ModuleSpec spec) { + return jar.getName().endsWith("-" + spec.getClassifier() + ".jar"); + } + private static boolean isModuleInfoClass(String jarEntryName) { return "module-info.class".equals(jarEntryName) || MODULE_INFO_CLASS_MRJAR_PATH.matcher(jarEntryName).matches(); } diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/IdValidator.java b/src/main/java/org/gradlex/javamodule/moduleinfo/IdValidator.java index 2981440..fd98cb1 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/IdValidator.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/IdValidator.java @@ -17,7 +17,7 @@ package org.gradlex.javamodule.moduleinfo; class IdValidator { - static private final String COORDINATES_PATTERN = "^[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$"; + static private final String COORDINATES_PATTERN = "^[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+(\\|[a-zA-Z0-9._-]+)?$"; static private final String FILE_NAME_PATTERN = "^[a-zA-Z0-9._-]+\\.(jar|zip)$"; static void validateIdentifier(String identifier) { diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleSpec.java b/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleSpec.java index 8e0e669..45de690 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleSpec.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleSpec.java @@ -33,6 +33,7 @@ public abstract class ModuleSpec implements Serializable { private final String identifier; + private final String classifier; // optional private final String moduleName; private final List mergedJars = new ArrayList<>(); @@ -41,7 +42,13 @@ public abstract class ModuleSpec implements Serializable { protected ModuleSpec(String identifier, String moduleName) { validateIdentifier(identifier); validateModuleName(moduleName); - this.identifier = identifier; + if (identifier.contains("|")) { + this.identifier = identifier.split("\\|")[0]; + this.classifier = identifier.split("\\|")[1]; + } else { + this.identifier = identifier; + this.classifier = null; + } this.moduleName = moduleName; } @@ -52,6 +59,13 @@ public String getIdentifier() { return identifier; } + /** + * @return classifier, as an addition to group:name coordinates, if defined + */ + public String getClassifier() { + return classifier; + } + /** * @return Module Name of the Module to construct */ diff --git a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/ClassifiedJarsFunctionalTest.groovy b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/ClassifiedJarsFunctionalTest.groovy new file mode 100644 index 0000000..51f6e06 --- /dev/null +++ b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/ClassifiedJarsFunctionalTest.groovy @@ -0,0 +1,56 @@ +package org.gradlex.javamodule.moduleinfo.test + +import org.gradle.testkit.runner.TaskOutcome +import org.gradlex.javamodule.moduleinfo.test.fixture.GradleBuild +import spock.lang.Specification + +class ClassifiedJarsFunctionalTest extends Specification { + + @Delegate + GradleBuild build = new GradleBuild() + + def setup() { + settingsFile << 'rootProject.name = "test-project"' + buildFile << ''' + plugins { + id("application") + id("org.gradlex.extra-java-module-info") + } + application { + mainModule.set("org.gradle.sample.app") + mainClass.set("org.gradle.sample.app.Main") + } + ''' + } + + def "can address classified Jars via coordinates"() { + given: + file("src/main/java/org/gradle/sample/app/Main.java") << """ + package org.gradle.sample.app; + public class Main { + public static void main(String[] args) { } + } + """ + file("src/main/java/module-info.java") << """ + module org.gradle.sample.app { + requires io.netty.transport.epoll.linux.x86_64; + requires io.netty.transport.epoll.linux.aarch_64; + } + """ + buildFile << """ + dependencies { + implementation(platform("io.netty:netty-bom:4.1.110.Final")) + implementation("io.netty:netty-transport-native-epoll:0:linux-x86_64") + implementation("io.netty:netty-transport-native-epoll:0:linux-aarch_64") + } + extraJavaModuleInfo { + module("io.netty:netty-transport-native-epoll|linux-x86_64", "io.netty.transport.epoll.linux.x86_64") + module("io.netty:netty-transport-native-epoll|linux-aarch_64", "io.netty.transport.epoll.linux.aarch_64") + } + """ + + expect: + build().task(':compileJava').outcome == TaskOutcome.SUCCESS + } + +}