27 import java.io.File; |
27 import java.io.File; |
28 import java.io.IOException; |
28 import java.io.IOException; |
29 import java.io.PrintWriter; |
29 import java.io.PrintWriter; |
30 import java.io.UncheckedIOException; |
30 import java.io.UncheckedIOException; |
31 import java.lang.module.Configuration; |
31 import java.lang.module.Configuration; |
|
32 import java.lang.module.ModuleDescriptor; |
32 import java.lang.module.ModuleFinder; |
33 import java.lang.module.ModuleFinder; |
33 import java.lang.module.ModuleReference; |
34 import java.lang.module.ModuleReference; |
34 import java.lang.module.ResolutionException; |
35 import java.lang.module.ResolutionException; |
35 import java.lang.module.ResolvedModule; |
36 import java.lang.module.ResolvedModule; |
36 import java.net.URI; |
37 import java.net.URI; |
189 } |
190 } |
190 if (options.version || options.fullVersion) { |
191 if (options.version || options.fullVersion) { |
191 taskHelper.showVersion(options.fullVersion); |
192 taskHelper.showVersion(options.fullVersion); |
192 return EXIT_OK; |
193 return EXIT_OK; |
193 } |
194 } |
|
195 |
194 if (taskHelper.getExistingImage() == null) { |
196 if (taskHelper.getExistingImage() == null) { |
195 if (options.modulePath.isEmpty()) { |
197 if (options.modulePath.isEmpty()) { |
196 throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true); |
198 throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true); |
197 } |
199 } |
198 createImage(); |
200 createImage(); |
254 |
256 |
255 // First create the image provider |
257 // First create the image provider |
256 ImageProvider imageProvider = |
258 ImageProvider imageProvider = |
257 createImageProvider(finder, |
259 createImageProvider(finder, |
258 config.getModules(), |
260 config.getModules(), |
259 config.getLimitmods(), |
|
260 config.getByteOrder(), |
261 config.getByteOrder(), |
261 null, |
262 null, |
262 IGNORE_SIGNING_DEFAULT); |
263 IGNORE_SIGNING_DEFAULT); |
263 |
264 |
264 // Then create the Plugin Stack |
265 // Then create the Plugin Stack |
289 throw taskHelper.newBadArgs("err.existing.image.invalid"); |
290 throw taskHelper.newBadArgs("err.existing.image.invalid"); |
290 } |
291 } |
291 postProcessImage(img, config.getPlugins()); |
292 postProcessImage(img, config.getPlugins()); |
292 } |
293 } |
293 |
294 |
|
295 // the token for "all modules on the module path" |
|
296 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; |
294 private void createImage() throws Exception { |
297 private void createImage() throws Exception { |
295 if (options.output == null) { |
298 if (options.output == null) { |
296 throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true); |
299 throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true); |
297 } |
300 } |
298 ModuleFinder finder |
301 |
299 = newModuleFinder(options.modulePath, options.limitMods, options.addMods); |
|
300 if (options.addMods.isEmpty()) { |
302 if (options.addMods.isEmpty()) { |
301 throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules") |
303 throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules") |
302 .showUsage(true); |
304 .showUsage(true); |
303 } |
305 } |
|
306 |
|
307 Set<String> roots = new HashSet<>(); |
|
308 for (String mod : options.addMods) { |
|
309 if (mod.equals(ALL_MODULE_PATH)) { |
|
310 ModuleFinder finder = modulePathFinder(); |
|
311 finder.findAll() |
|
312 .stream() |
|
313 .map(ModuleReference::descriptor) |
|
314 .map(ModuleDescriptor::name) |
|
315 .forEach(mn -> roots.add(mn)); |
|
316 } else { |
|
317 roots.add(mod); |
|
318 } |
|
319 } |
|
320 |
|
321 ModuleFinder finder = newModuleFinder(options.modulePath, |
|
322 options.limitMods, |
|
323 roots); |
|
324 |
|
325 |
304 // First create the image provider |
326 // First create the image provider |
305 ImageProvider imageProvider = createImageProvider(finder, |
327 ImageProvider imageProvider = createImageProvider(finder, |
306 options.addMods, |
328 roots, |
307 options.limitMods, |
329 options.endian, |
308 options.endian, |
330 options.packagedModulesPath, |
309 options.packagedModulesPath, |
331 options.ignoreSigning); |
310 options.ignoreSigning); |
|
311 |
332 |
312 // Then create the Plugin Stack |
333 // Then create the Plugin Stack |
313 ImagePluginStack stack = ImagePluginConfiguration. |
334 ImagePluginStack stack = ImagePluginConfiguration. |
314 parseConfiguration(taskHelper.getPluginsConfig(options.output)); |
335 parseConfiguration(taskHelper.getPluginsConfig(options.output)); |
315 |
336 |
360 URI uri = ouri.get(); |
381 URI uri = ouri.get(); |
361 return Paths.get(uri); |
382 return Paths.get(uri); |
362 } |
383 } |
363 |
384 |
364 private static ImageProvider createImageProvider(ModuleFinder finder, |
385 private static ImageProvider createImageProvider(ModuleFinder finder, |
365 Set<String> addMods, |
386 Set<String> roots, |
366 Set<String> limitMods, |
|
367 ByteOrder order, |
387 ByteOrder order, |
368 Path retainModulesPath, |
388 Path retainModulesPath, |
369 boolean ignoreSigning) |
389 boolean ignoreSigning) |
370 throws IOException |
390 throws IOException |
371 { |
391 { |
372 if (addMods.isEmpty()) { |
392 if (roots.isEmpty()) { |
373 throw new IllegalArgumentException("empty modules and limitmods"); |
393 throw new IllegalArgumentException("empty modules and limitmods"); |
374 } |
394 } |
375 |
395 |
376 Configuration cf = Configuration.empty() |
396 Configuration cf = Configuration.empty() |
377 .resolveRequires(finder, |
397 .resolveRequires(finder, |
378 ModuleFinder.of(), |
398 ModuleFinder.of(), |
379 addMods); |
399 roots); |
380 |
400 |
381 Map<String, Path> mods = cf.modules().stream() |
401 Map<String, Path> mods = cf.modules().stream() |
382 .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation)); |
402 .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation)); |
383 return new ImageHelper(cf, mods, order, retainModulesPath, ignoreSigning); |
403 return new ImageHelper(cf, mods, order, retainModulesPath, ignoreSigning); |
384 } |
404 } |
386 /* |
406 /* |
387 * Returns a ModuleFinder that limits observability to the given root |
407 * Returns a ModuleFinder that limits observability to the given root |
388 * modules, their transitive dependences, plus a set of other modules. |
408 * modules, their transitive dependences, plus a set of other modules. |
389 */ |
409 */ |
390 private static ModuleFinder limitFinder(ModuleFinder finder, |
410 private static ModuleFinder limitFinder(ModuleFinder finder, |
391 Set<String> roots, |
411 Set<String> roots, |
392 Set<String> otherMods) { |
412 Set<String> otherMods) { |
393 |
413 |
394 // resolve all root modules |
414 // resolve all root modules |
395 Configuration cf = Configuration.empty() |
415 Configuration cf = Configuration.empty() |
396 .resolveRequires(finder, |
416 .resolveRequires(finder, |
397 ModuleFinder.of(), |
417 ModuleFinder.of(), |
533 } |
553 } |
534 } |
554 } |
535 return image; |
555 return image; |
536 } |
556 } |
537 } |
557 } |
538 |
|
539 private static enum Section { |
|
540 NATIVE_LIBS("native"), |
|
541 NATIVE_CMDS("bin"), |
|
542 CLASSES("classes"), |
|
543 CONFIG("conf"), |
|
544 UNKNOWN("unknown"); |
|
545 |
|
546 private final String jmodDir; |
|
547 |
|
548 Section(String jmodDir) { |
|
549 this.jmodDir = jmodDir; |
|
550 } |
|
551 |
|
552 String jmodDir() { |
|
553 return jmodDir; |
|
554 } |
|
555 |
|
556 boolean matches(String path) { |
|
557 return path.startsWith(jmodDir); |
|
558 } |
|
559 |
|
560 static Section getSectionFromName(String dir) { |
|
561 if (Section.NATIVE_LIBS.matches(dir)) { |
|
562 return Section.NATIVE_LIBS; |
|
563 } else if (Section.NATIVE_CMDS.matches(dir)) { |
|
564 return Section.NATIVE_CMDS; |
|
565 } else if (Section.CLASSES.matches(dir)) { |
|
566 return Section.CLASSES; |
|
567 } else if (Section.CONFIG.matches(dir)) { |
|
568 return Section.CONFIG; |
|
569 } else { |
|
570 return Section.UNKNOWN; |
|
571 } |
|
572 } |
|
573 } |
|
574 } |
558 } |