From 3127932dfd2b881a94f9371a1a4cacb87eab8b7f Mon Sep 17 00:00:00 2001 From: Jendrik Johannes Date: Tue, 27 Jan 2026 11:27:14 +0100 Subject: [PATCH] Allow preserveExisting existing to be combined with other features - removePackage: remove exports of package from existing module-info - ignoreServiceProvider: remove ignored providers from module-info --- CHANGELOG.md | 4 ++ .../ExtraJavaModuleInfoTransform.java | 44 +++++++++++++++++- .../test/RemovePackageFunctionalTest.groovy | 45 ++++++++++++++++--- 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fa7abc..6074057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Extra Java Module Info Gradle Plugin - Changelog +## Version 1.13.2 +* [Fixed] [#219](https://github.com/gradlex-org/extra-java-module-info/issues/219) - Combine 'preserveExisting' and 'removePackage' +* [Fixed] [#223](https://github.com/gradlex-org/extra-java-module-info/issues/223) - Combine 'preserveExisting' and 'ignoreServiceProvider' + ## Version 1.13.1 * [Fixed] [#197](https://github.com/gradlex-org/extra-java-module-info/issues/197) - Slightly adjust Gradle API usage for better 9.0.0 compatibility diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java index 24c7d69..874987c 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 package org.gradlex.javamodule.moduleinfo; +import static java.util.Collections.emptySet; import static org.gradlex.javamodule.moduleinfo.FilePathToModuleCoordinates.gaCoordinatesFromFilePathMatch; import static org.gradlex.javamodule.moduleinfo.FilePathToModuleCoordinates.versionFromFilePath; import static org.gradlex.javamodule.moduleinfo.ModuleNameUtil.automaticModulNameFromFileName; @@ -17,6 +18,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -337,7 +339,9 @@ private void addModuleDescriptor(File originalJar, File moduleJar, ModuleInfo mo moduleInfo, providers, versionFromFilePath(originalJar.toPath()), - moduleInfo.exportAllPackages ? packages : Collections.emptySet(), + moduleInfo.exportAllPackages ? packages : emptySet(), + moduleInfo.getRemovedPackages(), + moduleInfo.ignoreServiceProviders, existingModuleInfo)); outputStream.closeEntry(); } @@ -428,6 +432,8 @@ private byte[] addModuleInfo( Map> providers, @Nullable String version, Set autoExportedPackages, + List removedPackages, + Map> ignoreServiceProviders, @Nullable byte[] existingModuleInfo) { ClassReader classReader = moduleInfo.preserveExisting && existingModuleInfo != null ? new ClassReader(existingModuleInfo) : null; @@ -449,6 +455,42 @@ private byte[] addModuleInfo( public ModuleVisitor visitModule(String name, int access, String version) { ModuleVisitor moduleVisitor = super.visitModule(name, access, version); return new ModuleVisitor(Opcodes.ASM9, moduleVisitor) { + + @Override + public void visitPackage(String packaze) { + if (!removedPackages.contains(pathToPackage(packaze))) { + super.visitPackage(packaze); + } + } + + @Override + public void visitExport(String packaze, int access, String... modules) { + if (!removedPackages.contains(pathToPackage(packaze))) { + super.visitExport(packaze, access, modules); + } + } + + @Override + public void visitUse(String service) { + String packaze = service.substring(0, service.lastIndexOf("/")); + // if package is removed, also remove 'use' directives based on the package + if (!removedPackages.contains(pathToPackage(packaze))) { + super.visitUse(service); + } + } + + @Override + public void visitProvide(String service, String... providers) { + String[] filteredProviders = Arrays.stream(providers) + .filter(p -> ignoreServiceProviders + .getOrDefault(service, emptySet()) + .contains(p)) + .toArray(String[]::new); + if (filteredProviders.length > 0) { + super.visitProvide(service, filteredProviders); + } + } + @Override public void visitEnd() { addModuleInfoEntires(moduleInfo, Collections.emptyMap(), autoExportedPackages, this); diff --git a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RemovePackageFunctionalTest.groovy b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RemovePackageFunctionalTest.groovy index fab446d..af2ae95 100644 --- a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RemovePackageFunctionalTest.groovy +++ b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RemovePackageFunctionalTest.groovy @@ -1,7 +1,6 @@ package org.gradlex.javamodule.moduleinfo.test import org.gradlex.javamodule.moduleinfo.test.fixture.GradleBuild -import org.gradlex.javamodule.moduleinfo.test.fixture.LegacyLibraries import spock.lang.Specification class RemovePackageFunctionalTest extends Specification { @@ -9,8 +8,6 @@ class RemovePackageFunctionalTest extends Specification { @Delegate GradleBuild build = new GradleBuild() - LegacyLibraries libs = new LegacyLibraries(false) - def setup() { settingsFile << 'rootProject.name = "test-project"' buildFile << ''' @@ -23,6 +20,10 @@ class RemovePackageFunctionalTest extends Specification { mainClass.set("org.example.app.Main") } ''' + } + + def "can remove duplicated packages"() { + given: file("src/main/java/module-info.java") << """ module org.example.app { requires jdk.xml.dom; @@ -37,10 +38,7 @@ class RemovePackageFunctionalTest extends Specification { } } """ - } - def "can remove duplicated packages"() { - given: buildFile << """ dependencies { implementation("xerces:xercesImpl:2.12.2") { isTransitive = false } @@ -58,4 +56,39 @@ class RemovePackageFunctionalTest extends Specification { run() } + def "removes package from module-info if removePackage and preserveExisting are used together"() { + given: + file("src/main/java/module-info.java") << """ + module org.example.app { + requires jakarta.el; + requires org.apache.tomcat.embed.el; + } + """ + file("src/main/java/org/gradle/sample/app/Main.java") << """ + package org.example.app; + public class Main { + public static void main(String[] args) { + jakarta.el.ELContext context; // from original jakarta.el-api module + org.apache.el.ValueExpressionLiteral exp; // from apache embedded module + } + } + """ + + buildFile << """ + dependencies { + implementation("jakarta.el:jakarta.el-api:5.0.1") + implementation("org.apache.tomcat.embed:tomcat-embed-el:10.1.50") + } + extraJavaModuleInfo { + module("org.apache.tomcat.embed:tomcat-embed-el", "org.apache.tomcat.embed.el") { + preserveExisting() + removePackage("jakarta.el") + } + } + """ + + expect: + run() + } + }