< prev index next >

src/java.base/share/classes/java/lang/module/Configuration.java

Print this page




  95  *
  96  * @since 9
  97  * @spec JPMS
  98  * @see java.lang.reflect.Layer
  99  */
 100 public final class Configuration {
 101 
 102     // @see Configuration#empty()
 103     private static final Configuration EMPTY_CONFIGURATION = new Configuration();
 104 
 105     // parent configurations, in search order
 106     private final List<Configuration> parents;
 107 
 108     private final Map<ResolvedModule, Set<ResolvedModule>> graph;
 109     private final Set<ResolvedModule> modules;
 110     private final Map<String, ResolvedModule> nameToModule;
 111 
 112     // module constraints on target
 113     private final String osName;
 114     private final String osArch;
 115     private final String osVersion;
 116 
 117     String osName() { return osName; }
 118     String osArch() { return osArch; }
 119     String osVersion() { return osVersion; }
 120 
 121     private Configuration() {
 122         this.parents = Collections.emptyList();
 123         this.graph = Collections.emptyMap();
 124         this.modules = Collections.emptySet();
 125         this.nameToModule = Collections.emptyMap();
 126         this.osName = null;
 127         this.osArch = null;
 128         this.osVersion = null;
 129     }
 130 
 131     private Configuration(List<Configuration> parents,
 132                           Resolver resolver,
 133                           boolean check)
 134     {
 135         Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check);
 136 
 137         @SuppressWarnings(value = {"rawtypes", "unchecked"})
 138         Entry<String, ResolvedModule>[] nameEntries
 139             = (Entry<String, ResolvedModule>[])new Entry[g.size()];
 140         ResolvedModule[] moduleArray = new ResolvedModule[g.size()];
 141         int i = 0;
 142         for (ResolvedModule resolvedModule : g.keySet()) {
 143             moduleArray[i] = resolvedModule;
 144             nameEntries[i] = Map.entry(resolvedModule.name(), resolvedModule);
 145             i++;
 146         }
 147 
 148         this.parents = Collections.unmodifiableList(parents);
 149         this.graph = g;
 150         this.modules = Set.of(moduleArray);
 151         this.nameToModule = Map.ofEntries(nameEntries);
 152 
 153         this.osName = resolver.osName();
 154         this.osArch = resolver.osArch();
 155         this.osVersion = resolver.osVersion();
 156     }
 157 
 158     /**
 159      * Resolves a collection of root modules, with this configuration as its
 160      * parent, to create a new configuration. This method works exactly as
 161      * specified by the static {@link
 162      * #resolve(ModuleFinder,List,ModuleFinder,Collection) resolve}
 163      * method when invoked with this configuration as the parent. In other words,
 164      * if this configuration is {@code cf} then this method is equivalent to
 165      * invoking:
 166      * <pre> {@code
 167      *     Configuration.resolve(before, List.of(cf), after, roots);
 168      * }</pre>
 169      *
 170      * @param  before
 171      *         The <em>before</em> module finder to find modules
 172      * @param  after
 173      *         The <em>after</em> module finder to locate modules when not
 174      *         located by the {@code before} module finder or in parent
 175      *         configurations


 264      * Resolves a collection of root modules to create a configuration.
 265      *
 266      * <p> Each root module is located using the given {@code before} module
 267      * finder. If a module is not found then it is located in the parent
 268      * configuration as if by invoking the {@link #findModule(String)
 269      * findModule} method on each parent in iteration order. If not found then
 270      * the module is located using the given {@code after} module finder. The
 271      * same search order is used to locate transitive dependences. Root modules
 272      * or dependences that are located in a parent configuration are resolved
 273      * no further and are not included in the resulting configuration. </p>
 274      *
 275      * <p> When all modules have been resolved then the resulting dependency
 276      * graph is checked to ensure that it does not contain cycles. A
 277      * readability graph is constructed, and in conjunction with the module
 278      * exports and service use, checked for consistency. </p>
 279      *
 280      * <p> Resolution may fail with {@code FindException} for the following
 281      * <em>observability-related</em> reasons: </p>
 282      *
 283      * <ul>

 284      *     <li><p> A root module, or a direct or transitive dependency, is not
 285      *     found. </p></li>
 286      *
 287      *     <li><p> An error occurs when attempting to find a module.
 288      *     Possible errors include I/O errors, errors detected parsing a module
 289      *     descriptor ({@code module-info.class}) or two versions of the same
 290      *     module are found in the same directory. </p></li>
 291      *
 292      *     <li><p> A module with the required name is found but the module
 293      *     requires a different {@link ModuleDescriptor#osName() operating
 294      *     system}, {@link ModuleDescriptor#osArch() architecture}, or {@link
 295      *     ModuleDescriptor#osVersion() version} to other modules that have
 296      *     been resolved for the new configuration or modules in the parent
 297      *     configurations. </p></li>
 298      *
 299      * </ul>
 300      *
 301      * <p> Post-resolution consistency checks may fail with {@code
 302      * ResolutionException} for the following reasons: </p>
 303      *
 304      * <ul>
 305      *
 306      *     <li><p> A cycle is detected, say where module {@code m1} requires
 307      *     module {@code m2} and {@code m2} requires {@code m1}. </p></li>
 308      *




 309      *     <li><p> Two or more modules in the configuration export the same
 310      *     package to a module that reads both. This includes the case where a
 311      *     module {@code M} containing package {@code p} reads another module
 312      *     that exports {@code p} to {@code M}. </p></li>
 313      *
 314      *     <li><p> A module {@code M} declares that it "{@code uses p.S}" or
 315      *     "{@code provides p.S with ...}" but package {@code p} is neither in
 316      *     module {@code M} nor exported to {@code M} by any module that
 317      *     {@code M} reads. </p></li>
 318      *
 319      * </ul>
 320      *
 321      * @implNote In the implementation then observability of modules may depend
 322      * on referential integrity checks that ensure different builds of tightly
 323      * coupled modules are not combined in the same configuration.

 324      *
 325      * @param  before
 326      *         The <em>before</em> module finder to find modules
 327      * @param  parents
 328      *         The list parent configurations in search order
 329      * @param  after
 330      *         The <em>after</em> module finder to locate modules when not
 331      *         located by the {@code before} module finder or in parent
 332      *         configurations
 333      * @param  roots
 334      *         The possibly-empty collection of module names of the modules
 335      *         to resolve
 336      *
 337      * @return The configuration that is the result of resolving the given
 338      *         root modules
 339      *
 340      * @throws FindException
 341      *         If resolution fails for an observability-related reason
 342      * @throws ResolutionException
 343      *         If a post-resolution consistency checks fails




  95  *
  96  * @since 9
  97  * @spec JPMS
  98  * @see java.lang.reflect.Layer
  99  */
 100 public final class Configuration {
 101 
 102     // @see Configuration#empty()
 103     private static final Configuration EMPTY_CONFIGURATION = new Configuration();
 104 
 105     // parent configurations, in search order
 106     private final List<Configuration> parents;
 107 
 108     private final Map<ResolvedModule, Set<ResolvedModule>> graph;
 109     private final Set<ResolvedModule> modules;
 110     private final Map<String, ResolvedModule> nameToModule;
 111 
 112     // module constraints on target
 113     private final String osName;
 114     private final String osArch;

 115 
 116     String osName() { return osName; }
 117     String osArch() { return osArch; }

 118 
 119     private Configuration() {
 120         this.parents = Collections.emptyList();
 121         this.graph = Collections.emptyMap();
 122         this.modules = Collections.emptySet();
 123         this.nameToModule = Collections.emptyMap();
 124         this.osName = null;
 125         this.osArch = null;

 126     }
 127 
 128     private Configuration(List<Configuration> parents,
 129                           Resolver resolver,
 130                           boolean check)
 131     {
 132         Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check);
 133 
 134         @SuppressWarnings(value = {"rawtypes", "unchecked"})
 135         Entry<String, ResolvedModule>[] nameEntries
 136             = (Entry<String, ResolvedModule>[])new Entry[g.size()];
 137         ResolvedModule[] moduleArray = new ResolvedModule[g.size()];
 138         int i = 0;
 139         for (ResolvedModule resolvedModule : g.keySet()) {
 140             moduleArray[i] = resolvedModule;
 141             nameEntries[i] = Map.entry(resolvedModule.name(), resolvedModule);
 142             i++;
 143         }
 144 
 145         this.parents = Collections.unmodifiableList(parents);
 146         this.graph = g;
 147         this.modules = Set.of(moduleArray);
 148         this.nameToModule = Map.ofEntries(nameEntries);
 149 
 150         this.osName = resolver.osName();
 151         this.osArch = resolver.osArch();

 152     }
 153 
 154     /**
 155      * Resolves a collection of root modules, with this configuration as its
 156      * parent, to create a new configuration. This method works exactly as
 157      * specified by the static {@link
 158      * #resolve(ModuleFinder,List,ModuleFinder,Collection) resolve}
 159      * method when invoked with this configuration as the parent. In other words,
 160      * if this configuration is {@code cf} then this method is equivalent to
 161      * invoking:
 162      * <pre> {@code
 163      *     Configuration.resolve(before, List.of(cf), after, roots);
 164      * }</pre>
 165      *
 166      * @param  before
 167      *         The <em>before</em> module finder to find modules
 168      * @param  after
 169      *         The <em>after</em> module finder to locate modules when not
 170      *         located by the {@code before} module finder or in parent
 171      *         configurations


 260      * Resolves a collection of root modules to create a configuration.
 261      *
 262      * <p> Each root module is located using the given {@code before} module
 263      * finder. If a module is not found then it is located in the parent
 264      * configuration as if by invoking the {@link #findModule(String)
 265      * findModule} method on each parent in iteration order. If not found then
 266      * the module is located using the given {@code after} module finder. The
 267      * same search order is used to locate transitive dependences. Root modules
 268      * or dependences that are located in a parent configuration are resolved
 269      * no further and are not included in the resulting configuration. </p>
 270      *
 271      * <p> When all modules have been resolved then the resulting dependency
 272      * graph is checked to ensure that it does not contain cycles. A
 273      * readability graph is constructed, and in conjunction with the module
 274      * exports and service use, checked for consistency. </p>
 275      *
 276      * <p> Resolution may fail with {@code FindException} for the following
 277      * <em>observability-related</em> reasons: </p>
 278      *
 279      * <ul>
 280      *
 281      *     <li><p> A root module, or a direct or transitive dependency, is not
 282      *     found. </p></li>
 283      *
 284      *     <li><p> An error occurs when attempting to find a module.
 285      *     Possible errors include I/O errors, errors detected parsing a module
 286      *     descriptor ({@code module-info.class}) or two versions of the same
 287      *     module are found in the same directory. </p></li>
 288      *







 289      * </ul>
 290      *
 291      * <p> Post-resolution consistency checks may fail with {@code
 292      * ResolutionException} for the following reasons: </p>
 293      *
 294      * <ul>
 295      *
 296      *     <li><p> A cycle is detected, say where module {@code m1} requires
 297      *     module {@code m2} and {@code m2} requires {@code m1}. </p></li>
 298      *
 299      *     <li><p> A module reads two or more modules with the same name. This
 300      *     includes the case where a module reads another with the same name as
 301      *     itself. </p></li>
 302      *
 303      *     <li><p> Two or more modules in the configuration export the same
 304      *     package to a module that reads both. This includes the case where a
 305      *     module {@code M} containing package {@code p} reads another module
 306      *     that exports {@code p} to {@code M}. </p></li>
 307      *
 308      *     <li><p> A module {@code M} declares that it "{@code uses p.S}" or
 309      *     "{@code provides p.S with ...}" but package {@code p} is neither in
 310      *     module {@code M} nor exported to {@code M} by any module that
 311      *     {@code M} reads. </p></li>
 312      *
 313      * </ul>
 314      *
 315      * @implNote In the implementation then observability of modules may depend
 316      * on referential integrity or other checks that ensure different builds of
 317      * tightly coupled modules or modules for specific operating systems or
 318      * architectures are not combined in the same configuration.
 319      *
 320      * @param  before
 321      *         The <em>before</em> module finder to find modules
 322      * @param  parents
 323      *         The list parent configurations in search order
 324      * @param  after
 325      *         The <em>after</em> module finder to locate modules when not
 326      *         located by the {@code before} module finder or in parent
 327      *         configurations
 328      * @param  roots
 329      *         The possibly-empty collection of module names of the modules
 330      *         to resolve
 331      *
 332      * @return The configuration that is the result of resolving the given
 333      *         root modules
 334      *
 335      * @throws FindException
 336      *         If resolution fails for an observability-related reason
 337      * @throws ResolutionException
 338      *         If a post-resolution consistency checks fails


< prev index next >