jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
changeset 42338 a60f280f803c
parent 41414 7fd4548e9733
child 42703 20c39ea4a507
--- 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<String, List<String>> 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<String, Set<String>> map = decode("jdk.module.addreads.");
+        Map<String, List<String>> map = decode("jdk.module.addreads.");
+        if (map.isEmpty())
+            return;
 
-        for (Map.Entry<String, Set<String>> e : map.entrySet()) {
+        for (Map.Entry<String, List<String>> 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<String, List<String>> extraExports = decode(prefix);
+        if (!extraExports.isEmpty()) {
+            addExtraExportsOrOpens(bootLayer, extraExports, false);
+        }
 
-        // decode the command line options
-        Map<String, Set<String>> map = decode("jdk.module.addexports.");
+        // --add-opens
+        prefix = "jdk.module.addopens.";
+        Map<String, List<String>> extraOpens = decode(prefix);
+        if (!extraOpens.isEmpty()) {
+            addExtraExportsOrOpens(bootLayer, extraOpens, true);
+        }
+    }
 
-        for (Map.Entry<String, Set<String>> e : map.entrySet()) {
+    private static void addExtraExportsOrOpens(Layer bootLayer,
+                                               Map<String, List<String>> map,
+                                               boolean opens)
+    {
+        for (Map.Entry<String, List<String>> 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<String, Set<String>> decode(String prefix) {
+    private static Map<String, List<String>> 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<String, Set<String>> map = new HashMap<>();
+        Map<String, List<String>> map = new HashMap<>();
 
         while (value != null) {
 
@@ -545,8 +596,11 @@
             if (rhs.isEmpty())
                 fail("Unable to parse: " + value);
 
-            Set<String> values = map.computeIfAbsent(key, k -> new HashSet<>());
-            for (String s : rhs.split(",")) {
+            // value is <module>(,<module>)* or <file>(<pathsep><file>)*
+            if (!allowDuplicates && map.containsKey(key))
+                fail(key + " specified more than once");
+            List<String> 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<String, List<String>> decode(String prefix) {
+        return decode(prefix, ",", true);
+    }
+
+    /**
      * Gets and remove the named system property
      */
     private static String getAndRemoveProperty(String key) {