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;
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;
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) {
192 showHelp();
193 return EXIT_OK;
194 }
195 if (options.version) {
196 showVersion();
197 return EXIT_OK;
198 }
307 md.provides().stream()
308 .sorted(Comparator.comparing(Provides::service))
309 .forEach(p -> sb.append("\n provides ").append(p.service())
310 .append(" with ")
311 .append(toString(p.providers())));
312
313 md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
314
315 md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v));
316
317 md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v));
318
319 md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v));
320
321 JLMA.hashes(md).ifPresent(
322 hashes -> hashes.names().stream().sorted().forEach(
323 mod -> sb.append("\n hashes ").append(mod).append(" ")
324 .append(hashes.algorithm()).append(" ")
325 .append(hashes.hashFor(mod))));
326
327 out.println(sb.toString());
328 }
329
330 private boolean create() throws IOException {
331 JmodFileWriter jmod = new JmodFileWriter();
332
333 // create jmod with temporary name to avoid it being examined
334 // when scanning the module path
335 Path target = options.jmodFile;
336 Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
337 try {
338 try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) {
339 jmod.write(jos);
340 }
341 Files.move(tempTarget, target);
342 } catch (Exception e) {
343 if (Files.exists(tempTarget)) {
344 try {
345 Files.delete(tempTarget);
346 } catch (IOException ioe) {
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 }
458 if (mainClass != null)
459 extender.mainClass(mainClass);
460
461 // --os-name, --os-arch, --os-version
462 if (osName != null || osArch != null || osVersion != null)
463 extender.targetPlatform(osName, osArch, osVersion);
464
465 // --module-version
466 if (moduleVersion != null)
467 extender.version(moduleVersion);
468
469 if (hasher != null) {
470 ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name());
471 if (moduleHashes != null) {
472 extender.hashes(moduleHashes);
473 } else {
474 warning("warn.no.module.hashes", descriptor.name());
475 }
476 }
477
478 // write the (possibly extended or modified) module-info.class
479 out.writeEntry(extender.toByteArray(), Section.CLASSES, MODULE_INFO);
480 }
481 }
482
483 /*
484 * Hasher resolves a module graph using the --hash-modules PATTERN
485 * as the roots.
486 *
487 * The jmod file is being created and does not exist in the
488 * given modulepath.
489 */
490 private Hasher hasher() {
491 if (options.modulesToHash == null)
492 return null;
493
494 try {
495 Supplier<InputStream> miSupplier = newModuleInfoSupplier();
496 if (miSupplier == null) {
497 throw new IOException(MODULE_INFO + " not found");
1082
1083 static class PatternConverter implements ValueConverter<Pattern> {
1084 @Override
1085 public Pattern convert(String value) {
1086 try {
1087 if (value.startsWith("regex:")) {
1088 value = value.substring("regex:".length()).trim();
1089 }
1090
1091 return Pattern.compile(value);
1092 } catch (PatternSyntaxException e) {
1093 throw new CommandException("err.bad.pattern", value);
1094 }
1095 }
1096
1097 @Override public Class<Pattern> valueType() { return Pattern.class; }
1098
1099 @Override public String valuePattern() { return "regex-pattern"; }
1100 }
1101
1102 static class PathMatcherConverter implements ValueConverter<PathMatcher> {
1103 @Override
1104 public PathMatcher convert(String pattern) {
1105 try {
1106 return Utils.getPathMatcher(FileSystems.getDefault(), pattern);
1107 } catch (PatternSyntaxException e) {
1108 throw new CommandException("err.bad.pattern", pattern);
1109 }
1110 }
1111
1112 @Override public Class<PathMatcher> valueType() { return PathMatcher.class; }
1113
1114 @Override public String valuePattern() { return "pattern-list"; }
1115 }
1116
1117 /* Support for @<file> in jmod help */
1118 private static final String CMD_FILENAME = "@<filename>";
1119
1120 /**
1121 * This formatter is adding the @filename option and does the required
1122 * formatting.
1123 */
1124 private static final class JmodHelpFormatter extends BuiltinHelpFormatter {
1125
1126 private JmodHelpFormatter() { super(80, 2); }
1127
1128 @Override
1129 public String format(Map<String, ? extends OptionDescriptor> options) {
1130 Map<String, OptionDescriptor> all = new HashMap<>();
1131 all.putAll(options);
1132 all.put(CMD_FILENAME, new OptionDescriptor() {
1133 @Override
1134 public Collection<String> options() {
1135 List<String> ret = new ArrayList<>();
1136 ret.add(CMD_FILENAME);
1137 return ret;
1138 }
1139 @Override
1140 public String description() { return getMessage("main.opt.cmdfile"); }
1141 @Override
1142 public List<?> defaultValues() { return Collections.emptyList(); }
1143 @Override
1144 public boolean isRequired() { return false; }
1145 @Override
1146 public boolean acceptsArguments() { return false; }
1147 @Override
1148 public boolean requiresArgument() { return false; }
1149 @Override
1150 public String argumentDescription() { return null; }
1151 @Override
1253 OptionSpec<Version> moduleVersion
1254 = parser.accepts("module-version", getMessage("main.opt.module-version"))
1255 .withRequiredArg()
1256 .withValuesConvertedBy(new ModuleVersionConverter());
1257
1258 OptionSpec<String> osName
1259 = parser.accepts("os-name", getMessage("main.opt.os-name"))
1260 .withRequiredArg()
1261 .describedAs(getMessage("main.opt.os-name.arg"));
1262
1263 OptionSpec<String> osArch
1264 = parser.accepts("os-arch", getMessage("main.opt.os-arch"))
1265 .withRequiredArg()
1266 .describedAs(getMessage("main.opt.os-arch.arg"));
1267
1268 OptionSpec<String> osVersion
1269 = parser.accepts("os-version", getMessage("main.opt.os-version"))
1270 .withRequiredArg()
1271 .describedAs(getMessage("main.opt.os-version.arg"));
1272
1273 OptionSpec<Void> version
1274 = parser.accepts("version", getMessage("main.opt.version"));
1275
1276 NonOptionArgumentSpec<String> nonOptions
1277 = parser.nonOptions();
1278
1279 try {
1280 OptionSet opts = parser.parse(args);
1281
1282 if (opts.has(help) || opts.has(version)) {
1283 options = new Options();
1284 options.help = opts.has(help);
1285 options.version = opts.has(version);
1286 return; // informational message will be shown
1287 }
1288
1289 List<String> words = opts.valuesOf(nonOptions);
1290 if (words.isEmpty())
1291 throw new CommandException("err.missing.mode").showUsage(true);
1292 String verb = words.get(0);
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);
1336 }
1337
1338 if (options.mode.equals(Mode.HASH)) {
1339 if (options.moduleFinder == null || options.modulesToHash == null)
1340 throw new CommandException("err.modulepath.must.be.specified")
1341 .showUsage(true);
1342 } else {
1343 if (words.size() <= 1)
1344 throw new CommandException("err.jmod.must.be.specified").showUsage(true);
1345 Path path = Paths.get(words.get(1));
1346
1347 if (options.mode.equals(Mode.CREATE) && Files.exists(path))
1348 throw new CommandException("err.file.already.exists", path);
1349 else if ((options.mode.equals(Mode.LIST) ||
1350 options.mode.equals(Mode.DESCRIBE))
1351 && Files.notExists(path))
1352 throw new CommandException("err.jmod.not.found", path);
1353
1354 if (options.dryrun) {
1355 throw new CommandException("err.invalid.dryrun.option");
1356 }
|
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.internal.module.WarnIfResolvedReason;
108 import jdk.tools.jlink.internal.Utils;
109
110 import static java.util.stream.Collectors.joining;
111
112 /**
113 * Implementation for the jmod tool.
114 */
115 public class JmodTask {
116
117 static class CommandException extends RuntimeException {
118 private static final long serialVersionUID = 0L;
119 boolean showUsage;
120
121 CommandException(String key, Object... args) {
122 super(getMessageOrKey(key, args));
123 }
124
125 CommandException showUsage(boolean b) {
126 showUsage = b;
127 return this;
160 };
161
162 static class Options {
163 Mode mode;
164 Path jmodFile;
165 boolean help;
166 boolean version;
167 List<Path> classpath;
168 List<Path> cmds;
169 List<Path> configs;
170 List<Path> libs;
171 List<Path> headerFiles;
172 List<Path> manPages;
173 ModuleFinder moduleFinder;
174 Version moduleVersion;
175 String mainClass;
176 String osName;
177 String osArch;
178 String osVersion;
179 Pattern modulesToHash;
180 boolean doNotResolveByDefault;
181 WarnIfResolvedReason warnIfResolvedReason = WarnIfResolvedReason.NONE;
182 boolean dryrun;
183 List<PathMatcher> excludes;
184 }
185
186 public int run(String[] args) {
187
188 try {
189 handleOptions(args);
190 if (options == null) {
191 showUsageSummary();
192 return EXIT_CMDERR;
193 }
194 if (options.help) {
195 showHelp();
196 return EXIT_OK;
197 }
198 if (options.version) {
199 showVersion();
200 return EXIT_OK;
201 }
310 md.provides().stream()
311 .sorted(Comparator.comparing(Provides::service))
312 .forEach(p -> sb.append("\n provides ").append(p.service())
313 .append(" with ")
314 .append(toString(p.providers())));
315
316 md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
317
318 md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v));
319
320 md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v));
321
322 md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v));
323
324 JLMA.hashes(md).ifPresent(
325 hashes -> hashes.names().stream().sorted().forEach(
326 mod -> sb.append("\n hashes ").append(mod).append(" ")
327 .append(hashes.algorithm()).append(" ")
328 .append(hashes.hashFor(mod))));
329
330 if (JLMA.doNotResolveByDefault(md))
331 sb.append("\n doNotResolveByDefault true");
332
333 WarnIfResolvedReason reason = JLMA.warnIfResolvedReason(md);
334 if (!reason.equals(WarnIfResolvedReason.NONE))
335 sb.append("\n warnIfResolved ").append(reason);
336
337 out.println(sb.toString());
338 }
339
340 private boolean create() throws IOException {
341 JmodFileWriter jmod = new JmodFileWriter();
342
343 // create jmod with temporary name to avoid it being examined
344 // when scanning the module path
345 Path target = options.jmodFile;
346 Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
347 try {
348 try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) {
349 jmod.write(jos);
350 }
351 Files.move(tempTarget, target);
352 } catch (Exception e) {
353 if (Files.exists(tempTarget)) {
354 try {
355 Files.delete(tempTarget);
356 } catch (IOException ioe) {
360 throw e;
361 }
362 return true;
363 }
364
365 private class JmodFileWriter {
366 final List<Path> cmds = options.cmds;
367 final List<Path> libs = options.libs;
368 final List<Path> configs = options.configs;
369 final List<Path> classpath = options.classpath;
370 final List<Path> headerFiles = options.headerFiles;
371 final List<Path> manPages = options.manPages;
372
373 final Version moduleVersion = options.moduleVersion;
374 final String mainClass = options.mainClass;
375 final String osName = options.osName;
376 final String osArch = options.osArch;
377 final String osVersion = options.osVersion;
378 final List<PathMatcher> excludes = options.excludes;
379 final Hasher hasher = hasher();
380 final boolean doNotResolveByDefault = options.doNotResolveByDefault;
381 final WarnIfResolvedReason warnReason = options.warnIfResolvedReason;
382
383 JmodFileWriter() { }
384
385 /**
386 * Writes the jmod to the given output stream.
387 */
388 void write(JmodOutputStream out) throws IOException {
389 // module-info.class
390 writeModuleInfo(out, findPackages(classpath));
391
392 // classes
393 processClasses(out, classpath);
394
395 processSection(out, Section.NATIVE_CMDS, cmds);
396 processSection(out, Section.NATIVE_LIBS, libs);
397 processSection(out, Section.CONFIG, configs);
398 processSection(out, Section.HEADER_FILES, headerFiles);
399 processSection(out, Section.MAN_PAGES, manPages);
400
401 }
470 if (mainClass != null)
471 extender.mainClass(mainClass);
472
473 // --os-name, --os-arch, --os-version
474 if (osName != null || osArch != null || osVersion != null)
475 extender.targetPlatform(osName, osArch, osVersion);
476
477 // --module-version
478 if (moduleVersion != null)
479 extender.version(moduleVersion);
480
481 if (hasher != null) {
482 ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name());
483 if (moduleHashes != null) {
484 extender.hashes(moduleHashes);
485 } else {
486 warning("warn.no.module.hashes", descriptor.name());
487 }
488 }
489
490 if (doNotResolveByDefault || warnReason != WarnIfResolvedReason.NONE)
491 extender.moduleResolution(doNotResolveByDefault, warnReason);
492
493 // write the (possibly extended or modified) module-info.class
494 out.writeEntry(extender.toByteArray(), Section.CLASSES, MODULE_INFO);
495 }
496 }
497
498 /*
499 * Hasher resolves a module graph using the --hash-modules PATTERN
500 * as the roots.
501 *
502 * The jmod file is being created and does not exist in the
503 * given modulepath.
504 */
505 private Hasher hasher() {
506 if (options.modulesToHash == null)
507 return null;
508
509 try {
510 Supplier<InputStream> miSupplier = newModuleInfoSupplier();
511 if (miSupplier == null) {
512 throw new IOException(MODULE_INFO + " not found");
1097
1098 static class PatternConverter implements ValueConverter<Pattern> {
1099 @Override
1100 public Pattern convert(String value) {
1101 try {
1102 if (value.startsWith("regex:")) {
1103 value = value.substring("regex:".length()).trim();
1104 }
1105
1106 return Pattern.compile(value);
1107 } catch (PatternSyntaxException e) {
1108 throw new CommandException("err.bad.pattern", value);
1109 }
1110 }
1111
1112 @Override public Class<Pattern> valueType() { return Pattern.class; }
1113
1114 @Override public String valuePattern() { return "regex-pattern"; }
1115 }
1116
1117 static class WarnIfResolvedReasonConverter
1118 implements ValueConverter<WarnIfResolvedReason>
1119 {
1120 @Override
1121 public WarnIfResolvedReason convert(String value) {
1122 if (value.equals("deprecated"))
1123 return WarnIfResolvedReason.DEPRECATED;
1124 else if (value.equals("deprecated-for-removal"))
1125 return WarnIfResolvedReason.DEPRECATED_FOR_REMOVAL;
1126 else if (value.equals("incubating"))
1127 return WarnIfResolvedReason.INCUBATING;
1128 else
1129 throw new CommandException("err.bad.WarnIfResolvedReason", value);
1130 }
1131
1132 @Override public Class<WarnIfResolvedReason> valueType() {
1133 return WarnIfResolvedReason.class;
1134 }
1135
1136 @Override public String valuePattern() { return "reason"; }
1137 }
1138
1139 static class PathMatcherConverter implements ValueConverter<PathMatcher> {
1140 @Override
1141 public PathMatcher convert(String pattern) {
1142 try {
1143 return Utils.getPathMatcher(FileSystems.getDefault(), pattern);
1144 } catch (PatternSyntaxException e) {
1145 throw new CommandException("err.bad.pattern", pattern);
1146 }
1147 }
1148
1149 @Override public Class<PathMatcher> valueType() { return PathMatcher.class; }
1150
1151 @Override public String valuePattern() { return "pattern-list"; }
1152 }
1153
1154 /* Support for @<file> in jmod help */
1155 private static final String CMD_FILENAME = "@<filename>";
1156
1157 /**
1158 * This formatter is adding the @filename option and does the required
1159 * formatting.
1160 */
1161 private static final class JmodHelpFormatter extends BuiltinHelpFormatter {
1162
1163 private JmodHelpFormatter() { super(80, 2); }
1164
1165 @Override
1166 public String format(Map<String, ? extends OptionDescriptor> options) {
1167 Map<String, OptionDescriptor> all = new HashMap<>();
1168 all.putAll(options);
1169
1170 // hidden options
1171 all.remove("do-not-resolve-by-default");
1172 all.remove("warn-if-resolved");
1173
1174 all.put(CMD_FILENAME, new OptionDescriptor() {
1175 @Override
1176 public Collection<String> options() {
1177 List<String> ret = new ArrayList<>();
1178 ret.add(CMD_FILENAME);
1179 return ret;
1180 }
1181 @Override
1182 public String description() { return getMessage("main.opt.cmdfile"); }
1183 @Override
1184 public List<?> defaultValues() { return Collections.emptyList(); }
1185 @Override
1186 public boolean isRequired() { return false; }
1187 @Override
1188 public boolean acceptsArguments() { return false; }
1189 @Override
1190 public boolean requiresArgument() { return false; }
1191 @Override
1192 public String argumentDescription() { return null; }
1193 @Override
1295 OptionSpec<Version> moduleVersion
1296 = parser.accepts("module-version", getMessage("main.opt.module-version"))
1297 .withRequiredArg()
1298 .withValuesConvertedBy(new ModuleVersionConverter());
1299
1300 OptionSpec<String> osName
1301 = parser.accepts("os-name", getMessage("main.opt.os-name"))
1302 .withRequiredArg()
1303 .describedAs(getMessage("main.opt.os-name.arg"));
1304
1305 OptionSpec<String> osArch
1306 = parser.accepts("os-arch", getMessage("main.opt.os-arch"))
1307 .withRequiredArg()
1308 .describedAs(getMessage("main.opt.os-arch.arg"));
1309
1310 OptionSpec<String> osVersion
1311 = parser.accepts("os-version", getMessage("main.opt.os-version"))
1312 .withRequiredArg()
1313 .describedAs(getMessage("main.opt.os-version.arg"));
1314
1315 OptionSpec<Void> doNotResolveByDefault
1316 = parser.accepts("do-not-resolve-by-default");
1317
1318 OptionSpec<WarnIfResolvedReason> warnIfResolved
1319 = parser.accepts("warn-if-resolved")
1320 .withRequiredArg()
1321 .withValuesConvertedBy(new WarnIfResolvedReasonConverter());
1322
1323 OptionSpec<Void> version
1324 = parser.accepts("version", getMessage("main.opt.version"));
1325
1326 NonOptionArgumentSpec<String> nonOptions
1327 = parser.nonOptions();
1328
1329 try {
1330 OptionSet opts = parser.parse(args);
1331
1332 if (opts.has(help) || opts.has(version)) {
1333 options = new Options();
1334 options.help = opts.has(help);
1335 options.version = opts.has(version);
1336 return; // informational message will be shown
1337 }
1338
1339 List<String> words = opts.valuesOf(nonOptions);
1340 if (words.isEmpty())
1341 throw new CommandException("err.missing.mode").showUsage(true);
1342 String verb = words.get(0);
1367 Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]);
1368 options.moduleFinder = JLMA.newModulePath(Runtime.version(), true, dirs);
1369 }
1370 if (opts.has(moduleVersion))
1371 options.moduleVersion = opts.valueOf(moduleVersion);
1372 if (opts.has(mainClass))
1373 options.mainClass = opts.valueOf(mainClass);
1374 if (opts.has(osName))
1375 options.osName = opts.valueOf(osName);
1376 if (opts.has(osArch))
1377 options.osArch = opts.valueOf(osArch);
1378 if (opts.has(osVersion))
1379 options.osVersion = opts.valueOf(osVersion);
1380 if (opts.has(hashModules)) {
1381 options.modulesToHash = opts.valueOf(hashModules);
1382 // if storing hashes then the module path is required
1383 if (options.moduleFinder == null)
1384 throw new CommandException("err.modulepath.must.be.specified")
1385 .showUsage(true);
1386 }
1387 if (opts.has(doNotResolveByDefault))
1388 options.doNotResolveByDefault = true;
1389 if (opts.has(warnIfResolved))
1390 options.warnIfResolvedReason = opts.valueOf(warnIfResolved);
1391
1392 if (options.mode.equals(Mode.HASH)) {
1393 if (options.moduleFinder == null || options.modulesToHash == null)
1394 throw new CommandException("err.modulepath.must.be.specified")
1395 .showUsage(true);
1396 } else {
1397 if (words.size() <= 1)
1398 throw new CommandException("err.jmod.must.be.specified").showUsage(true);
1399 Path path = Paths.get(words.get(1));
1400
1401 if (options.mode.equals(Mode.CREATE) && Files.exists(path))
1402 throw new CommandException("err.file.already.exists", path);
1403 else if ((options.mode.equals(Mode.LIST) ||
1404 options.mode.equals(Mode.DESCRIBE))
1405 && Files.notExists(path))
1406 throw new CommandException("err.jmod.not.found", path);
1407
1408 if (options.dryrun) {
1409 throw new CommandException("err.invalid.dryrun.option");
1410 }
|