8176772: jar tool support to report automatic module names
Reviewed-by: alanb, mchung
--- 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) {