8170618: jmod should validate if any exported or open package is missing
authorsundar
Wed, 21 Dec 2016 20:16:29 +0530
changeset 42922 9111fb672357
parent 42921 5567aa36deac
child 42923 691c320b44f7
8170618: jmod should validate if any exported or open package is missing Reviewed-by: jlaskey, chegar
jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties
jdk/test/tools/jmod/JmodTest.java
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Wed Dec 21 08:12:49 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Wed Dec 21 20:16:29 2016 +0530
@@ -74,6 +74,7 @@
 import java.util.Optional;
 import java.util.ResourceBundle;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
@@ -497,6 +498,7 @@
 
                 // Add (or replace) the Packages attribute
                 if (packages != null) {
+                    validatePackages(descriptor, packages);
                     extender.packages(packages);
                 }
 
@@ -530,6 +532,24 @@
             }
         }
 
+        private void validatePackages(ModuleDescriptor descriptor, Set<String> packages) {
+            Set<String> nonExistPackages = new TreeSet<>();
+            descriptor.exports().stream()
+                .map(Exports::source)
+                .filter(pn -> !packages.contains(pn))
+                .forEach(nonExistPackages::add);
+
+            descriptor.opens().stream()
+                .map(Opens::source)
+                .filter(pn -> !packages.contains(pn))
+                .forEach(nonExistPackages::add);
+
+            if (!nonExistPackages.isEmpty()) {
+                throw new CommandException("err.missing.export.or.open.packages",
+                    descriptor.name(), nonExistPackages);
+            }
+        }
+
         /*
          * Hasher resolves a module graph using the --hash-modules PATTERN
          * as the roots.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties	Wed Dec 21 08:12:49 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties	Wed Dec 21 20:16:29 2016 +0530
@@ -107,6 +107,7 @@
 err.internal.error=internal error: {0} {1} {2}
 err.invalid.dryrun.option=--dry-run can only be used with hash mode
 err.module.descriptor.not.found=Module descriptor not found
+err.missing.export.or.open.packages=Packages that are exported or open in {0} are not present: {1}
 warn.invalid.arg=Invalid classname or pathname not exist: {0}
 warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0}
 warn.module.resolution.fail=No hashes recorded: {0}
--- a/jdk/test/tools/jmod/JmodTest.java	Wed Dec 21 08:12:49 2016 +0000
+++ b/jdk/test/tools/jmod/JmodTest.java	Wed Dec 21 20:16:29 2016 +0530
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8142968 8166568
+ * @bug 8142968 8166568 8166286 8170618
  * @summary Basic test for jmod
  * @library /lib/testlibrary
  * @modules jdk.compiler
@@ -114,6 +114,27 @@
             .assertSuccess();
     }
 
+    // JDK-8170618 - jmod should validate if any exported or open package is missing
+    @Test
+    public void testMissingPackages() throws IOException {
+        Path apaDir = EXPLODED_DIR.resolve("apa");
+        Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes");
+        if (Files.exists(classesDir))
+            FileUtils.deleteFileTreeWithRetry(classesDir);
+        assertTrue(compileModule("apa", classesDir));
+        FileUtils.deleteFileTreeWithRetry(classesDir.resolve("jdk"));
+        Path jmod = MODS_DIR.resolve("apa.jmod");
+        jmod("create",
+             "--class-path", classesDir.toString(),
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r -> {
+                assertContains(r.output, "Packages that are exported or open in apa are not present: [jdk.test.apa]");
+            });
+        if (Files.exists(classesDir))
+            FileUtils.deleteFileTreeWithRetry(classesDir);
+    }
+
     @Test
     public void testList() throws IOException {
         String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();