< prev index next >

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

Print this page




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.tools.jmod;
  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.File;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.io.OutputStream;
  34 import java.io.PrintStream;
  35 import java.io.PrintWriter;
  36 import java.io.UncheckedIOException;
  37 import java.lang.module.Configuration;
  38 import java.lang.module.ModuleReader;
  39 import java.lang.module.ModuleReference;
  40 import java.lang.module.ModuleFinder;
  41 import java.lang.module.ModuleDescriptor;
  42 import java.lang.module.ModuleDescriptor.Exports;
  43 import java.lang.module.ModuleDescriptor.Opens;
  44 import java.lang.module.ModuleDescriptor.Provides;
  45 import java.lang.module.ModuleDescriptor.Requires;
  46 import java.lang.module.ModuleDescriptor.Version;
  47 import java.lang.module.ResolutionException;
  48 import java.lang.module.ResolvedModule;
  49 import java.net.URI;
  50 import java.nio.file.FileSystems;
  51 import java.nio.file.FileVisitOption;
  52 import java.nio.file.FileVisitResult;
  53 import java.nio.file.Files;
  54 import java.nio.file.InvalidPathException;


  67 import java.util.Deque;
  68 import java.util.HashMap;
  69 import java.util.HashSet;
  70 import java.util.List;
  71 import java.util.Locale;
  72 import java.util.Map;
  73 import java.util.MissingResourceException;
  74 import java.util.Optional;
  75 import java.util.ResourceBundle;
  76 import java.util.Set;
  77 import java.util.function.Consumer;
  78 import java.util.function.Function;
  79 import java.util.function.Predicate;
  80 import java.util.function.Supplier;
  81 import java.util.jar.JarEntry;
  82 import java.util.jar.JarFile;
  83 import java.util.jar.JarOutputStream;
  84 import java.util.stream.Collectors;
  85 import java.util.regex.Pattern;
  86 import java.util.regex.PatternSyntaxException;
  87 import java.util.stream.Stream;
  88 import java.util.zip.ZipEntry;
  89 import java.util.zip.ZipException;
  90 import java.util.zip.ZipFile;
  91 
  92 import jdk.internal.jmod.JmodFile;
  93 import jdk.internal.jmod.JmodFile.Section;
  94 import jdk.internal.joptsimple.BuiltinHelpFormatter;
  95 import jdk.internal.joptsimple.NonOptionArgumentSpec;
  96 import jdk.internal.joptsimple.OptionDescriptor;
  97 import jdk.internal.joptsimple.OptionException;
  98 import jdk.internal.joptsimple.OptionParser;
  99 import jdk.internal.joptsimple.OptionSet;
 100 import jdk.internal.joptsimple.OptionSpec;
 101 import jdk.internal.joptsimple.ValueConverter;
 102 import jdk.internal.loader.ResourceHelper;
 103 import jdk.internal.misc.JavaLangModuleAccess;
 104 import jdk.internal.misc.SharedSecrets;
 105 import jdk.internal.module.ModuleHashes;
 106 import jdk.internal.module.ModuleInfoExtender;
 107 import jdk.tools.jlink.internal.Utils;


 152                      EXIT_ABNORMAL = 4;// terminated abnormally
 153 
 154     enum Mode {
 155         CREATE,
 156         LIST,
 157         DESCRIBE,
 158         HASH
 159     };
 160 
 161     static class Options {
 162         Mode mode;
 163         Path jmodFile;
 164         boolean help;
 165         boolean version;
 166         List<Path> classpath;
 167         List<Path> cmds;
 168         List<Path> configs;
 169         List<Path> libs;
 170         List<Path> headerFiles;
 171         List<Path> manPages;

 172         ModuleFinder moduleFinder;
 173         Version moduleVersion;
 174         String mainClass;
 175         String osName;
 176         String osArch;
 177         String osVersion;
 178         Pattern modulesToHash;
 179         boolean dryrun;
 180         List<PathMatcher> excludes;
 181     }
 182 
 183     public int run(String[] args) {
 184 
 185         try {
 186             handleOptions(args);
 187             if (options == null) {
 188                 showUsageSummary();
 189                 return EXIT_CMDERR;
 190             }
 191             if (options.help) {


 342         } catch (Exception e) {
 343             if (Files.exists(tempTarget)) {
 344                 try {
 345                     Files.delete(tempTarget);
 346                 } catch (IOException ioe) {
 347                     e.addSuppressed(ioe);
 348                 }
 349             }
 350             throw e;
 351         }
 352         return true;
 353     }
 354 
 355     private class JmodFileWriter {
 356         final List<Path> cmds = options.cmds;
 357         final List<Path> libs = options.libs;
 358         final List<Path> configs = options.configs;
 359         final List<Path> classpath = options.classpath;
 360         final List<Path> headerFiles = options.headerFiles;
 361         final List<Path> manPages = options.manPages;

 362 
 363         final Version moduleVersion = options.moduleVersion;
 364         final String mainClass = options.mainClass;
 365         final String osName = options.osName;
 366         final String osArch = options.osArch;
 367         final String osVersion = options.osVersion;
 368         final List<PathMatcher> excludes = options.excludes;
 369         final Hasher hasher = hasher();
 370 
 371         JmodFileWriter() { }
 372 
 373         /**
 374          * Writes the jmod to the given output stream.
 375          */
 376         void write(JmodOutputStream out) throws IOException {
 377             // module-info.class
 378             writeModuleInfo(out, findPackages(classpath));
 379 
 380             // classes
 381             processClasses(out, classpath);
 382 
 383             processSection(out, Section.NATIVE_CMDS, cmds);
 384             processSection(out, Section.NATIVE_LIBS, libs);
 385             processSection(out, Section.CONFIG, configs);
 386             processSection(out, Section.HEADER_FILES, headerFiles);

 387             processSection(out, Section.MAN_PAGES, manPages);


 388 
 389         }
 390 
 391         /**
 392          * Returns a supplier of an input stream to the module-info.class
 393          * on the class path of directories and JAR files.
 394          */
 395         Supplier<InputStream> newModuleInfoSupplier() throws IOException {
 396             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 397             for (Path e: classpath) {
 398                 if (Files.isDirectory(e)) {
 399                     Path mi = e.resolve(MODULE_INFO);
 400                     if (Files.isRegularFile(mi)) {
 401                         Files.copy(mi, baos);
 402                         break;
 403                     }
 404                 } else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) {
 405                     try (JarFile jf = new JarFile(e.toFile())) {
 406                         ZipEntry entry = jf.getEntry(MODULE_INFO);
 407                         if (entry != null) {


 627                 return;
 628 
 629             for (Path p : classpaths) {
 630                 if (Files.isDirectory(p)) {
 631                     processSection(out, Section.CLASSES, p);
 632                 } else if (Files.isRegularFile(p) && p.toString().endsWith(".jar")) {
 633                     try (JarFile jf = new JarFile(p.toFile())) {
 634                         JarEntryConsumer jec = new JarEntryConsumer(out, jf);
 635                         jf.stream().filter(jec).forEach(jec);
 636                     }
 637                 }
 638             }
 639         }
 640 
 641         void processSection(JmodOutputStream out, Section section, List<Path> paths)
 642             throws IOException
 643         {
 644             if (paths == null)
 645                 return;
 646 
 647             for (Path p : paths)
 648                 processSection(out, section, p);
 649         }

 650 
 651         void processSection(JmodOutputStream out, Section section, Path top)
 652             throws IOException
 653         {
 654             Files.walkFileTree(top, Set.of(FileVisitOption.FOLLOW_LINKS),
 655                     Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
 656                 @Override
 657                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
 658                     throws IOException
 659                 {
 660                     Path relPath = top.relativize(file);
 661                     if (relPath.toString().equals(MODULE_INFO)
 662                         && !Section.CLASSES.equals(section))
 663                         warning("warn.ignore.entry", MODULE_INFO, section);
 664 
 665                     if (!relPath.toString().equals(MODULE_INFO)
 666                         && !matches(relPath, excludes)) {
 667                         try (InputStream in = Files.newInputStream(file)) {
 668                             out.writeEntry(in, section, relPath.toString());
 669                         } catch (IOException x) {
 670                             if (x.getMessage().contains("duplicate entry")) {
 671                                 warning("warn.ignore.duplicate.entry", relPath.toString(), section);

 672                                 return FileVisitResult.CONTINUE;
 673                             }
 674                             throw x;
 675                         }
 676                     }
 677                     return FileVisitResult.CONTINUE;
 678                 }
 679             });
 680         }
 681 
 682         boolean matches(Path path, List<PathMatcher> matchers) {
 683             if (matchers != null) {
 684                 for (PathMatcher pm : matchers) {
 685                     if (pm.matches(path))
 686                         return true;
 687                 }
 688             }
 689             return false;
 690         }
 691 


1215                 = parser.accepts("hash-modules", getMessage("main.opt.hash-modules"))
1216                         .withRequiredArg()
1217                         .withValuesConvertedBy(new PatternConverter());
1218 
1219         OptionSpec<Void> help
1220                 = parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help"))
1221                         .forHelp();
1222 
1223         OptionSpec<Path> headerFiles
1224             = parser.accepts("header-files", getMessage("main.opt.header-files"))
1225                     .withRequiredArg()
1226                     .withValuesSeparatedBy(File.pathSeparatorChar)
1227                     .withValuesConvertedBy(DirPathConverter.INSTANCE);
1228 
1229         OptionSpec<Path> libs
1230                 = parser.accepts("libs", getMessage("main.opt.libs"))
1231                         .withRequiredArg()
1232                         .withValuesSeparatedBy(File.pathSeparatorChar)
1233                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1234 







1235         OptionSpec<String> mainClass
1236                 = parser.accepts("main-class", getMessage("main.opt.main-class"))
1237                         .withRequiredArg()
1238                         .describedAs(getMessage("main.opt.main-class.arg"));
1239 
1240         OptionSpec<Path> manPages
1241             = parser.accepts("man-pages", getMessage("main.opt.man-pages"))
1242                         .withRequiredArg()
1243                         .withValuesSeparatedBy(File.pathSeparatorChar)
1244                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1245 
1246         OptionSpec<Path> modulePath
1247                 = parser.acceptsAll(Set.of("p", "module-path"),
1248                                     getMessage("main.opt.module-path"))
1249                         .withRequiredArg()
1250                         .withValuesSeparatedBy(File.pathSeparatorChar)
1251                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1252 
1253         OptionSpec<Version> moduleVersion
1254                 = parser.accepts("module-version", getMessage("main.opt.module-version"))


1296             } catch (IllegalArgumentException e) {
1297                 throw new CommandException("err.invalid.mode", verb).showUsage(true);
1298             }
1299 
1300             if (opts.has(classPath))
1301                 options.classpath = opts.valuesOf(classPath);
1302             if (opts.has(cmds))
1303                 options.cmds = opts.valuesOf(cmds);
1304             if (opts.has(config))
1305                 options.configs = opts.valuesOf(config);
1306             if (opts.has(dryrun))
1307                 options.dryrun = true;
1308             if (opts.has(excludes))
1309                 options.excludes = opts.valuesOf(excludes);
1310             if (opts.has(libs))
1311                 options.libs = opts.valuesOf(libs);
1312             if (opts.has(headerFiles))
1313                 options.headerFiles = opts.valuesOf(headerFiles);
1314             if (opts.has(manPages))
1315                 options.manPages = opts.valuesOf(manPages);


1316             if (opts.has(modulePath)) {
1317                 Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]);
1318                 options.moduleFinder = JLMA.newModulePath(Runtime.version(), true, dirs);
1319             }
1320             if (opts.has(moduleVersion))
1321                 options.moduleVersion = opts.valueOf(moduleVersion);
1322             if (opts.has(mainClass))
1323                 options.mainClass = opts.valueOf(mainClass);
1324             if (opts.has(osName))
1325                 options.osName = opts.valueOf(osName);
1326             if (opts.has(osArch))
1327                 options.osArch = opts.valueOf(osArch);
1328             if (opts.has(osVersion))
1329                 options.osVersion = opts.valueOf(osVersion);
1330             if (opts.has(hashModules)) {
1331                 options.modulesToHash = opts.valueOf(hashModules);
1332                 // if storing hashes then the module path is required
1333                 if (options.moduleFinder == null)
1334                     throw new CommandException("err.modulepath.must.be.specified")
1335                             .showUsage(true);




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.tools.jmod;
  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.File;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.io.OutputStream;

  34 import java.io.PrintWriter;
  35 import java.io.UncheckedIOException;
  36 import java.lang.module.Configuration;
  37 import java.lang.module.ModuleReader;
  38 import java.lang.module.ModuleReference;
  39 import java.lang.module.ModuleFinder;
  40 import java.lang.module.ModuleDescriptor;
  41 import java.lang.module.ModuleDescriptor.Exports;
  42 import java.lang.module.ModuleDescriptor.Opens;
  43 import java.lang.module.ModuleDescriptor.Provides;
  44 import java.lang.module.ModuleDescriptor.Requires;
  45 import java.lang.module.ModuleDescriptor.Version;
  46 import java.lang.module.ResolutionException;
  47 import java.lang.module.ResolvedModule;
  48 import java.net.URI;
  49 import java.nio.file.FileSystems;
  50 import java.nio.file.FileVisitOption;
  51 import java.nio.file.FileVisitResult;
  52 import java.nio.file.Files;
  53 import java.nio.file.InvalidPathException;


  66 import java.util.Deque;
  67 import java.util.HashMap;
  68 import java.util.HashSet;
  69 import java.util.List;
  70 import java.util.Locale;
  71 import java.util.Map;
  72 import java.util.MissingResourceException;
  73 import java.util.Optional;
  74 import java.util.ResourceBundle;
  75 import java.util.Set;
  76 import java.util.function.Consumer;
  77 import java.util.function.Function;
  78 import java.util.function.Predicate;
  79 import java.util.function.Supplier;
  80 import java.util.jar.JarEntry;
  81 import java.util.jar.JarFile;
  82 import java.util.jar.JarOutputStream;
  83 import java.util.stream.Collectors;
  84 import java.util.regex.Pattern;
  85 import java.util.regex.PatternSyntaxException;

  86 import java.util.zip.ZipEntry;
  87 import java.util.zip.ZipException;
  88 import java.util.zip.ZipFile;
  89 
  90 import jdk.internal.jmod.JmodFile;
  91 import jdk.internal.jmod.JmodFile.Section;
  92 import jdk.internal.joptsimple.BuiltinHelpFormatter;
  93 import jdk.internal.joptsimple.NonOptionArgumentSpec;
  94 import jdk.internal.joptsimple.OptionDescriptor;
  95 import jdk.internal.joptsimple.OptionException;
  96 import jdk.internal.joptsimple.OptionParser;
  97 import jdk.internal.joptsimple.OptionSet;
  98 import jdk.internal.joptsimple.OptionSpec;
  99 import jdk.internal.joptsimple.ValueConverter;
 100 import jdk.internal.loader.ResourceHelper;
 101 import jdk.internal.misc.JavaLangModuleAccess;
 102 import jdk.internal.misc.SharedSecrets;
 103 import jdk.internal.module.ModuleHashes;
 104 import jdk.internal.module.ModuleInfoExtender;
 105 import jdk.tools.jlink.internal.Utils;


 150                      EXIT_ABNORMAL = 4;// terminated abnormally
 151 
 152     enum Mode {
 153         CREATE,
 154         LIST,
 155         DESCRIBE,
 156         HASH
 157     };
 158 
 159     static class Options {
 160         Mode mode;
 161         Path jmodFile;
 162         boolean help;
 163         boolean version;
 164         List<Path> classpath;
 165         List<Path> cmds;
 166         List<Path> configs;
 167         List<Path> libs;
 168         List<Path> headerFiles;
 169         List<Path> manPages;
 170         List<Path> legalNotices;;
 171         ModuleFinder moduleFinder;
 172         Version moduleVersion;
 173         String mainClass;
 174         String osName;
 175         String osArch;
 176         String osVersion;
 177         Pattern modulesToHash;
 178         boolean dryrun;
 179         List<PathMatcher> excludes;
 180     }
 181 
 182     public int run(String[] args) {
 183 
 184         try {
 185             handleOptions(args);
 186             if (options == null) {
 187                 showUsageSummary();
 188                 return EXIT_CMDERR;
 189             }
 190             if (options.help) {


 341         } catch (Exception e) {
 342             if (Files.exists(tempTarget)) {
 343                 try {
 344                     Files.delete(tempTarget);
 345                 } catch (IOException ioe) {
 346                     e.addSuppressed(ioe);
 347                 }
 348             }
 349             throw e;
 350         }
 351         return true;
 352     }
 353 
 354     private class JmodFileWriter {
 355         final List<Path> cmds = options.cmds;
 356         final List<Path> libs = options.libs;
 357         final List<Path> configs = options.configs;
 358         final List<Path> classpath = options.classpath;
 359         final List<Path> headerFiles = options.headerFiles;
 360         final List<Path> manPages = options.manPages;
 361         final List<Path> legalNotices = options.legalNotices;
 362 
 363         final Version moduleVersion = options.moduleVersion;
 364         final String mainClass = options.mainClass;
 365         final String osName = options.osName;
 366         final String osArch = options.osArch;
 367         final String osVersion = options.osVersion;
 368         final List<PathMatcher> excludes = options.excludes;
 369         final Hasher hasher = hasher();
 370 
 371         JmodFileWriter() { }
 372 
 373         /**
 374          * Writes the jmod to the given output stream.
 375          */
 376         void write(JmodOutputStream out) throws IOException {
 377             // module-info.class
 378             writeModuleInfo(out, findPackages(classpath));
 379 
 380             // classes
 381             processClasses(out, classpath);
 382 


 383             processSection(out, Section.CONFIG, configs);
 384             processSection(out, Section.HEADER_FILES, headerFiles);
 385             processSection(out, Section.LEGAL_NOTICES, legalNotices);
 386             processSection(out, Section.MAN_PAGES, manPages);
 387             processSection(out, Section.NATIVE_CMDS, cmds);
 388             processSection(out, Section.NATIVE_LIBS, libs);
 389 
 390         }
 391 
 392         /**
 393          * Returns a supplier of an input stream to the module-info.class
 394          * on the class path of directories and JAR files.
 395          */
 396         Supplier<InputStream> newModuleInfoSupplier() throws IOException {
 397             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 398             for (Path e: classpath) {
 399                 if (Files.isDirectory(e)) {
 400                     Path mi = e.resolve(MODULE_INFO);
 401                     if (Files.isRegularFile(mi)) {
 402                         Files.copy(mi, baos);
 403                         break;
 404                     }
 405                 } else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) {
 406                     try (JarFile jf = new JarFile(e.toFile())) {
 407                         ZipEntry entry = jf.getEntry(MODULE_INFO);
 408                         if (entry != null) {


 628                 return;
 629 
 630             for (Path p : classpaths) {
 631                 if (Files.isDirectory(p)) {
 632                     processSection(out, Section.CLASSES, p);
 633                 } else if (Files.isRegularFile(p) && p.toString().endsWith(".jar")) {
 634                     try (JarFile jf = new JarFile(p.toFile())) {
 635                         JarEntryConsumer jec = new JarEntryConsumer(out, jf);
 636                         jf.stream().filter(jec).forEach(jec);
 637                     }
 638                 }
 639             }
 640         }
 641 
 642         void processSection(JmodOutputStream out, Section section, List<Path> paths)
 643             throws IOException
 644         {
 645             if (paths == null)
 646                 return;
 647 
 648             for (Path p : paths) {
 649                 processSection(out, section, p);
 650             }
 651         }
 652 
 653         void processSection(JmodOutputStream out, Section section, Path path)
 654             throws IOException
 655         {
 656             Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS),
 657                 Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
 658                     @Override
 659                     public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
 660                         throws IOException
 661                     {
 662                         Path relPath = path.relativize(file);
 663                         if (relPath.toString().equals(MODULE_INFO)
 664                                 && !Section.CLASSES.equals(section))
 665                             warning("warn.ignore.entry", MODULE_INFO, section);
 666 
 667                         if (!relPath.toString().equals(MODULE_INFO)
 668                                 && !matches(relPath, excludes)) {
 669                             try (InputStream in = Files.newInputStream(file)) {
 670                                 out.writeEntry(in, section, relPath.toString());
 671                             } catch (IOException x) {
 672                                 if (x.getMessage().contains("duplicate entry")) {
 673                                     warning("warn.ignore.duplicate.entry",
 674                                             relPath.toString(), section);
 675                                     return FileVisitResult.CONTINUE;
 676                                 }
 677                                 throw x;
 678                             }
 679                         }
 680                         return FileVisitResult.CONTINUE;
 681                     }
 682                 });
 683         }
 684 
 685         boolean matches(Path path, List<PathMatcher> matchers) {
 686             if (matchers != null) {
 687                 for (PathMatcher pm : matchers) {
 688                     if (pm.matches(path))
 689                         return true;
 690                 }
 691             }
 692             return false;
 693         }
 694 


1218                 = parser.accepts("hash-modules", getMessage("main.opt.hash-modules"))
1219                         .withRequiredArg()
1220                         .withValuesConvertedBy(new PatternConverter());
1221 
1222         OptionSpec<Void> help
1223                 = parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help"))
1224                         .forHelp();
1225 
1226         OptionSpec<Path> headerFiles
1227                 = parser.accepts("header-files", getMessage("main.opt.header-files"))
1228                         .withRequiredArg()
1229                         .withValuesSeparatedBy(File.pathSeparatorChar)
1230                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1231 
1232         OptionSpec<Path> libs
1233                 = parser.accepts("libs", getMessage("main.opt.libs"))
1234                         .withRequiredArg()
1235                         .withValuesSeparatedBy(File.pathSeparatorChar)
1236                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1237 
1238         OptionSpec<Path> legalNotices
1239                 = parser.accepts("legal-notices", getMessage("main.opt.legal-notices"))
1240                         .withRequiredArg()
1241                         .withValuesSeparatedBy(File.pathSeparatorChar)
1242                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1243 
1244 
1245         OptionSpec<String> mainClass
1246                 = parser.accepts("main-class", getMessage("main.opt.main-class"))
1247                         .withRequiredArg()
1248                         .describedAs(getMessage("main.opt.main-class.arg"));
1249 
1250         OptionSpec<Path> manPages
1251                 = parser.accepts("man-pages", getMessage("main.opt.man-pages"))
1252                         .withRequiredArg()
1253                         .withValuesSeparatedBy(File.pathSeparatorChar)
1254                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1255 
1256         OptionSpec<Path> modulePath
1257                 = parser.acceptsAll(Set.of("p", "module-path"),
1258                                     getMessage("main.opt.module-path"))
1259                         .withRequiredArg()
1260                         .withValuesSeparatedBy(File.pathSeparatorChar)
1261                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
1262 
1263         OptionSpec<Version> moduleVersion
1264                 = parser.accepts("module-version", getMessage("main.opt.module-version"))


1306             } catch (IllegalArgumentException e) {
1307                 throw new CommandException("err.invalid.mode", verb).showUsage(true);
1308             }
1309 
1310             if (opts.has(classPath))
1311                 options.classpath = opts.valuesOf(classPath);
1312             if (opts.has(cmds))
1313                 options.cmds = opts.valuesOf(cmds);
1314             if (opts.has(config))
1315                 options.configs = opts.valuesOf(config);
1316             if (opts.has(dryrun))
1317                 options.dryrun = true;
1318             if (opts.has(excludes))
1319                 options.excludes = opts.valuesOf(excludes);
1320             if (opts.has(libs))
1321                 options.libs = opts.valuesOf(libs);
1322             if (opts.has(headerFiles))
1323                 options.headerFiles = opts.valuesOf(headerFiles);
1324             if (opts.has(manPages))
1325                 options.manPages = opts.valuesOf(manPages);
1326             if (opts.has(legalNotices))
1327                 options.legalNotices = opts.valuesOf(legalNotices);
1328             if (opts.has(modulePath)) {
1329                 Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]);
1330                 options.moduleFinder = JLMA.newModulePath(Runtime.version(), true, dirs);
1331             }
1332             if (opts.has(moduleVersion))
1333                 options.moduleVersion = opts.valueOf(moduleVersion);
1334             if (opts.has(mainClass))
1335                 options.mainClass = opts.valueOf(mainClass);
1336             if (opts.has(osName))
1337                 options.osName = opts.valueOf(osName);
1338             if (opts.has(osArch))
1339                 options.osArch = opts.valueOf(osArch);
1340             if (opts.has(osVersion))
1341                 options.osVersion = opts.valueOf(osVersion);
1342             if (opts.has(hashModules)) {
1343                 options.modulesToHash = opts.valueOf(hashModules);
1344                 // if storing hashes then the module path is required
1345                 if (options.moduleFinder == null)
1346                     throw new CommandException("err.modulepath.must.be.specified")
1347                             .showUsage(true);


< prev index next >