jdk/src/java.base/share/classes/java/lang/module/Resolver.java
changeset 44359 c6761862ca0b
parent 43712 5dfd0950317c
child 44545 83b611b88ac8
equal deleted inserted replaced
44210:5a8499c4b32c 44359:c6761862ca0b
    45 import java.util.StringJoiner;
    45 import java.util.StringJoiner;
    46 import java.util.stream.Collectors;
    46 import java.util.stream.Collectors;
    47 
    47 
    48 import jdk.internal.module.ModuleHashes;
    48 import jdk.internal.module.ModuleHashes;
    49 import jdk.internal.module.ModuleReferenceImpl;
    49 import jdk.internal.module.ModuleReferenceImpl;
       
    50 import jdk.internal.module.ModuleTarget;
    50 
    51 
    51 /**
    52 /**
    52  * The resolver used by {@link Configuration#resolve} and {@link
    53  * The resolver used by {@link Configuration#resolve} and {@link
    53  * Configuration#resolveAndBind}.
    54  * Configuration#resolveAndBind}.
    54  *
    55  *
    67     private final Map<String, ModuleReference> nameToReference = new HashMap<>();
    68     private final Map<String, ModuleReference> nameToReference = new HashMap<>();
    68 
    69 
    69     // module constraints on target platform
    70     // module constraints on target platform
    70     private String osName;
    71     private String osName;
    71     private String osArch;
    72     private String osArch;
    72     private String osVersion;
       
    73 
    73 
    74     String osName() { return osName; }
    74     String osName() { return osName; }
    75     String osArch() { return osArch; }
    75     String osArch() { return osArch; }
    76     String osVersion() { return osVersion; }
       
    77 
    76 
    78     /**
    77     /**
    79      * @throws IllegalArgumentException if there are more than one parent and
    78      * @throws IllegalArgumentException if there are more than one parent and
    80      *         the constraints on the target platform conflict
    79      *         the constraints on the target platform conflict
    81      */
    80      */
   105                 if (osArch == null) {
   104                 if (osArch == null) {
   106                     osArch = value;
   105                     osArch = value;
   107                 } else {
   106                 } else {
   108                     if (!value.equals(osArch)) {
   107                     if (!value.equals(osArch)) {
   109                         failParentConflict("OS architecture", osArch, value);
   108                         failParentConflict("OS architecture", osArch, value);
   110                     }
       
   111                 }
       
   112             }
       
   113             value = parent.osVersion();
       
   114             if (value != null) {
       
   115                 if (osVersion == null) {
       
   116                     osVersion  = value;
       
   117                 } else {
       
   118                     if (!value.equals(osVersion)) {
       
   119                         failParentConflict("OS version", osVersion, value);
       
   120                     }
   109                     }
   121                 }
   110                 }
   122             }
   111             }
   123         }
   112         }
   124     }
   113     }
   316     /**
   305     /**
   317      * Add the module to the nameToReference map. Also check any constraints on
   306      * Add the module to the nameToReference map. Also check any constraints on
   318      * the target platform with the constraints of other modules.
   307      * the target platform with the constraints of other modules.
   319      */
   308      */
   320     private void addFoundModule(ModuleReference mref) {
   309     private void addFoundModule(ModuleReference mref) {
   321         ModuleDescriptor descriptor = mref.descriptor();
   310         String mn = mref.descriptor().name();
   322         nameToReference.put(descriptor.name(), mref);
   311 
   323 
   312         if (mref instanceof ModuleReferenceImpl) {
   324         if (descriptor.osName().isPresent()
   313             ModuleTarget target = ((ModuleReferenceImpl)mref).moduleTarget();
   325                 || descriptor.osArch().isPresent()
   314             if (target != null)
   326                 || descriptor.osVersion().isPresent())
   315                 checkTargetConstraints(mn, target);
   327             checkTargetConstraints(descriptor);
   316         }
       
   317 
       
   318         nameToReference.put(mn, mref);
   328     }
   319     }
   329 
   320 
   330     /**
   321     /**
   331      * Check that the module's constraints on the target platform do not
   322      * Check that the module's constraints on the target platform do not
   332      * conflict with the constraints of other modules resolved so far or
   323      * conflict with the constraints of other modules resolved so far or
   333      * modules in parent configurations.
   324      * modules in parent configurations.
   334      */
   325      */
   335     private void checkTargetConstraints(ModuleDescriptor descriptor) {
   326     private void checkTargetConstraints(String mn, ModuleTarget target) {
   336         String value = descriptor.osName().orElse(null);
   327         String value = target.osName();
   337         if (value != null) {
   328         if (value != null) {
   338             if (osName == null) {
   329             if (osName == null) {
   339                 osName = value;
   330                 osName = value;
   340             } else {
   331             } else {
   341                 if (!value.equals(osName)) {
   332                 if (!value.equals(osName)) {
   342                     failTargetConstraint(descriptor);
   333                     failTargetConstraint(mn, target);
   343                 }
   334                 }
   344             }
   335             }
   345         }
   336         }
   346         value = descriptor.osArch().orElse(null);
   337         value = target.osArch();
   347         if (value != null) {
   338         if (value != null) {
   348             if (osArch == null) {
   339             if (osArch == null) {
   349                 osArch = value;
   340                 osArch = value;
   350             } else {
   341             } else {
   351                 if (!value.equals(osArch)) {
   342                 if (!value.equals(osArch)) {
   352                     failTargetConstraint(descriptor);
   343                     failTargetConstraint(mn, target);
   353                 }
   344                 }
   354             }
   345             }
   355         }
   346         }
   356         value = descriptor.osVersion().orElse(null);
   347     }
   357         if (value != null) {
   348 
   358             if (osVersion == null) {
   349     private void failTargetConstraint(String mn, ModuleTarget target) {
   359                 osVersion = value;
   350         String s1 = targetAsString(osName, osArch);
   360             } else {
   351         String s2 = targetAsString(target.osName(), target.osArch());
   361                 if (!value.equals(osVersion)) {
   352         findFail("Module %s has constraints on target platform (%s) that"
   362                     failTargetConstraint(descriptor);
   353                  + " conflict with other modules: %s", mn, s1, s2);
   363                 }
   354     }
   364             }
   355 
   365         }
   356     private String targetAsString(ModuleTarget target) {
   366     }
   357         return targetAsString(target.osName(), target.osArch());
   367 
   358     }
   368     private void failTargetConstraint(ModuleDescriptor md) {
   359 
   369         String s1 = targetAsString(osName, osArch, osVersion);
   360     private String targetAsString(String osName, String osArch) {
   370         String s2 = targetAsString(md);
       
   371         findFail("Module %s has constraints on target platform that conflict" +
       
   372                  " with other modules: %s, %s", md.name(), s1, s2);
       
   373     }
       
   374 
       
   375     private String targetAsString(ModuleDescriptor descriptor) {
       
   376         String osName = descriptor.osName().orElse(null);
       
   377         String osArch = descriptor.osArch().orElse(null);
       
   378         String osVersion = descriptor.osVersion().orElse(null);
       
   379         return targetAsString(osName, osArch, osVersion);
       
   380     }
       
   381 
       
   382     private String targetAsString(String osName, String osArch, String osVersion) {
       
   383         return new StringJoiner("-")
   361         return new StringJoiner("-")
   384                 .add(Objects.toString(osName, "*"))
   362                 .add(Objects.toString(osName, "*"))
   385                 .add(Objects.toString(osArch, "*"))
   363                 .add(Objects.toString(osArch, "*"))
   386                 .add(Objects.toString(osVersion, "*"))
       
   387                 .toString();
   364                 .toString();
   388     }
   365     }
   389 
   366 
   390 
   367 
   391     /**
   368     /**
   710         return m;
   687         return m;
   711     }
   688     }
   712 
   689 
   713 
   690 
   714     /**
   691     /**
   715      * Checks the readability graph to ensure that no two modules export the
   692      * Checks the readability graph to ensure that
   716      * same package to a module. This includes the case where module M has
   693      * <ol>
   717      * a local package P and M reads another module that exports P to M.
   694      *   <li><p> A module does not read two or more modules with the same name.
   718      * Also checks the uses/provides of module M to ensure that it reads a
   695      *   This includes the case where a module reads another another with the
   719      * module that exports the package of the service type to M.
   696      *   same name as itself. </p></li>
       
   697      *   <li><p> Two or more modules in the configuration don't export the same
       
   698      *   package to a module that reads both. This includes the case where a
       
   699      *   module {@code M} containing package {@code p} reads another module
       
   700      *   that exports {@code p} to {@code M}. </p></li>
       
   701      *   <li><p> A module {@code M} doesn't declare that it "{@code uses p.S}"
       
   702      *   or "{@code provides p.S with ...}" but package {@code p} is neither
       
   703      *   in module {@code M} nor exported to {@code M} by any module that
       
   704      *   {@code M} reads. </p></li>
       
   705      * </ol>
   720      */
   706      */
   721     private void checkExportSuppliers(Map<ResolvedModule, Set<ResolvedModule>> graph) {
   707     private void checkExportSuppliers(Map<ResolvedModule, Set<ResolvedModule>> graph) {
   722 
   708 
   723         for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : graph.entrySet()) {
   709         for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : graph.entrySet()) {
   724             ModuleDescriptor descriptor1 = e.getKey().descriptor();
   710             ModuleDescriptor descriptor1 = e.getKey().descriptor();
       
   711             String name1 = descriptor1.name();
       
   712 
       
   713             // the names of the modules that are read (including self)
       
   714             Set<String> names = new HashSet<>();
       
   715             names.add(name1);
   725 
   716 
   726             // the map of packages that are local or exported to descriptor1
   717             // the map of packages that are local or exported to descriptor1
   727             Map<String, ModuleDescriptor> packageToExporter = new HashMap<>();
   718             Map<String, ModuleDescriptor> packageToExporter = new HashMap<>();
   728 
   719 
   729             // local packages
   720             // local packages
   735             // descriptor1 reads descriptor2
   726             // descriptor1 reads descriptor2
   736             Set<ResolvedModule> reads = e.getValue();
   727             Set<ResolvedModule> reads = e.getValue();
   737             for (ResolvedModule endpoint : reads) {
   728             for (ResolvedModule endpoint : reads) {
   738                 ModuleDescriptor descriptor2 = endpoint.descriptor();
   729                 ModuleDescriptor descriptor2 = endpoint.descriptor();
   739 
   730 
       
   731                 String name2 = descriptor2.name();
       
   732                 if (descriptor2 != descriptor1 && !names.add(name2)) {
       
   733                     if (name2.equals(name1)) {
       
   734                         resolveFail("Module %s reads another module named %s",
       
   735                                     name1, name1);
       
   736                     } else{
       
   737                         resolveFail("Module %s reads more than one module named %s",
       
   738                                      name1, name2);
       
   739                     }
       
   740                 }
       
   741 
   740                 if (descriptor2.isAutomatic()) {
   742                 if (descriptor2.isAutomatic()) {
   741                     // automatic modules read self and export all packages
   743                     // automatic modules read self and export all packages
   742                     if (descriptor2 != descriptor1){
   744                     if (descriptor2 != descriptor1) {
   743                         for (String source : descriptor2.packages()) {
   745                         for (String source : descriptor2.packages()) {
   744                             ModuleDescriptor supplier
   746                             ModuleDescriptor supplier
   745                                 = packageToExporter.putIfAbsent(source, descriptor2);
   747                                 = packageToExporter.putIfAbsent(source, descriptor2);
   746 
   748 
   747                             // descriptor2 and 'supplier' export source to descriptor1
   749                             // descriptor2 and 'supplier' export source to descriptor1