diff --git a/CHANGELOG.md b/CHANGELOG.md index d5cde8f..cad2a11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Extra Java Module Info Gradle Plugin - Changelog ## Version 1.14 -* [Fixed] [#179](https://github.com/gradlex-org/extra-java-module-info/issues/179) - Combine 'preserveExisting' and 'exports' -* [Fixed] [#219](https://github.com/gradlex-org/extra-java-module-info/issues/219) - Combine 'preserveExisting' and 'removePackage' +* [New] [#207](https://github.com/gradlex-org/extra-java-module-info/issues/207) - Add 'exportAllPackagesExcept("org.exception", ...)' (Thanks [Tim Hurman](https://github.com/timhamoni) for contributing) +* [Fixed] [#179](https://github.com/gradlex-org/extra-java-module-info/issues/179) - Combine 'preserveExisting' and 'exports' (Thanks to [JabRef](https://github.com/JabRef/jabref) for providing a use case) +* [Fixed] [#219](https://github.com/gradlex-org/extra-java-module-info/issues/219) - Combine 'preserveExisting' and 'removePackage' (Thanks to [stewue](https://github.com/stewue) for providing a use case) * [Fixed] [#223](https://github.com/gradlex-org/extra-java-module-info/issues/223) - Combine 'preserveExisting' and 'ignoreServiceProvider' * [Fixed] [#227](https://github.com/gradlex-org/extra-java-module-info/issues/227) - Stable order for the mergeJar path input diff --git a/README.md b/README.md index 7f57770..1e44fc6 100644 --- a/README.md +++ b/README.md @@ -73,11 +73,13 @@ extraJavaModuleInfo { // skipLocalJars = true module("commons-beanutils:commons-beanutils", "org.apache.commons.beanutils") { exports("org.apache.commons.beanutils") - // or granuarly allowing access to a package by specific modules + // or granularly allowing access to a package by specific modules // exports("org.apache.commons.beanutils", // "org.mycompany.server", "org.mycompany.client") // or simply export all packages // exportAllPackages() + // or export all packages except specific named ones + // exportAllPackagesExcept("org.mycompany.notgood1", "org.mycompany.notgood2") requiresTransitive("org.apache.commons.logging") requires("java.sql") diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java index 8ad570b..744d169 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java @@ -337,12 +337,17 @@ private void addModuleDescriptor(File originalJar, File moduleJar, ModuleInfo mo providers, packages); mergeJars(moduleInfo, outputStream, providers, packages); + if (moduleInfo.exportAllPackages) { + moduleInfo.exportAllPackagesExceptions.forEach(it -> packages.remove(packageToPath(it))); + } else { + packages.clear(); + } outputStream.putNextEntry(newReproducibleEntry("module-info.class")); outputStream.write(addModuleInfo( moduleInfo, providers, versionFromFilePath(originalJar.toPath()), - moduleInfo.exportAllPackages ? packages : emptySet(), + packages, moduleInfo.getRemovedPackages(), moduleInfo.ignoreServiceProviders, existingModuleInfo)); diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleInfo.java b/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleInfo.java index b4e0792..73ca225 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleInfo.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/ModuleInfo.java @@ -2,18 +2,19 @@ package org.gradlex.javamodule.moduleinfo; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; import org.gradle.api.model.ObjectFactory; -import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; /** * Data class to hold the information that should be added as module-info.class to an existing Jar file. */ -@NullMarked +@SuppressWarnings("unused") public class ModuleInfo extends ModuleSpec { @Nullable @@ -28,6 +29,7 @@ public class ModuleInfo extends ModuleSpec { final Set requiresStaticTransitive = new LinkedHashSet<>(); final Map> ignoreServiceProviders = new LinkedHashMap<>(); final Set uses = new LinkedHashSet<>(); + final Set exportAllPackagesExceptions = new LinkedHashSet<>(); boolean exportAllPackages; boolean requireAllDefinedDependencies; @@ -120,7 +122,24 @@ public String getModuleVersion() { * Automatically export all packages of the Jar. Can be used instead of individual 'exports()' statements. */ public void exportAllPackages() { + exportAllPackagesExcept(Collections.emptyList()); + } + + /** + * Automatically export all packages of the Jar. Can be used instead of individual 'exports()' statements. + * @param exceptions A list of packages not to export + */ + public void exportAllPackagesExcept(String... exceptions) { + exportAllPackagesExcept(Arrays.asList(exceptions)); + } + + /** + * Automatically export all packages of the Jar. Can be used instead of individual 'exports()' statements. + * @param exceptions A list of packages not to export + */ + public void exportAllPackagesExcept(List exceptions) { this.exportAllPackages = true; + exportAllPackagesExceptions.addAll(exceptions); } /** diff --git a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/EdgeCasesFunctionalTest.groovy b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/EdgeCasesFunctionalTest.groovy index 6f6f644..6b12338 100644 --- a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/EdgeCasesFunctionalTest.groovy +++ b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/EdgeCasesFunctionalTest.groovy @@ -177,6 +177,53 @@ class EdgeCasesFunctionalTest extends Specification { run().task(':run').outcome == TaskOutcome.SUCCESS } + def "can automatically export all packages except specified of a legacy Jar"() { + given: + file("src/main/java/org/gradle/sample/app/Main.java") << """ + package org.gradle.sample.app; + + import javax.json.JsonString; + import javax.json.JsonValue; + + public class Main { + public static void main(String[] args) { + JsonString jsonString = new JsonString() { + public boolean equals(Object obj) { return false; } + public CharSequence getChars() { return null; } + public String getString() { return null; } + public int hashCode() { return 0; } + public JsonValue.ValueType getValueType() { return null; } + }; + } + } + """ + + file("src/main/java/module-info.java") << """ + module org.gradle.sample.app { + exports org.gradle.sample.app; + + requires java.json; + } + """ + buildFile << """ + dependencies { + implementation("org.glassfish:jakarta.json:1.1.6") + implementation("jakarta.json:jakarta.json-api:1.1.6") + } + + extraJavaModuleInfo { + module("org.glassfish:jakarta.json", "java.json") { + // exportAllPackages() + exportAllPackagesExcept("javax.json", "javax.json.spi", "javax.json.stream") + } + } + """ + + expect: + def result = failRun() + result.output.contains("error: package javax.json is not visible") + } + def "deriveAutomaticModuleNamesFromFileNames produces a build time error for invalid module names"() { given: buildFile << """