8176772: jar tool support to report automatic module names
authorchegar
Thu, 16 Mar 2017 16:56:08 +0000
changeset 44267 00898a596f31
parent 44266 2b9cc0e5e79f
child 44268 1ec855c8a7d4
8176772: jar tool support to report automatic module names Reviewed-by: alanb, mchung
jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java
jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
jdk/test/tools/jar/modularJar/Basic.java
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java	Thu Mar 16 08:58:31 2017 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java	Thu Mar 16 16:56:08 2017 +0000
@@ -95,7 +95,7 @@
                     tool.xflag = true;
                 }
             },
-            new Option(false, OptionType.MAIN_OPERATION, "--print-module-descriptor", "-d") {
+            new Option(false, OptionType.MAIN_OPERATION, "--describe-module", "-d") {
                 void process(Main tool, String opt, String arg) throws BadArgs {
                     if (tool.cflag || tool.iflag  || tool.tflag || tool.uflag || tool.xflag)
                         throw new BadArgs("error.multiple.main.operations").showUsage(true);
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Thu Mar 16 08:58:31 2017 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Thu Mar 16 16:56:08 2017 +0000
@@ -27,6 +27,7 @@
 
 import java.io.*;
 import java.lang.module.Configuration;
+import java.lang.module.FindException;
 import java.lang.module.InvalidModuleDescriptorException;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
@@ -407,11 +408,11 @@
                 boolean found;
                 if (fname != null) {
                     try (ZipFile zf = new ZipFile(fname)) {
-                        found = printModuleDescriptor(zf);
+                        found = describeModule(zf);
                     }
                 } else {
                     try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
-                        found = printModuleDescriptor(fin);
+                        found = describeModule(fin);
                     }
                 }
                 if (!found)
@@ -603,7 +604,7 @@
         int n = args.length - count;
         if (n > 0) {
             if (dflag) {
-                // "--print-module-descriptor/-d" does not require file argument(s)
+                // "--describe-module/-d" does not require file argument(s)
                 usageError(formatMsg("error.bad.dflag", args[count]));
                 return false;
             }
@@ -1728,24 +1729,43 @@
                            .collect(joining(", ", prefix, suffix));
     }
 
-    private boolean printModuleDescriptor(ZipFile zipFile)
-        throws IOException
-    {
+    private boolean describeModule(ZipFile zipFile) throws IOException {
         ZipEntry[] zes = zipFile.stream()
             .filter(e -> isModuleInfoEntry(e.getName()))
             .sorted(Validator.ENTRY_COMPARATOR)
             .toArray(ZipEntry[]::new);
-        if (zes.length == 0)
-            return false;
-        for (ZipEntry ze : zes) {
-            try (InputStream is = zipFile.getInputStream(ze)) {
-                printModuleDescriptor(is, ze.getName());
+
+        if (zes.length == 0) {
+            // No module descriptor found, derive the automatic module name
+            String fn = zipFile.getName();
+            ModuleFinder mf = ModuleFinder.of(Paths.get(fn));
+            try {
+                Set<ModuleReference> mref = mf.findAll();
+                if (mref.isEmpty()) {
+                    output(formatMsg("error.unable.derive.automodule", fn));
+                    return true;
+                }
+                ModuleDescriptor md = mref.iterator().next().descriptor();
+                output(getMsg("out.automodule"));
+                describeModule(md, null, "automatic");
+            } catch (FindException e) {
+                String msg = formatMsg("error.unable.derive.automodule", fn);
+                Throwable t = e.getCause();
+                if (t != null)
+                    msg = msg + "\n" + t.getMessage();
+                output(msg);
+            }
+        } else {
+            for (ZipEntry ze : zes) {
+                try (InputStream is = zipFile.getInputStream(ze)) {
+                    describeModule(is, ze.getName());
+                }
             }
         }
         return true;
     }
 
-    private boolean printModuleDescriptor(FileInputStream fis)
+    private boolean describeModule(FileInputStream fis)
         throws IOException
     {
         try (BufferedInputStream bis = new BufferedInputStream(fis);
@@ -1764,7 +1784,7 @@
             .sorted(Validator.ENTRYNAME_COMPARATOR)
             .toArray(String[]::new);
         for (String name : names) {
-            printModuleDescriptor(new ByteArrayInputStream(moduleInfos.get(name)), name);
+            describeModule(new ByteArrayInputStream(moduleInfos.get(name)), name);
         }
         return true;
     }
@@ -1775,13 +1795,21 @@
                   .collect(joining(" "));
     }
 
-    private void printModuleDescriptor(InputStream entryInputStream, String ename)
+    private void describeModule(InputStream entryInputStream, String ename)
         throws IOException
     {
         ModuleInfo.Attributes attrs = ModuleInfo.read(entryInputStream, null);
         ModuleDescriptor md = attrs.descriptor();
         ModuleHashes hashes = attrs.recordedHashes();
 
+        describeModule(md, hashes, ename);
+    }
+
+    private void describeModule(ModuleDescriptor md,
+                                ModuleHashes hashes,
+                                String ename)
+        throws IOException
+    {
         StringBuilder sb = new StringBuilder();
         sb.append("\nmodule ")
           .append(md.toNameAndVersion())
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Thu Mar 16 08:58:31 2017 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Thu Mar 16 16:56:08 2017 +0000
@@ -45,7 +45,7 @@
 	'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
 	 together!
 error.bad.dflag=\
-        '-d, --print-module-descriptor' option requires no input file(s) to be specified: {0}
+        '-d, --describe-module' option requires no input file(s) to be specified: {0}
 error.bad.reason=\
         bad reason: {0}, must be one of deprecated, deprecated-for-removal, or incubating
 error.nosuch.fileordir=\
@@ -62,6 +62,8 @@
         Hashing module {0} dependences, unable to find module {1} on module path
 error.module.options.without.info=\
         One of --module-version or --hash-modules without module-info.class
+error.unable.derive.automodule=\
+        Unable to derive module descriptor for: {0}
 error.unexpected.module-info=\
         Unexpected module descriptor {0}
 error.module.descriptor.not.found=\
@@ -129,6 +131,8 @@
         added manifest
 out.added.module-info=\
         added module-info: {0}
+out.automodule=\
+        No module descriptor found. Derived automatic module.
 out.update.manifest=\
         updated manifest
 out.update.module-info=\
@@ -224,8 +228,8 @@
 \  -u, --update               Update an existing jar archive
 main.help.opt.main.extract=\
 \  -x, --extract              Extract named (or all) files from the archive
-main.help.opt.main.print-module-descriptor=\
-\  -d, --print-module-descriptor  Print the module descriptor
+main.help.opt.main.describe-module=\
+\  -d, --describe-module      Print the module descriptor, or automatic module name
 main.help.opt.any=\
 \ Operation modifiers valid in any mode:\n\
 \n\
--- a/jdk/test/tools/jar/modularJar/Basic.java	Thu Mar 16 08:58:31 2017 -0700
+++ b/jdk/test/tools/jar/modularJar/Basic.java	Thu Mar 16 16:56:08 2017 +0000
@@ -39,6 +39,7 @@
 import jdk.testlibrary.FileUtils;
 import jdk.testlibrary.JDKToolFinder;
 import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import static java.lang.String.format;
@@ -46,7 +47,7 @@
 
 /*
  * @test
- * @bug 8167328 8171830 8165640 8174248
+ * @bug 8167328 8171830 8165640 8174248 8176772
  * @library /lib/testlibrary
  * @modules jdk.compiler
  *          jdk.jartool
@@ -754,7 +755,7 @@
             .assertSuccess();
 
 
-        for (String option : new String[]  {"--print-module-descriptor", "-d" }) {
+        for (String option : new String[]  {"--describe-module", "-d" }) {
 
             jar(option,
                 "--file=" + modularJar.toString())
@@ -801,8 +802,8 @@
     }
 
     @Test
-    public void printModuleDescriptorFoo() throws IOException {
-        Path mp = Paths.get("printModuleDescriptorFoo");
+    public void describeModuleFoo() throws IOException {
+        Path mp = Paths.get("describeModuleFoo");
         createTestDir(mp);
         Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
         Path modularJar = mp.resolve(FOO.moduleName + ".jar");
@@ -815,7 +816,7 @@
             "-C", modClasses.toString(), ".")
             .assertSuccess();
 
-        for (String option : new String[]  {"--print-module-descriptor", "-d" }) {
+        for (String option : new String[]  {"--describe-module", "-d" }) {
             jar(option,
                 "--file=" + modularJar.toString())
                 .assertSuccess()
@@ -836,8 +837,8 @@
     }
 
     @Test
-    public void printModuleDescriptorFooFromStdin() throws IOException {
-        Path mp = Paths.get("printModuleDescriptorFooFromStdin");
+    public void describeModuleFooFromStdin() throws IOException {
+        Path mp = Paths.get("describeModuleFooFromStdin");
         createTestDir(mp);
         Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
         Path modularJar = mp.resolve(FOO.moduleName + ".jar");
@@ -850,7 +851,7 @@
             "-C", modClasses.toString(), ".")
             .assertSuccess();
 
-        for (String option : new String[]  {"--print-module-descriptor", "-d" }) {
+        for (String option : new String[]  {"--describe-module", "-d" }) {
             jarWithStdin(modularJar.toFile(),
                          option)
                          .assertSuccess()
@@ -862,6 +863,50 @@
         }
     }
 
+
+    @DataProvider(name = "autoNames")
+    public Object[][] autoNames() {
+        return new Object[][] {
+            // JAR file name                module-name[@version]
+            { "foo.jar",                    "foo" },
+            { "foo4j.jar",                  "foo4j", },
+            { "foo1.2.3.jar",               "foo" },
+            { "foo-1.2.3.4.jar",            "foo@1.2.3.4" },
+            { "foo-bar.jar",                "foo.bar" },
+            { "foo-1.2-SNAPSHOT.jar",       "foo@1.2-SNAPSHOT" },
+        };
+    }
+
+    @Test(dataProvider = "autoNames")
+    public void describeAutomaticModule(String jarName, String mid)
+        throws IOException
+    {
+        Path mp = Paths.get("describeAutomaticModule");
+        createTestDir(mp);
+        Path regularJar = mp.resolve(jarName);
+        Path t = Paths.get("t");
+        if (Files.notExists(t))
+            Files.createFile(t);
+
+        jar("--create",
+            "--file=" + regularJar.toString(),
+            t.toString())
+            .assertSuccess();
+
+        for (String option : new String[]  {"--describe-module", "-d" }) {
+            jar(option,
+                "--file=" + regularJar.toString())
+                .assertSuccess()
+                .resultChecker(r -> {
+                    assertTrue(r.output.contains("No module descriptor found"));
+                    assertTrue(r.output.contains("Derived automatic module"));
+                    assertTrue(r.output.contains("module " + mid),
+                               "Expected [", "module " + mid,"] in [", r.output, "]");
+                    }
+                );
+        }
+    }
+
     // -- Infrastructure
 
     static Result jarWithStdin(File stdinSource, String... args) {