jdk/src/java.base/share/classes/java/lang/module/Resolver.java
changeset 44359 c6761862ca0b
parent 43712 5dfd0950317c
child 44545 83b611b88ac8
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java	Thu Mar 16 16:34:36 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java	Wed Mar 22 16:26:27 2017 +0000
@@ -47,6 +47,7 @@
 
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleReferenceImpl;
+import jdk.internal.module.ModuleTarget;
 
 /**
  * The resolver used by {@link Configuration#resolve} and {@link
@@ -69,11 +70,9 @@
     // module constraints on target platform
     private String osName;
     private String osArch;
-    private String osVersion;
 
     String osName() { return osName; }
     String osArch() { return osArch; }
-    String osVersion() { return osVersion; }
 
     /**
      * @throws IllegalArgumentException if there are more than one parent and
@@ -110,16 +109,6 @@
                     }
                 }
             }
-            value = parent.osVersion();
-            if (value != null) {
-                if (osVersion == null) {
-                    osVersion  = value;
-                } else {
-                    if (!value.equals(osVersion)) {
-                        failParentConflict("OS version", osVersion, value);
-                    }
-                }
-            }
         }
     }
 
@@ -318,13 +307,15 @@
      * the target platform with the constraints of other modules.
      */
     private void addFoundModule(ModuleReference mref) {
-        ModuleDescriptor descriptor = mref.descriptor();
-        nameToReference.put(descriptor.name(), mref);
+        String mn = mref.descriptor().name();
 
-        if (descriptor.osName().isPresent()
-                || descriptor.osArch().isPresent()
-                || descriptor.osVersion().isPresent())
-            checkTargetConstraints(descriptor);
+        if (mref instanceof ModuleReferenceImpl) {
+            ModuleTarget target = ((ModuleReferenceImpl)mref).moduleTarget();
+            if (target != null)
+                checkTargetConstraints(mn, target);
+        }
+
+        nameToReference.put(mn, mref);
     }
 
     /**
@@ -332,58 +323,44 @@
      * conflict with the constraints of other modules resolved so far or
      * modules in parent configurations.
      */
-    private void checkTargetConstraints(ModuleDescriptor descriptor) {
-        String value = descriptor.osName().orElse(null);
+    private void checkTargetConstraints(String mn, ModuleTarget target) {
+        String value = target.osName();
         if (value != null) {
             if (osName == null) {
                 osName = value;
             } else {
                 if (!value.equals(osName)) {
-                    failTargetConstraint(descriptor);
+                    failTargetConstraint(mn, target);
                 }
             }
         }
-        value = descriptor.osArch().orElse(null);
+        value = target.osArch();
         if (value != null) {
             if (osArch == null) {
                 osArch = value;
             } else {
                 if (!value.equals(osArch)) {
-                    failTargetConstraint(descriptor);
-                }
-            }
-        }
-        value = descriptor.osVersion().orElse(null);
-        if (value != null) {
-            if (osVersion == null) {
-                osVersion = value;
-            } else {
-                if (!value.equals(osVersion)) {
-                    failTargetConstraint(descriptor);
+                    failTargetConstraint(mn, target);
                 }
             }
         }
     }
 
-    private void failTargetConstraint(ModuleDescriptor md) {
-        String s1 = targetAsString(osName, osArch, osVersion);
-        String s2 = targetAsString(md);
-        findFail("Module %s has constraints on target platform that conflict" +
-                 " with other modules: %s, %s", md.name(), s1, s2);
+    private void failTargetConstraint(String mn, ModuleTarget target) {
+        String s1 = targetAsString(osName, osArch);
+        String s2 = targetAsString(target.osName(), target.osArch());
+        findFail("Module %s has constraints on target platform (%s) that"
+                 + " conflict with other modules: %s", mn, s1, s2);
     }
 
-    private String targetAsString(ModuleDescriptor descriptor) {
-        String osName = descriptor.osName().orElse(null);
-        String osArch = descriptor.osArch().orElse(null);
-        String osVersion = descriptor.osVersion().orElse(null);
-        return targetAsString(osName, osArch, osVersion);
+    private String targetAsString(ModuleTarget target) {
+        return targetAsString(target.osName(), target.osArch());
     }
 
-    private String targetAsString(String osName, String osArch, String osVersion) {
+    private String targetAsString(String osName, String osArch) {
         return new StringJoiner("-")
                 .add(Objects.toString(osName, "*"))
                 .add(Objects.toString(osArch, "*"))
-                .add(Objects.toString(osVersion, "*"))
                 .toString();
     }
 
@@ -712,16 +689,30 @@
 
 
     /**
-     * Checks the readability graph to ensure that no two modules export the
-     * same package to a module. This includes the case where module M has
-     * a local package P and M reads another module that exports P to M.
-     * Also checks the uses/provides of module M to ensure that it reads a
-     * module that exports the package of the service type to M.
+     * Checks the readability graph to ensure that
+     * <ol>
+     *   <li><p> A module does not read two or more modules with the same name.
+     *   This includes the case where a module reads another another with the
+     *   same name as itself. </p></li>
+     *   <li><p> Two or more modules in the configuration don't export the same
+     *   package to a module that reads both. This includes the case where a
+     *   module {@code M} containing package {@code p} reads another module
+     *   that exports {@code p} to {@code M}. </p></li>
+     *   <li><p> A module {@code M} doesn't declare that it "{@code uses p.S}"
+     *   or "{@code provides p.S with ...}" but package {@code p} is neither
+     *   in module {@code M} nor exported to {@code M} by any module that
+     *   {@code M} reads. </p></li>
+     * </ol>
      */
     private void checkExportSuppliers(Map<ResolvedModule, Set<ResolvedModule>> graph) {
 
         for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : graph.entrySet()) {
             ModuleDescriptor descriptor1 = e.getKey().descriptor();
+            String name1 = descriptor1.name();
+
+            // the names of the modules that are read (including self)
+            Set<String> names = new HashSet<>();
+            names.add(name1);
 
             // the map of packages that are local or exported to descriptor1
             Map<String, ModuleDescriptor> packageToExporter = new HashMap<>();
@@ -737,9 +728,20 @@
             for (ResolvedModule endpoint : reads) {
                 ModuleDescriptor descriptor2 = endpoint.descriptor();
 
+                String name2 = descriptor2.name();
+                if (descriptor2 != descriptor1 && !names.add(name2)) {
+                    if (name2.equals(name1)) {
+                        resolveFail("Module %s reads another module named %s",
+                                    name1, name1);
+                    } else{
+                        resolveFail("Module %s reads more than one module named %s",
+                                     name1, name2);
+                    }
+                }
+
                 if (descriptor2.isAutomatic()) {
                     // automatic modules read self and export all packages
-                    if (descriptor2 != descriptor1){
+                    if (descriptor2 != descriptor1) {
                         for (String source : descriptor2.packages()) {
                             ModuleDescriptor supplier
                                 = packageToExporter.putIfAbsent(source, descriptor2);