43 import java.util.Map; |
43 import java.util.Map; |
44 import java.util.Properties; |
44 import java.util.Properties; |
45 import java.util.ResourceBundle; |
45 import java.util.ResourceBundle; |
46 import java.util.Set; |
46 import java.util.Set; |
47 import java.util.Optional; |
47 import java.util.Optional; |
|
48 import java.util.Arrays; |
|
49 import java.util.stream.Collectors; |
|
50 import java.util.stream.Stream; |
|
51 import java.lang.module.Configuration; |
|
52 import java.lang.module.ResolvedModule; |
48 import java.lang.module.ModuleDescriptor; |
53 import java.lang.module.ModuleDescriptor; |
49 import java.lang.module.ModuleFinder; |
54 import java.lang.module.ModuleFinder; |
50 import java.lang.module.ModuleReference; |
55 import java.lang.module.ModuleReference; |
51 |
56 |
52 import jdk.tools.jlink.internal.packager.AppRuntimeImageBuilder; |
57 import jdk.tools.jlink.internal.packager.AppRuntimeImageBuilder; |
180 Set<String> limitModules = |
185 Set<String> limitModules = |
181 StandardBundlerParam.LIMIT_MODULES.fetchFrom(params); |
186 StandardBundlerParam.LIMIT_MODULES.fetchFrom(params); |
182 Path javaBasePath = findPathOfModule(modulePath, "java.base.jmod"); |
187 Path javaBasePath = findPathOfModule(modulePath, "java.base.jmod"); |
183 Set<String> addModules = getValidModules(modulePath, |
188 Set<String> addModules = getValidModules(modulePath, |
184 StandardBundlerParam.ADD_MODULES.fetchFrom(params), |
189 StandardBundlerParam.ADD_MODULES.fetchFrom(params), |
185 limitModules, true); |
190 limitModules); |
186 |
191 |
187 |
192 |
188 if (javaBasePath != null && javaBasePath.toFile().exists()) { |
193 if (javaBasePath != null && javaBasePath.toFile().exists()) { |
189 result = getModuleVersion(javaBasePath.toFile(), |
194 result = getModuleVersion(javaBasePath.toFile(), |
190 modulePath, addModules, limitModules); |
195 modulePath, addModules, limitModules); |
228 |
233 |
229 return result; |
234 return result; |
230 } |
235 } |
231 |
236 |
232 private static Set<String> getValidModules(List<Path> modulePath, |
237 private static Set<String> getValidModules(List<Path> modulePath, |
233 Set<String> addModules, Set<String> limitModules, |
238 Set<String> addModules, Set<String> limitModules) { |
234 boolean forJRE) { |
|
235 ModuleHelper moduleHelper = new ModuleHelper( |
239 ModuleHelper moduleHelper = new ModuleHelper( |
236 modulePath, addModules, limitModules, forJRE); |
240 modulePath, addModules, limitModules); |
237 return removeInvalidModules(modulePath, moduleHelper.modules()); |
241 return removeInvalidModules(modulePath, moduleHelper.modules()); |
238 } |
242 } |
239 |
243 |
240 static void execute(Map<String, ? super Object> params, |
244 static void execute(Map<String, ? super Object> params, |
241 AbstractAppImageBuilder imageBuilder) |
245 AbstractAppImageBuilder imageBuilder) |
260 mainJarType = ModFile.ModType.UnnamedJar; |
264 mainJarType = ModFile.ModType.UnnamedJar; |
261 } |
265 } |
262 |
266 |
263 // Modules |
267 // Modules |
264 |
268 |
265 // The default for an unnamed jar is ALL_DEFAULT with the |
|
266 // non-valid modules removed. |
|
267 if (mainJarType == ModFile.ModType.UnnamedJar) { |
269 if (mainJarType == ModFile.ModType.UnnamedJar) { |
268 addModules.add(ModuleHelper.ALL_RUNTIME); |
270 // The default for an unnamed jar is ALL_DEFAULT |
|
271 addModules.add(ModuleHelper.ALL_DEFAULT); |
269 } else if (mainJarType == ModFile.ModType.Unknown || |
272 } else if (mainJarType == ModFile.ModType.Unknown || |
270 mainJarType == ModFile.ModType.ModularJar) { |
273 mainJarType == ModFile.ModType.ModularJar) { |
271 String mainModule = getMainModule(params); |
274 String mainModule = getMainModule(params); |
272 addModules.add(mainModule); |
275 addModules.add(mainModule); |
273 } |
276 } |
274 addModules.addAll(getValidModules( |
277 addModules.addAll(getValidModules( |
275 modulePath, addModules, limitModules, false)); |
278 modulePath, addModules, limitModules)); |
276 |
279 |
277 Log.verbose(MessageFormat.format( |
280 Log.verbose(MessageFormat.format( |
278 I18N.getString("message.modules"), addModules.toString())); |
281 I18N.getString("message.modules"), addModules.toString())); |
279 |
282 |
280 AppRuntimeImageBuilder appRuntimeBuilder = new AppRuntimeImageBuilder(); |
283 AppRuntimeImageBuilder appRuntimeBuilder = new AppRuntimeImageBuilder(); |
300 Set<String> limitModules = |
303 Set<String> limitModules = |
301 StandardBundlerParam.LIMIT_MODULES.fetchFrom(params); |
304 StandardBundlerParam.LIMIT_MODULES.fetchFrom(params); |
302 boolean stripNativeCommands = |
305 boolean stripNativeCommands = |
303 StandardBundlerParam.STRIP_NATIVE_COMMANDS.fetchFrom(params); |
306 StandardBundlerParam.STRIP_NATIVE_COMMANDS.fetchFrom(params); |
304 Path outputDir = imageBuilder.getRoot(); |
307 Path outputDir = imageBuilder.getRoot(); |
305 addModules.add(ModuleHelper.ALL_RUNTIME); |
308 addModules.add(ModuleHelper.ALL_MODULE_PATH); |
306 Set<String> redistModules = getValidModules(modulePath, |
309 Set<String> redistModules = getValidModules(modulePath, |
307 addModules, limitModules, true); |
310 addModules, limitModules); |
308 addModules.addAll(redistModules); |
311 addModules.addAll(redistModules); |
309 |
312 |
310 Log.verbose(MessageFormat.format( |
313 Log.verbose(MessageFormat.format( |
311 I18N.getString("message.modules"), addModules.toString())); |
314 I18N.getString("message.modules"), addModules.toString())); |
312 |
315 |
338 } |
341 } |
339 |
342 |
340 return result; |
343 return result; |
341 } |
344 } |
342 |
345 |
|
346 /* |
|
347 * Returns the set of modules that would be visible by default for |
|
348 * a non-modular-aware application consisting of the given elements. |
|
349 */ |
|
350 private static Set<String> getDefaultModules( |
|
351 Path[] paths, String[] addModules) { |
|
352 |
|
353 // the modules in the run-time image that export an API |
|
354 Stream<String> systemRoots = ModuleFinder.ofSystem().findAll().stream() |
|
355 .map(ModuleReference::descriptor) |
|
356 .filter(descriptor -> exportsAPI(descriptor)) |
|
357 .map(ModuleDescriptor::name); |
|
358 |
|
359 Set<String> roots; |
|
360 if (addModules == null || addModules.length == 0) { |
|
361 roots = systemRoots.collect(Collectors.toSet()); |
|
362 } else { |
|
363 var extraRoots = Stream.of(addModules); |
|
364 roots = Stream.concat(systemRoots, |
|
365 extraRoots).collect(Collectors.toSet()); |
|
366 } |
|
367 |
|
368 ModuleFinder finder = ModuleFinder.ofSystem(); |
|
369 if (paths != null && paths.length > 0) { |
|
370 finder = ModuleFinder.compose(finder, ModuleFinder.of(paths)); |
|
371 } |
|
372 return Configuration.empty() |
|
373 .resolveAndBind(finder, ModuleFinder.of(), roots) |
|
374 .modules() |
|
375 .stream() |
|
376 .map(ResolvedModule::name) |
|
377 .collect(Collectors.toSet()); |
|
378 } |
|
379 |
|
380 /* |
|
381 * Returns true if the given module exports an API to all module. |
|
382 */ |
|
383 private static boolean exportsAPI(ModuleDescriptor descriptor) { |
|
384 return descriptor.exports() |
|
385 .stream() |
|
386 .filter(e -> !e.isQualified()) |
|
387 .findAny() |
|
388 .isPresent(); |
|
389 } |
|
390 |
343 private static Set<String> removeInvalidModules( |
391 private static Set<String> removeInvalidModules( |
344 List<Path> modulePath, Set<String> modules) { |
392 List<Path> modulePath, Set<String> modules) { |
345 Set<String> result = new LinkedHashSet<String>(); |
393 Set<String> result = new LinkedHashSet<String>(); |
346 ModuleManager mm = new ModuleManager(modulePath); |
394 ModuleManager mm = new ModuleManager(modulePath); |
347 List<ModFile> lmodfiles = |
395 List<ModFile> lmodfiles = |
396 private static class ModuleHelper { |
444 private static class ModuleHelper { |
397 // The token for "all modules on the module path". |
445 // The token for "all modules on the module path". |
398 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; |
446 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; |
399 |
447 |
400 // The token for "all valid runtime modules". |
448 // The token for "all valid runtime modules". |
401 static final String ALL_RUNTIME = "ALL-RUNTIME"; |
449 static final String ALL_DEFAULT = "ALL-DEFAULT"; |
402 |
450 |
403 private final Set<String> modules = new HashSet<>(); |
451 private final Set<String> modules = new HashSet<>(); |
404 private enum Macros {None, AllModulePath, AllRuntime} |
452 private enum Macros {None, AllModulePath, AllRuntime} |
405 |
453 |
406 ModuleHelper(List<Path> paths, Set<String> roots, |
454 ModuleHelper(List<Path> paths, Set<String> addModules, |
407 Set<String> limitMods, boolean forJRE) { |
455 Set<String> limitModules) { |
408 Macros macro = Macros.None; |
456 boolean addAllModulePath = false; |
409 |
457 boolean addDefaultMods = false; |
410 for (Iterator<String> iterator = roots.iterator(); |
458 |
|
459 for (Iterator<String> iterator = addModules.iterator(); |
411 iterator.hasNext();) { |
460 iterator.hasNext();) { |
412 String module = iterator.next(); |
461 String module = iterator.next(); |
413 |
462 |
414 switch (module) { |
463 switch (module) { |
415 case ALL_MODULE_PATH: |
464 case ALL_MODULE_PATH: |
416 iterator.remove(); |
465 iterator.remove(); |
417 macro = Macros.AllModulePath; |
466 addAllModulePath = true; |
418 break; |
467 break; |
419 case ALL_RUNTIME: |
468 case ALL_DEFAULT: |
420 iterator.remove(); |
469 iterator.remove(); |
421 macro = Macros.AllRuntime; |
470 addDefaultMods = true; |
422 break; |
471 break; |
423 default: |
472 default: |
424 this.modules.add(module); |
473 this.modules.add(module); |
425 } |
474 } |
426 } |
475 } |
427 |
476 |
428 switch (macro) { |
477 if (addAllModulePath) { |
429 case AllModulePath: |
478 this.modules.addAll(getModuleNamesFromPath(paths)); |
430 this.modules.addAll(getModuleNamesFromPath(paths)); |
479 } else if (addDefaultMods) { |
431 break; |
480 this.modules.addAll(getDefaultModules( |
432 case AllRuntime: |
481 paths.toArray(new Path[0]), |
433 Set<Module> runtimeModules = |
482 addModules.toArray(new String[0]))); |
434 ModuleLayer.boot().modules(); |
|
435 for (Module m : runtimeModules) { |
|
436 String name = m.getName(); |
|
437 if (forJRE && isModuleExcludedFromJRE(name)) { |
|
438 continue; // JRE does not include this module |
|
439 } |
|
440 this.modules.add(name); |
|
441 } |
|
442 break; |
|
443 } |
483 } |
444 } |
484 } |
445 |
485 |
446 Set<String> modules() { |
486 Set<String> modules() { |
447 return modules; |
487 return modules; |
448 } |
488 } |
449 |
489 |
450 private boolean isModuleExcludedFromJRE(String name) { |
|
451 return false; // not excluding any modules from JRE at this time |
|
452 } |
|
453 |
|
454 private static Set<String> getModuleNamesFromPath(List<Path> Value) { |
490 private static Set<String> getModuleNamesFromPath(List<Path> Value) { |
455 Set<String> result = new LinkedHashSet<String>(); |
491 Set<String> result = new LinkedHashSet<String>(); |
456 ModuleManager mm = new ModuleManager(Value); |
492 ModuleManager mm = new ModuleManager(Value); |
457 List<ModFile> modFiles = |
493 List<ModFile> modFiles = mm.getModules( |
458 mm.getModules( |
494 EnumSet.of(ModuleManager.SearchType.ModularJar, |
459 EnumSet.of(ModuleManager.SearchType.ModularJar, |
495 ModuleManager.SearchType.Jmod, |
460 ModuleManager.SearchType.Jmod, |
496 ModuleManager.SearchType.ExplodedModule)); |
461 ModuleManager.SearchType.ExplodedModule)); |
497 |
462 |
498 for (ModFile modFile : modFiles) { |
463 for (ModFile modFile : modFiles) { |
499 result.add(modFile.getModName()); |
464 result.add(modFile.getModName()); |
500 } |
465 } |
501 return result; |
466 |
|
467 return result; |
|
468 } |
502 } |
469 } |
503 } |
470 } |
504 } |