diff -r 7a4a59859ac0 -r a60f280f803c jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Wed Nov 23 16:16:35 2016 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Thu Dec 01 08:57:53 2016 +0000 @@ -37,9 +37,11 @@ import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -81,10 +83,20 @@ // the token for "all modules on the module path" private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; + // The ModulePatcher for the initial configuration + private static final ModulePatcher patcher = initModulePatcher(); + // ModuleFinder for the initial configuration private static ModuleFinder initialFinder; /** + * Returns the ModulePatcher for the initial configuration. + */ + public static ModulePatcher patcher() { + return patcher; + } + + /** * Returns the ModuleFinder for the initial configuration */ public static ModuleFinder finder() { @@ -101,7 +113,7 @@ long t0 = System.nanoTime(); - // system modules + // system modules (may be patched) ModuleFinder systemModules = ModuleFinder.ofSystem(); PerfCounters.systemModulesTime.addElapsedTimeFrom(t0); @@ -247,7 +259,7 @@ if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here && (upgradeModulePath == null) && (appModulePath == null) - && (!ModulePatcher.isBootLayerPatched())) { + && (patcher.isEmpty())) { needPostResolutionChecks = false; } @@ -314,9 +326,9 @@ PerfCounters.loadModulesTime.addElapsedTimeFrom(t5); - // --add-reads and --add-exports + // --add-reads, -add-exports/-add-opens addExtraReads(bootLayer); - addExtraExports(bootLayer); + addExtraExportsAndOpens(bootLayer); // total time to initialize PerfCounters.bootstrapTime.addElapsedTimeFrom(t0); @@ -389,6 +401,18 @@ } } + + /** + * Initialize the module patcher for the initial configuration passed on the + * value of the --patch-module options. + */ + private static ModulePatcher initModulePatcher() { + Map> map = decode("jdk.module.patch.", + File.pathSeparator, + false); + return new ModulePatcher(map); + } + /** * Returns the set of module names specified via --add-modules options * on the command line @@ -408,7 +432,6 @@ for (String s : value.split(",")) { if (s.length() > 0) modules.add(s); } - index++; value = getAndRemoveProperty(prefix + index); } @@ -423,9 +446,11 @@ private static void addExtraReads(Layer bootLayer) { // decode the command line options - Map> map = decode("jdk.module.addreads."); + Map> map = decode("jdk.module.addreads."); + if (map.isEmpty()) + return; - for (Map.Entry> e : map.entrySet()) { + for (Map.Entry> e : map.entrySet()) { // the key is $MODULE String mn = e.getKey(); @@ -448,22 +473,36 @@ warn("Unknown module: " + name); } } - } } } - /** - * Process the --add-exports options to add any additional read edges that - * are specified on the command-line. + * Process the --add-exports and --add-opens options to export/open + * additional packages specified on the command-line. */ - private static void addExtraExports(Layer bootLayer) { + private static void addExtraExportsAndOpens(Layer bootLayer) { + + // --add-exports + String prefix = "jdk.module.addexports."; + Map> extraExports = decode(prefix); + if (!extraExports.isEmpty()) { + addExtraExportsOrOpens(bootLayer, extraExports, false); + } - // decode the command line options - Map> map = decode("jdk.module.addexports."); + // --add-opens + prefix = "jdk.module.addopens."; + Map> extraOpens = decode(prefix); + if (!extraOpens.isEmpty()) { + addExtraExportsOrOpens(bootLayer, extraOpens, true); + } + } - for (Map.Entry> e : map.entrySet()) { + private static void addExtraExportsOrOpens(Layer bootLayer, + Map> map, + boolean opens) + { + for (Map.Entry> e : map.entrySet()) { // the key is $MODULE/$PACKAGE String key = e.getKey(); @@ -507,28 +546,40 @@ } } if (allUnnamed) { - Modules.addExportsToAllUnnamed(m, pn); + if (opens) { + Modules.addOpensToAllUnnamed(m, pn); + } else { + Modules.addExportsToAllUnnamed(m, pn); + } } else { - Modules.addExports(m, pn, other); + if (opens) { + Modules.addOpens(m, pn, other); + } else { + Modules.addExports(m, pn, other); + } } + } } } - /** - * Decodes the values of --add-reads or --add-exports options + * Decodes the values of --add-reads, -add-exports, --add-opens or + * --patch-modules options that are encoded in system properties. * - * The format of the options is: $KEY=$MODULE(,$MODULE)* + * @param prefix the system property prefix + * @praam regex the regex for splitting the RHS of the option value */ - private static Map> decode(String prefix) { + private static Map> decode(String prefix, + String regex, + boolean allowDuplicates) { int index = 0; // the system property is removed after decoding String value = getAndRemoveProperty(prefix + index); if (value == null) return Collections.emptyMap(); - Map> map = new HashMap<>(); + Map> map = new HashMap<>(); while (value != null) { @@ -545,8 +596,11 @@ if (rhs.isEmpty()) fail("Unable to parse: " + value); - Set values = map.computeIfAbsent(key, k -> new HashSet<>()); - for (String s : rhs.split(",")) { + // value is (,)* or ()* + if (!allowDuplicates && map.containsKey(key)) + fail(key + " specified more than once"); + List values = map.computeIfAbsent(key, k -> new ArrayList<>()); + for (String s : rhs.split(regex)) { if (s.length() > 0) values.add(s); } @@ -558,6 +612,14 @@ } /** + * Decodes the values of --add-reads, -add-exports or --add-opens + * which use the "," to separate the RHS of the option value. + */ + private static Map> decode(String prefix) { + return decode(prefix, ",", true); + } + + /** * Gets and remove the named system property */ private static String getAndRemoveProperty(String key) {