148 EXIT_CMDERR = 2, // Bad command-line arguments 149 EXIT_SYSERR = 3, // System error or resource exhaustion. 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 ModuleFinder moduleFinder; 169 Version moduleVersion; 170 String mainClass; 171 String osName; 172 String osArch; 173 String osVersion; 174 Pattern modulesToHash; 175 boolean dryrun; 176 List<PathMatcher> excludes; 177 } 178 179 public int run(String[] args) { 180 181 try { 182 handleOptions(args); 183 if (options == null) { 184 showUsageSummary(); 185 return EXIT_CMDERR; 186 } 187 if (options.help) { 329 } 330 Files.move(tempTarget, target); 331 } catch (Exception e) { 332 if (Files.exists(tempTarget)) { 333 try { 334 Files.delete(tempTarget); 335 } catch (IOException ioe) { 336 e.addSuppressed(ioe); 337 } 338 } 339 throw e; 340 } 341 return true; 342 } 343 344 private class JmodFileWriter { 345 final List<Path> cmds = options.cmds; 346 final List<Path> libs = options.libs; 347 final List<Path> configs = options.configs; 348 final List<Path> classpath = options.classpath; 349 final Version moduleVersion = options.moduleVersion; 350 final String mainClass = options.mainClass; 351 final String osName = options.osName; 352 final String osArch = options.osArch; 353 final String osVersion = options.osVersion; 354 final List<PathMatcher> excludes = options.excludes; 355 final Hasher hasher = hasher(); 356 357 JmodFileWriter() { } 358 359 /** 360 * Writes the jmod to the given output stream. 361 */ 362 void write(JmodOutputStream out) throws IOException { 363 // module-info.class 364 writeModuleInfo(out, findPackages(classpath)); 365 366 // classes 367 processClasses(out, classpath); 368 369 processSection(out, Section.NATIVE_CMDS, cmds); 370 processSection(out, Section.NATIVE_LIBS, libs); 371 processSection(out, Section.CONFIG, configs); 372 } 373 374 /** 375 * Returns a supplier of an input stream to the module-info.class 376 * on the class path of directories and JAR files. 377 */ 378 Supplier<InputStream> newModuleInfoSupplier() throws IOException { 379 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 380 for (Path e: classpath) { 381 if (Files.isDirectory(e)) { 382 Path mi = e.resolve(MODULE_INFO); 383 if (Files.isRegularFile(mi)) { 384 Files.copy(mi, baos); 385 break; 386 } 387 } else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) { 388 try (JarFile jf = new JarFile(e.toFile())) { 389 ZipEntry entry = jf.getEntry(MODULE_INFO); 390 if (entry != null) { 391 jf.getInputStream(entry).transferTo(baos); 1178 .withValuesSeparatedBy(File.pathSeparatorChar) 1179 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1180 1181 OptionSpec<Void> dryrun 1182 = parser.accepts("dry-run", getMessage("main.opt.dry-run")); 1183 1184 OptionSpec<PathMatcher> excludes 1185 = parser.accepts("exclude", getMessage("main.opt.exclude")) 1186 .withRequiredArg() 1187 .withValuesConvertedBy(new PathMatcherConverter()); 1188 1189 OptionSpec<Pattern> hashModules 1190 = parser.accepts("hash-modules", getMessage("main.opt.hash-modules")) 1191 .withRequiredArg() 1192 .withValuesConvertedBy(new PatternConverter()); 1193 1194 OptionSpec<Void> help 1195 = parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help")) 1196 .forHelp(); 1197 1198 OptionSpec<Path> libs 1199 = parser.accepts("libs", getMessage("main.opt.libs")) 1200 .withRequiredArg() 1201 .withValuesSeparatedBy(File.pathSeparatorChar) 1202 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1203 1204 OptionSpec<String> mainClass 1205 = parser.accepts("main-class", getMessage("main.opt.main-class")) 1206 .withRequiredArg() 1207 .describedAs(getMessage("main.opt.main-class.arg")); 1208 1209 OptionSpec<Path> modulePath 1210 = parser.acceptsAll(Set.of("p", "module-path"), 1211 getMessage("main.opt.module-path")) 1212 .withRequiredArg() 1213 .withValuesSeparatedBy(File.pathSeparatorChar) 1214 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1215 1216 OptionSpec<Version> moduleVersion 1217 = parser.accepts("module-version", getMessage("main.opt.module-version")) 1218 .withRequiredArg() 1219 .withValuesConvertedBy(new ModuleVersionConverter()); 1220 1221 OptionSpec<String> osName 1222 = parser.accepts("os-name", getMessage("main.opt.os-name")) 1223 .withRequiredArg() 1224 .describedAs(getMessage("main.opt.os-name.arg")); 1225 1226 OptionSpec<String> osArch 1227 = parser.accepts("os-arch", getMessage("main.opt.os-arch")) 1228 .withRequiredArg() 1255 String verb = words.get(0); 1256 options = new Options(); 1257 try { 1258 options.mode = Enum.valueOf(Mode.class, verb.toUpperCase()); 1259 } catch (IllegalArgumentException e) { 1260 throw new CommandException("err.invalid.mode", verb).showUsage(true); 1261 } 1262 1263 if (opts.has(classPath)) 1264 options.classpath = opts.valuesOf(classPath); 1265 if (opts.has(cmds)) 1266 options.cmds = opts.valuesOf(cmds); 1267 if (opts.has(config)) 1268 options.configs = opts.valuesOf(config); 1269 if (opts.has(dryrun)) 1270 options.dryrun = true; 1271 if (opts.has(excludes)) 1272 options.excludes = opts.valuesOf(excludes); 1273 if (opts.has(libs)) 1274 options.libs = opts.valuesOf(libs); 1275 if (opts.has(modulePath)) { 1276 Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]); 1277 options.moduleFinder = ModuleFinder.of(dirs); 1278 if (options.moduleFinder instanceof ConfigurableModuleFinder) 1279 ((ConfigurableModuleFinder)options.moduleFinder).configurePhase(Phase.LINK_TIME); 1280 } 1281 if (opts.has(moduleVersion)) 1282 options.moduleVersion = opts.valueOf(moduleVersion); 1283 if (opts.has(mainClass)) 1284 options.mainClass = opts.valueOf(mainClass); 1285 if (opts.has(osName)) 1286 options.osName = opts.valueOf(osName); 1287 if (opts.has(osArch)) 1288 options.osArch = opts.valueOf(osArch); 1289 if (opts.has(osVersion)) 1290 options.osVersion = opts.valueOf(osVersion); 1291 if (opts.has(hashModules)) { 1292 options.modulesToHash = opts.valueOf(hashModules); 1293 // if storing hashes then the module path is required 1294 if (options.moduleFinder == null) | 148 EXIT_CMDERR = 2, // Bad command-line arguments 149 EXIT_SYSERR = 3, // System error or resource exhaustion. 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 ModuleFinder moduleFinder; 171 Version moduleVersion; 172 String mainClass; 173 String osName; 174 String osArch; 175 String osVersion; 176 Pattern modulesToHash; 177 boolean dryrun; 178 List<PathMatcher> excludes; 179 } 180 181 public int run(String[] args) { 182 183 try { 184 handleOptions(args); 185 if (options == null) { 186 showUsageSummary(); 187 return EXIT_CMDERR; 188 } 189 if (options.help) { 331 } 332 Files.move(tempTarget, target); 333 } catch (Exception e) { 334 if (Files.exists(tempTarget)) { 335 try { 336 Files.delete(tempTarget); 337 } catch (IOException ioe) { 338 e.addSuppressed(ioe); 339 } 340 } 341 throw e; 342 } 343 return true; 344 } 345 346 private class JmodFileWriter { 347 final List<Path> cmds = options.cmds; 348 final List<Path> libs = options.libs; 349 final List<Path> configs = options.configs; 350 final List<Path> classpath = options.classpath; 351 final List<Path> headerFiles = options.headerFiles; 352 final List<Path> manPages = options.manPages; 353 354 final Version moduleVersion = options.moduleVersion; 355 final String mainClass = options.mainClass; 356 final String osName = options.osName; 357 final String osArch = options.osArch; 358 final String osVersion = options.osVersion; 359 final List<PathMatcher> excludes = options.excludes; 360 final Hasher hasher = hasher(); 361 362 JmodFileWriter() { } 363 364 /** 365 * Writes the jmod to the given output stream. 366 */ 367 void write(JmodOutputStream out) throws IOException { 368 // module-info.class 369 writeModuleInfo(out, findPackages(classpath)); 370 371 // classes 372 processClasses(out, classpath); 373 374 processSection(out, Section.NATIVE_CMDS, cmds); 375 processSection(out, Section.NATIVE_LIBS, libs); 376 processSection(out, Section.CONFIG, configs); 377 processSection(out, Section.HEADER_FILES, headerFiles); 378 processSection(out, Section.MAN_PAGES, manPages); 379 380 } 381 382 /** 383 * Returns a supplier of an input stream to the module-info.class 384 * on the class path of directories and JAR files. 385 */ 386 Supplier<InputStream> newModuleInfoSupplier() throws IOException { 387 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 388 for (Path e: classpath) { 389 if (Files.isDirectory(e)) { 390 Path mi = e.resolve(MODULE_INFO); 391 if (Files.isRegularFile(mi)) { 392 Files.copy(mi, baos); 393 break; 394 } 395 } else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) { 396 try (JarFile jf = new JarFile(e.toFile())) { 397 ZipEntry entry = jf.getEntry(MODULE_INFO); 398 if (entry != null) { 399 jf.getInputStream(entry).transferTo(baos); 1186 .withValuesSeparatedBy(File.pathSeparatorChar) 1187 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1188 1189 OptionSpec<Void> dryrun 1190 = parser.accepts("dry-run", getMessage("main.opt.dry-run")); 1191 1192 OptionSpec<PathMatcher> excludes 1193 = parser.accepts("exclude", getMessage("main.opt.exclude")) 1194 .withRequiredArg() 1195 .withValuesConvertedBy(new PathMatcherConverter()); 1196 1197 OptionSpec<Pattern> hashModules 1198 = parser.accepts("hash-modules", getMessage("main.opt.hash-modules")) 1199 .withRequiredArg() 1200 .withValuesConvertedBy(new PatternConverter()); 1201 1202 OptionSpec<Void> help 1203 = parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help")) 1204 .forHelp(); 1205 1206 OptionSpec<Path> headerFiles 1207 = parser.accepts("header-files", getMessage("main.opt.header-files")) 1208 .withRequiredArg() 1209 .withValuesSeparatedBy(File.pathSeparatorChar) 1210 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1211 1212 OptionSpec<Path> libs 1213 = parser.accepts("libs", getMessage("main.opt.libs")) 1214 .withRequiredArg() 1215 .withValuesSeparatedBy(File.pathSeparatorChar) 1216 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1217 1218 OptionSpec<String> mainClass 1219 = parser.accepts("main-class", getMessage("main.opt.main-class")) 1220 .withRequiredArg() 1221 .describedAs(getMessage("main.opt.main-class.arg")); 1222 1223 OptionSpec<Path> manPages 1224 = parser.accepts("man-pages", getMessage("main.opt.man-pages")) 1225 .withRequiredArg() 1226 .withValuesSeparatedBy(File.pathSeparatorChar) 1227 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1228 1229 OptionSpec<Path> modulePath 1230 = parser.acceptsAll(Set.of("p", "module-path"), 1231 getMessage("main.opt.module-path")) 1232 .withRequiredArg() 1233 .withValuesSeparatedBy(File.pathSeparatorChar) 1234 .withValuesConvertedBy(DirPathConverter.INSTANCE); 1235 1236 OptionSpec<Version> moduleVersion 1237 = parser.accepts("module-version", getMessage("main.opt.module-version")) 1238 .withRequiredArg() 1239 .withValuesConvertedBy(new ModuleVersionConverter()); 1240 1241 OptionSpec<String> osName 1242 = parser.accepts("os-name", getMessage("main.opt.os-name")) 1243 .withRequiredArg() 1244 .describedAs(getMessage("main.opt.os-name.arg")); 1245 1246 OptionSpec<String> osArch 1247 = parser.accepts("os-arch", getMessage("main.opt.os-arch")) 1248 .withRequiredArg() 1275 String verb = words.get(0); 1276 options = new Options(); 1277 try { 1278 options.mode = Enum.valueOf(Mode.class, verb.toUpperCase()); 1279 } catch (IllegalArgumentException e) { 1280 throw new CommandException("err.invalid.mode", verb).showUsage(true); 1281 } 1282 1283 if (opts.has(classPath)) 1284 options.classpath = opts.valuesOf(classPath); 1285 if (opts.has(cmds)) 1286 options.cmds = opts.valuesOf(cmds); 1287 if (opts.has(config)) 1288 options.configs = opts.valuesOf(config); 1289 if (opts.has(dryrun)) 1290 options.dryrun = true; 1291 if (opts.has(excludes)) 1292 options.excludes = opts.valuesOf(excludes); 1293 if (opts.has(libs)) 1294 options.libs = opts.valuesOf(libs); 1295 if (opts.has(headerFiles)) 1296 options.headerFiles = opts.valuesOf(headerFiles); 1297 if (opts.has(manPages)) 1298 options.manPages = opts.valuesOf(manPages); 1299 if (opts.has(modulePath)) { 1300 Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]); 1301 options.moduleFinder = ModuleFinder.of(dirs); 1302 if (options.moduleFinder instanceof ConfigurableModuleFinder) 1303 ((ConfigurableModuleFinder)options.moduleFinder).configurePhase(Phase.LINK_TIME); 1304 } 1305 if (opts.has(moduleVersion)) 1306 options.moduleVersion = opts.valueOf(moduleVersion); 1307 if (opts.has(mainClass)) 1308 options.mainClass = opts.valueOf(mainClass); 1309 if (opts.has(osName)) 1310 options.osName = opts.valueOf(osName); 1311 if (opts.has(osArch)) 1312 options.osArch = opts.valueOf(osArch); 1313 if (opts.has(osVersion)) 1314 options.osVersion = opts.valueOf(osVersion); 1315 if (opts.has(hashModules)) { 1316 options.modulesToHash = opts.valueOf(hashModules); 1317 // if storing hashes then the module path is required 1318 if (options.moduleFinder == null) |