< prev index next >

src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java

Print this page




  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 {


< prev index next >