src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java
branchJDK-8200758-branch
changeset 57126 8041f62342f0
parent 57125 846d4865b362
child 57197 7fc5a57945d2
equal deleted inserted replaced
57125:846d4865b362 57126:8041f62342f0
    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 }