79 import java.util.jar.JarEntry;
80 import java.util.jar.JarFile;
81 import java.util.jar.JarOutputStream;
82 import java.util.stream.Collectors;
83 import java.util.regex.Pattern;
84 import java.util.regex.PatternSyntaxException;
85 import java.util.zip.ZipEntry;
86 import java.util.zip.ZipException;
87 import java.util.zip.ZipFile;
88
89 import jdk.internal.jmod.JmodFile;
90 import jdk.internal.jmod.JmodFile.Section;
91 import jdk.internal.joptsimple.BuiltinHelpFormatter;
92 import jdk.internal.joptsimple.NonOptionArgumentSpec;
93 import jdk.internal.joptsimple.OptionDescriptor;
94 import jdk.internal.joptsimple.OptionException;
95 import jdk.internal.joptsimple.OptionParser;
96 import jdk.internal.joptsimple.OptionSet;
97 import jdk.internal.joptsimple.OptionSpec;
98 import jdk.internal.joptsimple.ValueConverter;
99 import jdk.internal.loader.ResourceHelper;
100 import jdk.internal.module.ModuleHashes;
101 import jdk.internal.module.ModuleHashesBuilder;
102 import jdk.internal.module.ModuleInfo;
103 import jdk.internal.module.ModuleInfoExtender;
104 import jdk.internal.module.ModulePath;
105 import jdk.internal.module.ModuleResolution;
106 import jdk.tools.jlink.internal.Utils;
107
108 import static java.util.stream.Collectors.joining;
109
110 /**
111 * Implementation for the jmod tool.
112 */
113 public class JmodTask {
114
115 static class CommandException extends RuntimeException {
116 private static final long serialVersionUID = 0L;
117 boolean showUsage;
118
119 CommandException(String key, Object... args) {
120 super(getMessageOrKey(key, args));
121 }
122
123 CommandException showUsage(boolean b) {
124 showUsage = b;
125 return this;
161 };
162
163 static class Options {
164 Mode mode;
165 Path jmodFile;
166 boolean help;
167 boolean helpExtra;
168 boolean version;
169 List<Path> classpath;
170 List<Path> cmds;
171 List<Path> configs;
172 List<Path> libs;
173 List<Path> headerFiles;
174 List<Path> manPages;
175 List<Path> legalNotices;;
176 ModuleFinder moduleFinder;
177 Version moduleVersion;
178 String mainClass;
179 String osName;
180 String osArch;
181 String osVersion;
182 Pattern modulesToHash;
183 ModuleResolution moduleResolution;
184 boolean dryrun;
185 List<PathMatcher> excludes;
186 Path extractDir;
187 }
188
189 public int run(String[] args) {
190
191 try {
192 handleOptions(args);
193 if (options == null) {
194 showUsageSummary();
195 return EXIT_CMDERR;
196 }
197 if (options.help || options.helpExtra) {
198 showHelp();
199 return EXIT_OK;
200 }
201 if (options.version) {
294 out.format("%s%n", mn);
295 hashes.names().stream()
296 .sorted()
297 .forEach(name -> out.format(" hashes %s %s %s%n",
298 name, hashes.algorithm(), toHex(hashes.hashFor(name))));
299 } else {
300 try {
301 hasher.updateModuleInfo(mn, hashes);
302 } catch (IOException ex) {
303 throw new UncheckedIOException(ex);
304 }
305 }
306 });
307 return true;
308 }
309
310 private boolean describe() throws IOException {
311 try (JmodFile jf = new JmodFile(options.jmodFile)) {
312 try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
313 ModuleInfo.Attributes attrs = ModuleInfo.read(in, null);
314 printModuleDescriptor(attrs.descriptor(), attrs.recordedHashes());
315 return true;
316 } catch (IOException e) {
317 throw new CommandException("err.module.descriptor.not.found");
318 }
319 }
320 }
321
322 static <T> String toString(Collection<T> c) {
323 if (c.isEmpty()) { return ""; }
324 return c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
325 .collect(joining(" "));
326 }
327
328 private void printModuleDescriptor(ModuleDescriptor md, ModuleHashes hashes)
329 throws IOException
330 {
331 StringBuilder sb = new StringBuilder();
332 sb.append("\n").append(md.toNameAndVersion());
333
334 md.requires().stream()
335 .sorted(Comparator.comparing(Requires::name))
336 .forEach(r -> {
337 sb.append("\n requires ");
338 if (!r.modifiers().isEmpty())
339 sb.append(toString(r.modifiers())).append(" ");
340 sb.append(r.name());
341 });
342
343 md.uses().stream().sorted()
344 .forEach(s -> sb.append("\n uses ").append(s));
345
346 md.exports().stream()
347 .sorted(Comparator.comparing(Exports::source))
348 .forEach(p -> sb.append("\n exports ").append(p));
349
350 md.opens().stream()
351 .sorted(Comparator.comparing(Opens::source))
352 .forEach(p -> sb.append("\n opens ").append(p));
353
354 Set<String> concealed = new HashSet<>(md.packages());
355 md.exports().stream().map(Exports::source).forEach(concealed::remove);
356 md.opens().stream().map(Opens::source).forEach(concealed::remove);
357 concealed.stream().sorted()
358 .forEach(p -> sb.append("\n contains ").append(p));
359
360 md.provides().stream()
361 .sorted(Comparator.comparing(Provides::service))
362 .forEach(p -> sb.append("\n provides ").append(p.service())
363 .append(" with ")
364 .append(toString(p.providers())));
365
366 md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
367
368 md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v));
369
370 md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v));
371
372 md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v));
373
374 if (hashes != null) {
375 hashes.names().stream().sorted().forEach(
376 mod -> sb.append("\n hashes ").append(mod).append(" ")
377 .append(hashes.algorithm()).append(" ")
378 .append(toHex(hashes.hashFor(mod))));
379 }
380
381 out.println(sb.toString());
382 }
383
384 private String toHex(byte[] ba) {
385 StringBuilder sb = new StringBuilder(ba.length);
386 for (byte b: ba) {
387 sb.append(String.format("%02x", b & 0xff));
388 }
389 return sb.toString();
390 }
391
392 private boolean create() throws IOException {
415 /*
416 * Create a JMOD .tmp file for the given target JMOD file
417 */
418 private static Path jmodTempFilePath(Path target) throws IOException {
419 return target.resolveSibling("." + target.getFileName() + ".tmp");
420 }
421
422 private class JmodFileWriter {
423 final List<Path> cmds = options.cmds;
424 final List<Path> libs = options.libs;
425 final List<Path> configs = options.configs;
426 final List<Path> classpath = options.classpath;
427 final List<Path> headerFiles = options.headerFiles;
428 final List<Path> manPages = options.manPages;
429 final List<Path> legalNotices = options.legalNotices;
430
431 final Version moduleVersion = options.moduleVersion;
432 final String mainClass = options.mainClass;
433 final String osName = options.osName;
434 final String osArch = options.osArch;
435 final String osVersion = options.osVersion;
436 final List<PathMatcher> excludes = options.excludes;
437 final ModuleResolution moduleResolution = options.moduleResolution;
438
439 JmodFileWriter() { }
440
441 /**
442 * Writes the jmod to the given output stream.
443 */
444 void write(JmodOutputStream out) throws IOException {
445 // module-info.class
446 writeModuleInfo(out, findPackages(classpath));
447
448 // classes
449 processClasses(out, classpath);
450
451 processSection(out, Section.CONFIG, configs);
452 processSection(out, Section.HEADER_FILES, headerFiles);
453 processSection(out, Section.LEGAL_NOTICES, legalNotices);
454 processSection(out, Section.MAN_PAGES, manPages);
455 processSection(out, Section.NATIVE_CMDS, cmds);
511 ModuleDescriptor descriptor;
512 try (InputStream in = miSupplier.get()) {
513 descriptor = ModuleDescriptor.read(in);
514 }
515
516 // copy the module-info.class into the jmod with the additional
517 // attributes for the version, main class and other meta data
518 try (InputStream in = miSupplier.get()) {
519 ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
520
521 // Add (or replace) the Packages attribute
522 if (packages != null) {
523 validatePackages(descriptor, packages);
524 extender.packages(packages);
525 }
526
527 // --main-class
528 if (mainClass != null)
529 extender.mainClass(mainClass);
530
531 // --os-name, --os-arch, --os-version
532 if (osName != null || osArch != null || osVersion != null)
533 extender.targetPlatform(osName, osArch, osVersion);
534
535 // --module-version
536 if (moduleVersion != null)
537 extender.version(moduleVersion);
538
539 // --hash-modules
540 if (options.modulesToHash != null) {
541 // To compute hashes, it creates a Configuration to resolve
542 // a module graph. The post-resolution check requires
543 // the packages in ModuleDescriptor be available for validation.
544 ModuleDescriptor md;
545 try (InputStream is = miSupplier.get()) {
546 md = ModuleDescriptor.read(is, () -> packages);
547 }
548
549 ModuleHashes moduleHashes = computeHashes(md);
550 if (moduleHashes != null) {
551 extender.hashes(moduleHashes);
552 } else {
553 warning("warn.no.module.hashes", descriptor.name());
658 }
659
660 /**
661 * Returns the set of packages in the given JAR file.
662 */
663 Set<String> findPackages(JarFile jf) {
664 return jf.stream()
665 .filter(e -> !e.isDirectory() && isResource(e.getName()))
666 .map(e -> toPackageName(e))
667 .filter(pkg -> pkg.length() > 0)
668 .distinct()
669 .collect(Collectors.toSet());
670 }
671
672 /**
673 * Returns true if it's a .class or a resource with an effective
674 * package name.
675 */
676 boolean isResource(String name) {
677 name = name.replace(File.separatorChar, '/');
678 return name.endsWith(".class") || !ResourceHelper.isSimpleResource(name);
679 }
680
681
682 String toPackageName(Path path) {
683 String name = path.toString();
684 int index = name.lastIndexOf(File.separatorChar);
685 if (index != -1)
686 return name.substring(0, index).replace(File.separatorChar, '.');
687
688 if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
689 IOException e = new IOException(name + " in the unnamed package");
690 throw new UncheckedIOException(e);
691 }
692 return "";
693 }
694
695 String toPackageName(ZipEntry entry) {
696 String name = entry.getName();
697 int index = name.lastIndexOf("/");
698 if (index != -1)
1314 = parser.acceptsAll(Set.of("p", "module-path"),
1315 getMessage("main.opt.module-path"))
1316 .withRequiredArg()
1317 .withValuesConvertedBy(DirPathConverter.INSTANCE);
1318
1319 OptionSpec<Version> moduleVersion
1320 = parser.accepts("module-version", getMessage("main.opt.module-version"))
1321 .withRequiredArg()
1322 .withValuesConvertedBy(new ModuleVersionConverter());
1323
1324 OptionSpec<String> osName
1325 = parser.accepts("os-name", getMessage("main.opt.os-name"))
1326 .withRequiredArg()
1327 .describedAs(getMessage("main.opt.os-name.arg"));
1328
1329 OptionSpec<String> osArch
1330 = parser.accepts("os-arch", getMessage("main.opt.os-arch"))
1331 .withRequiredArg()
1332 .describedAs(getMessage("main.opt.os-arch.arg"));
1333
1334 OptionSpec<String> osVersion
1335 = parser.accepts("os-version", getMessage("main.opt.os-version"))
1336 .withRequiredArg()
1337 .describedAs(getMessage("main.opt.os-version.arg"));
1338
1339 OptionSpec<Void> doNotResolveByDefault
1340 = parser.accepts("do-not-resolve-by-default",
1341 getMessage("main.opt.do-not-resolve-by-default"));
1342
1343 OptionSpec<ModuleResolution> warnIfResolved
1344 = parser.accepts("warn-if-resolved", getMessage("main.opt.warn-if-resolved"))
1345 .withRequiredArg()
1346 .withValuesConvertedBy(new WarnIfResolvedReasonConverter());
1347
1348 OptionSpec<Void> version
1349 = parser.accepts("version", getMessage("main.opt.version"));
1350
1351 NonOptionArgumentSpec<String> nonOptions
1352 = parser.nonOptions();
1353
1354 try {
1355 OptionSet opts = parser.parse(args);
1356
1357 if (opts.has(help) || opts.has(helpExtra) || opts.has(version)) {
1358 options.help = opts.has(help);
1386 if (opts.has(libs))
1387 options.libs = getLastElement(opts.valuesOf(libs));
1388 if (opts.has(headerFiles))
1389 options.headerFiles = getLastElement(opts.valuesOf(headerFiles));
1390 if (opts.has(manPages))
1391 options.manPages = getLastElement(opts.valuesOf(manPages));
1392 if (opts.has(legalNotices))
1393 options.legalNotices = getLastElement(opts.valuesOf(legalNotices));
1394 if (opts.has(modulePath)) {
1395 Path[] dirs = getLastElement(opts.valuesOf(modulePath)).toArray(new Path[0]);
1396 options.moduleFinder = ModulePath.of(Runtime.version(), true, dirs);
1397 }
1398 if (opts.has(moduleVersion))
1399 options.moduleVersion = getLastElement(opts.valuesOf(moduleVersion));
1400 if (opts.has(mainClass))
1401 options.mainClass = getLastElement(opts.valuesOf(mainClass));
1402 if (opts.has(osName))
1403 options.osName = getLastElement(opts.valuesOf(osName));
1404 if (opts.has(osArch))
1405 options.osArch = getLastElement(opts.valuesOf(osArch));
1406 if (opts.has(osVersion))
1407 options.osVersion = getLastElement(opts.valuesOf(osVersion));
1408 if (opts.has(warnIfResolved))
1409 options.moduleResolution = getLastElement(opts.valuesOf(warnIfResolved));
1410 if (opts.has(doNotResolveByDefault)) {
1411 if (options.moduleResolution == null)
1412 options.moduleResolution = ModuleResolution.empty();
1413 options.moduleResolution = options.moduleResolution.withDoNotResolveByDefault();
1414 }
1415 if (opts.has(hashModules)) {
1416 options.modulesToHash = getLastElement(opts.valuesOf(hashModules));
1417 // if storing hashes then the module path is required
1418 if (options.moduleFinder == null)
1419 throw new CommandException("err.modulepath.must.be.specified")
1420 .showUsage(true);
1421 }
1422
1423 if (options.mode.equals(Mode.HASH)) {
1424 if (options.moduleFinder == null || options.modulesToHash == null)
1425 throw new CommandException("err.modulepath.must.be.specified")
1426 .showUsage(true);
1427 } else {
|
79 import java.util.jar.JarEntry;
80 import java.util.jar.JarFile;
81 import java.util.jar.JarOutputStream;
82 import java.util.stream.Collectors;
83 import java.util.regex.Pattern;
84 import java.util.regex.PatternSyntaxException;
85 import java.util.zip.ZipEntry;
86 import java.util.zip.ZipException;
87 import java.util.zip.ZipFile;
88
89 import jdk.internal.jmod.JmodFile;
90 import jdk.internal.jmod.JmodFile.Section;
91 import jdk.internal.joptsimple.BuiltinHelpFormatter;
92 import jdk.internal.joptsimple.NonOptionArgumentSpec;
93 import jdk.internal.joptsimple.OptionDescriptor;
94 import jdk.internal.joptsimple.OptionException;
95 import jdk.internal.joptsimple.OptionParser;
96 import jdk.internal.joptsimple.OptionSet;
97 import jdk.internal.joptsimple.OptionSpec;
98 import jdk.internal.joptsimple.ValueConverter;
99 import jdk.internal.module.ModuleHashes;
100 import jdk.internal.module.ModuleHashesBuilder;
101 import jdk.internal.module.ModuleInfo;
102 import jdk.internal.module.ModuleInfoExtender;
103 import jdk.internal.module.ModulePath;
104 import jdk.internal.module.ModuleResolution;
105 import jdk.internal.module.ModuleTarget;
106 import jdk.internal.module.Resources;
107 import jdk.tools.jlink.internal.Utils;
108
109 import static java.util.stream.Collectors.joining;
110
111 /**
112 * Implementation for the jmod tool.
113 */
114 public class JmodTask {
115
116 static class CommandException extends RuntimeException {
117 private static final long serialVersionUID = 0L;
118 boolean showUsage;
119
120 CommandException(String key, Object... args) {
121 super(getMessageOrKey(key, args));
122 }
123
124 CommandException showUsage(boolean b) {
125 showUsage = b;
126 return this;
162 };
163
164 static class Options {
165 Mode mode;
166 Path jmodFile;
167 boolean help;
168 boolean helpExtra;
169 boolean version;
170 List<Path> classpath;
171 List<Path> cmds;
172 List<Path> configs;
173 List<Path> libs;
174 List<Path> headerFiles;
175 List<Path> manPages;
176 List<Path> legalNotices;;
177 ModuleFinder moduleFinder;
178 Version moduleVersion;
179 String mainClass;
180 String osName;
181 String osArch;
182 Pattern modulesToHash;
183 ModuleResolution moduleResolution;
184 boolean dryrun;
185 List<PathMatcher> excludes;
186 Path extractDir;
187 }
188
189 public int run(String[] args) {
190
191 try {
192 handleOptions(args);
193 if (options == null) {
194 showUsageSummary();
195 return EXIT_CMDERR;
196 }
197 if (options.help || options.helpExtra) {
198 showHelp();
199 return EXIT_OK;
200 }
201 if (options.version) {
294 out.format("%s%n", mn);
295 hashes.names().stream()
296 .sorted()
297 .forEach(name -> out.format(" hashes %s %s %s%n",
298 name, hashes.algorithm(), toHex(hashes.hashFor(name))));
299 } else {
300 try {
301 hasher.updateModuleInfo(mn, hashes);
302 } catch (IOException ex) {
303 throw new UncheckedIOException(ex);
304 }
305 }
306 });
307 return true;
308 }
309
310 private boolean describe() throws IOException {
311 try (JmodFile jf = new JmodFile(options.jmodFile)) {
312 try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
313 ModuleInfo.Attributes attrs = ModuleInfo.read(in, null);
314 printModuleDescriptor(attrs.descriptor(),
315 attrs.target(),
316 attrs.recordedHashes());
317 return true;
318 } catch (IOException e) {
319 throw new CommandException("err.module.descriptor.not.found");
320 }
321 }
322 }
323
324 static <T> String toString(Collection<T> c) {
325 if (c.isEmpty()) { return ""; }
326 return c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
327 .collect(joining(" "));
328 }
329
330 private void printModuleDescriptor(ModuleDescriptor md,
331 ModuleTarget target,
332 ModuleHashes hashes)
333 throws IOException
334 {
335 StringBuilder sb = new StringBuilder();
336 sb.append("\n").append(md.toNameAndVersion());
337
338 md.requires().stream()
339 .sorted(Comparator.comparing(Requires::name))
340 .forEach(r -> {
341 sb.append("\n requires ");
342 if (!r.modifiers().isEmpty())
343 sb.append(toString(r.modifiers())).append(" ");
344 sb.append(r.name());
345 });
346
347 md.uses().stream().sorted()
348 .forEach(s -> sb.append("\n uses ").append(s));
349
350 md.exports().stream()
351 .sorted(Comparator.comparing(Exports::source))
352 .forEach(p -> sb.append("\n exports ").append(p));
353
354 md.opens().stream()
355 .sorted(Comparator.comparing(Opens::source))
356 .forEach(p -> sb.append("\n opens ").append(p));
357
358 Set<String> concealed = new HashSet<>(md.packages());
359 md.exports().stream().map(Exports::source).forEach(concealed::remove);
360 md.opens().stream().map(Opens::source).forEach(concealed::remove);
361 concealed.stream().sorted()
362 .forEach(p -> sb.append("\n contains ").append(p));
363
364 md.provides().stream()
365 .sorted(Comparator.comparing(Provides::service))
366 .forEach(p -> sb.append("\n provides ").append(p.service())
367 .append(" with ")
368 .append(toString(p.providers())));
369
370 md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
371
372 if (target != null) {
373 String osName = target.osName();
374 if (osName != null)
375 sb.append("\n operating-system-name " + osName);
376 String osArch = target.osArch();
377 if (osArch != null)
378 sb.append("\n operating-system-architecture " + osArch);
379 }
380
381 if (hashes != null) {
382 hashes.names().stream().sorted().forEach(
383 mod -> sb.append("\n hashes ").append(mod).append(" ")
384 .append(hashes.algorithm()).append(" ")
385 .append(toHex(hashes.hashFor(mod))));
386 }
387
388 out.println(sb.toString());
389 }
390
391 private String toHex(byte[] ba) {
392 StringBuilder sb = new StringBuilder(ba.length);
393 for (byte b: ba) {
394 sb.append(String.format("%02x", b & 0xff));
395 }
396 return sb.toString();
397 }
398
399 private boolean create() throws IOException {
422 /*
423 * Create a JMOD .tmp file for the given target JMOD file
424 */
425 private static Path jmodTempFilePath(Path target) throws IOException {
426 return target.resolveSibling("." + target.getFileName() + ".tmp");
427 }
428
429 private class JmodFileWriter {
430 final List<Path> cmds = options.cmds;
431 final List<Path> libs = options.libs;
432 final List<Path> configs = options.configs;
433 final List<Path> classpath = options.classpath;
434 final List<Path> headerFiles = options.headerFiles;
435 final List<Path> manPages = options.manPages;
436 final List<Path> legalNotices = options.legalNotices;
437
438 final Version moduleVersion = options.moduleVersion;
439 final String mainClass = options.mainClass;
440 final String osName = options.osName;
441 final String osArch = options.osArch;
442 final List<PathMatcher> excludes = options.excludes;
443 final ModuleResolution moduleResolution = options.moduleResolution;
444
445 JmodFileWriter() { }
446
447 /**
448 * Writes the jmod to the given output stream.
449 */
450 void write(JmodOutputStream out) throws IOException {
451 // module-info.class
452 writeModuleInfo(out, findPackages(classpath));
453
454 // classes
455 processClasses(out, classpath);
456
457 processSection(out, Section.CONFIG, configs);
458 processSection(out, Section.HEADER_FILES, headerFiles);
459 processSection(out, Section.LEGAL_NOTICES, legalNotices);
460 processSection(out, Section.MAN_PAGES, manPages);
461 processSection(out, Section.NATIVE_CMDS, cmds);
517 ModuleDescriptor descriptor;
518 try (InputStream in = miSupplier.get()) {
519 descriptor = ModuleDescriptor.read(in);
520 }
521
522 // copy the module-info.class into the jmod with the additional
523 // attributes for the version, main class and other meta data
524 try (InputStream in = miSupplier.get()) {
525 ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
526
527 // Add (or replace) the Packages attribute
528 if (packages != null) {
529 validatePackages(descriptor, packages);
530 extender.packages(packages);
531 }
532
533 // --main-class
534 if (mainClass != null)
535 extender.mainClass(mainClass);
536
537 // --os-name, --os-arch
538 if (osName != null || osArch != null)
539 extender.targetPlatform(osName, osArch);
540
541 // --module-version
542 if (moduleVersion != null)
543 extender.version(moduleVersion);
544
545 // --hash-modules
546 if (options.modulesToHash != null) {
547 // To compute hashes, it creates a Configuration to resolve
548 // a module graph. The post-resolution check requires
549 // the packages in ModuleDescriptor be available for validation.
550 ModuleDescriptor md;
551 try (InputStream is = miSupplier.get()) {
552 md = ModuleDescriptor.read(is, () -> packages);
553 }
554
555 ModuleHashes moduleHashes = computeHashes(md);
556 if (moduleHashes != null) {
557 extender.hashes(moduleHashes);
558 } else {
559 warning("warn.no.module.hashes", descriptor.name());
664 }
665
666 /**
667 * Returns the set of packages in the given JAR file.
668 */
669 Set<String> findPackages(JarFile jf) {
670 return jf.stream()
671 .filter(e -> !e.isDirectory() && isResource(e.getName()))
672 .map(e -> toPackageName(e))
673 .filter(pkg -> pkg.length() > 0)
674 .distinct()
675 .collect(Collectors.toSet());
676 }
677
678 /**
679 * Returns true if it's a .class or a resource with an effective
680 * package name.
681 */
682 boolean isResource(String name) {
683 name = name.replace(File.separatorChar, '/');
684 return name.endsWith(".class") || Resources.canEncapsulate(name);
685 }
686
687
688 String toPackageName(Path path) {
689 String name = path.toString();
690 int index = name.lastIndexOf(File.separatorChar);
691 if (index != -1)
692 return name.substring(0, index).replace(File.separatorChar, '.');
693
694 if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
695 IOException e = new IOException(name + " in the unnamed package");
696 throw new UncheckedIOException(e);
697 }
698 return "";
699 }
700
701 String toPackageName(ZipEntry entry) {
702 String name = entry.getName();
703 int index = name.lastIndexOf("/");
704 if (index != -1)
1320 = parser.acceptsAll(Set.of("p", "module-path"),
1321 getMessage("main.opt.module-path"))
1322 .withRequiredArg()
1323 .withValuesConvertedBy(DirPathConverter.INSTANCE);
1324
1325 OptionSpec<Version> moduleVersion
1326 = parser.accepts("module-version", getMessage("main.opt.module-version"))
1327 .withRequiredArg()
1328 .withValuesConvertedBy(new ModuleVersionConverter());
1329
1330 OptionSpec<String> osName
1331 = parser.accepts("os-name", getMessage("main.opt.os-name"))
1332 .withRequiredArg()
1333 .describedAs(getMessage("main.opt.os-name.arg"));
1334
1335 OptionSpec<String> osArch
1336 = parser.accepts("os-arch", getMessage("main.opt.os-arch"))
1337 .withRequiredArg()
1338 .describedAs(getMessage("main.opt.os-arch.arg"));
1339
1340 OptionSpec<Void> doNotResolveByDefault
1341 = parser.accepts("do-not-resolve-by-default",
1342 getMessage("main.opt.do-not-resolve-by-default"));
1343
1344 OptionSpec<ModuleResolution> warnIfResolved
1345 = parser.accepts("warn-if-resolved", getMessage("main.opt.warn-if-resolved"))
1346 .withRequiredArg()
1347 .withValuesConvertedBy(new WarnIfResolvedReasonConverter());
1348
1349 OptionSpec<Void> version
1350 = parser.accepts("version", getMessage("main.opt.version"));
1351
1352 NonOptionArgumentSpec<String> nonOptions
1353 = parser.nonOptions();
1354
1355 try {
1356 OptionSet opts = parser.parse(args);
1357
1358 if (opts.has(help) || opts.has(helpExtra) || opts.has(version)) {
1359 options.help = opts.has(help);
1387 if (opts.has(libs))
1388 options.libs = getLastElement(opts.valuesOf(libs));
1389 if (opts.has(headerFiles))
1390 options.headerFiles = getLastElement(opts.valuesOf(headerFiles));
1391 if (opts.has(manPages))
1392 options.manPages = getLastElement(opts.valuesOf(manPages));
1393 if (opts.has(legalNotices))
1394 options.legalNotices = getLastElement(opts.valuesOf(legalNotices));
1395 if (opts.has(modulePath)) {
1396 Path[] dirs = getLastElement(opts.valuesOf(modulePath)).toArray(new Path[0]);
1397 options.moduleFinder = ModulePath.of(Runtime.version(), true, dirs);
1398 }
1399 if (opts.has(moduleVersion))
1400 options.moduleVersion = getLastElement(opts.valuesOf(moduleVersion));
1401 if (opts.has(mainClass))
1402 options.mainClass = getLastElement(opts.valuesOf(mainClass));
1403 if (opts.has(osName))
1404 options.osName = getLastElement(opts.valuesOf(osName));
1405 if (opts.has(osArch))
1406 options.osArch = getLastElement(opts.valuesOf(osArch));
1407 if (opts.has(warnIfResolved))
1408 options.moduleResolution = getLastElement(opts.valuesOf(warnIfResolved));
1409 if (opts.has(doNotResolveByDefault)) {
1410 if (options.moduleResolution == null)
1411 options.moduleResolution = ModuleResolution.empty();
1412 options.moduleResolution = options.moduleResolution.withDoNotResolveByDefault();
1413 }
1414 if (opts.has(hashModules)) {
1415 options.modulesToHash = getLastElement(opts.valuesOf(hashModules));
1416 // if storing hashes then the module path is required
1417 if (options.moduleFinder == null)
1418 throw new CommandException("err.modulepath.must.be.specified")
1419 .showUsage(true);
1420 }
1421
1422 if (options.mode.equals(Mode.HASH)) {
1423 if (options.moduleFinder == null || options.modulesToHash == null)
1424 throw new CommandException("err.modulepath.must.be.specified")
1425 .showUsage(true);
1426 } else {
|