8200125: Fix some classloader/module typos
Reviewed-by: alanb

   1 /*
   2  * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 import java.lang.module.Configuration;
  29 import java.lang.module.ModuleDescriptor;
  30 import java.lang.module.ResolvedModule;
  31 import java.util.ArrayDeque;
  32 import java.util.ArrayList;
  33 import java.util.Collections;
  34 import java.util.Deque;
  35 import java.util.HashMap;
  36 import java.util.HashSet;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Objects;
  40 import java.util.Optional;
  41 import java.util.Set;
  42 import java.util.concurrent.CopyOnWriteArrayList;
  43 import java.util.function.Function;
  44 import java.util.stream.Collectors;
  45 import java.util.stream.Stream;
  46 
  47 import jdk.internal.loader.ClassLoaderValue;
  48 import jdk.internal.loader.Loader;
  49 import jdk.internal.loader.LoaderPool;
  50 import jdk.internal.module.ServicesCatalog;
  51 import sun.security.util.SecurityConstants;
  52 
  53 
  54 /**
  55  * A layer of modules in the Java virtual machine.
  56  *
  57  * <p> A layer is created from a graph of modules in a {@link Configuration}
  58  * and a function that maps each module to a {@link ClassLoader}.
  59  * Creating a layer informs the Java virtual machine about the classes that
  60  * may be loaded from the modules so that the Java virtual machine knows which
  61  * module that each class is a member of. </p>
  62  *
  63  * <p> Creating a layer creates a {@link Module} object for each {@link
  64  * ResolvedModule} in the configuration. For each resolved module that is
  65  * {@link ResolvedModule#reads() read}, the {@code Module} {@link
  66  * Module#canRead reads} the corresponding run-time {@code Module}, which may
  67  * be in the same layer or a {@link #parents() parent} layer. </p>
  68  *
  69  * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
  70  * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
  71  * provide convenient ways to create a module layer where all modules are
  72  * mapped to a single class loader or where each module is mapped to its own
  73  * class loader. The {@link #defineModules defineModules} method is for more
  74  * advanced cases where modules are mapped to custom class loaders by means of
  75  * a function specified to the method. Each of these methods has an instance
  76  * and static variant. The instance methods create a layer with the receiver
  77  * as the parent layer. The static methods are for more advanced cases where
  78  * there can be more than one parent layer or where a {@link
  79  * ModuleLayer.Controller Controller} is needed to control modules in the layer
  80  * </p>
  81  *
  82  * <p> A Java virtual machine has at least one non-empty layer, the {@link
  83  * #boot() boot} layer, that is created when the Java virtual machine is
  84  * started. The boot layer contains module {@code java.base} and is the only
  85  * layer in the Java virtual machine with a module named "{@code java.base}".
  86  * The modules in the boot layer are mapped to the bootstrap class loader and
  87  * other class loaders that are <a href="ClassLoader.html#builtinLoaders">
  88  * built-in</a> into the Java virtual machine. The boot layer will often be
  89  * the {@link #parents() parent} when creating additional layers. </p>
  90  *
  91  * <p> Each {@code Module} in a layer is created so that it {@link
  92  * Module#isExported(String) exports} and {@link Module#isOpen(String) opens}
  93  * the packages described by its {@link ModuleDescriptor}. Qualified exports
  94  * (where a package is exported to a set of target modules rather than all
  95  * modules) are reified when creating the layer as follows: </p>
  96  * <ul>
  97  *     <li> If module {@code X} exports a package to {@code Y}, and if the
  98  *     runtime {@code Module} {@code X} reads {@code Module} {@code Y}, then
  99  *     the package is exported to {@code Module} {@code Y} (which may be in
 100  *     the same layer as {@code X} or a parent layer). </li>
 101  *
 102  *     <li> If module {@code X} exports a package to {@code Y}, and if the
 103  *     runtime {@code Module} {@code X} does not read {@code Y} then target
 104  *     {@code Y} is located as if by invoking {@link #findModule(String)
 105  *     findModule} to find the module in the layer or its parent layers. If
 106  *     {@code Y} is found then the package is exported to the instance of
 107  *     {@code Y} that was found. If {@code Y} is not found then the qualified
 108  *     export is ignored. </li>
 109  * </ul>
 110  *
 111  * <p> Qualified opens are handled in same way as qualified exports. </p>
 112  *
 113  * <p> As when creating a {@code Configuration},
 114  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive special
 115  * treatment when creating a layer. An automatic module is created in the
 116  * Java virtual machine as a {@code Module} that reads every unnamed {@code
 117  * Module} in the Java virtual machine. </p>
 118  *
 119  * <p> Unless otherwise specified, passing a {@code null} argument to a method
 120  * in this class causes a {@link NullPointerException NullPointerException} to
 121  * be thrown. </p>
 122  *
 123  * <h3> Example usage: </h3>
 124  *
 125  * <p> This example creates a configuration by resolving a module named
 126  * "{@code myapp}" with the configuration for the boot layer as the parent. It
 127  * then creates a new layer with the modules in this configuration. All modules
 128  * are defined to the same class loader. </p>
 129  *
 130  * <pre>{@code
 131  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
 132  *
 133  *     ModuleLayer parent = ModuleLayer.boot();
 134  *
 135  *     Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp"));
 136  *
 137  *     ClassLoader scl = ClassLoader.getSystemClassLoader();
 138  *
 139  *     ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
 140  *
 141  *     Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
 142  * }</pre>
 143  *
 144  * @since 9
 145  * @spec JPMS
 146  * @see Module#getLayer()
 147  */
 148 
 149 public final class ModuleLayer {
 150 
 151     // the empty layer
 152     private static final ModuleLayer EMPTY_LAYER
 153         = new ModuleLayer(Configuration.empty(), List.of(), null);
 154 
 155     // the configuration from which this layer was created
 156     private final Configuration cf;
 157 
 158     // parent layers, empty in the case of the empty layer
 159     private final List<ModuleLayer> parents;
 160 
 161     // maps module name to jlr.Module
 162     private final Map<String, Module> nameToModule;
 163 
 164     /**
 165      * Creates a new module layer from the modules in the given configuration.
 166      */
 167     private ModuleLayer(Configuration cf,
 168                         List<ModuleLayer> parents,
 169                         Function<String, ClassLoader> clf)
 170     {
 171         this.cf = cf;
 172         this.parents = parents; // no need to do defensive copy
 173 
 174         Map<String, Module> map;
 175         if (parents.isEmpty()) {
 176             map = Collections.emptyMap();
 177         } else {
 178             map = Module.defineModules(cf, clf, this);
 179         }
 180         this.nameToModule = map; // no need to do defensive copy
 181     }
 182 
 183     /**
 184      * Controls a module layer. The static methods defined by {@link ModuleLayer}
 185      * to create module layers return a {@code Controller} that can be used to
 186      * control modules in the layer.
 187      *
 188      * <p> Unless otherwise specified, passing a {@code null} argument to a
 189      * method in this class causes a {@link NullPointerException
 190      * NullPointerException} to be thrown. </p>
 191      *
 192      * @apiNote Care should be taken with {@code Controller} objects, they
 193      * should never be shared with untrusted code.
 194      *
 195      * @since 9
 196      * @spec JPMS
 197      */
 198     public static final class Controller {
 199         private final ModuleLayer layer;
 200 
 201         Controller(ModuleLayer layer) {
 202             this.layer = layer;
 203         }
 204 
 205         /**
 206          * Returns the layer that this object controls.
 207          *
 208          * @return the module layer
 209          */
 210         public ModuleLayer layer() {
 211             return layer;
 212         }
 213 
 214         private void ensureInLayer(Module source) {
 215             if (source.getLayer() != layer)
 216                 throw new IllegalArgumentException(source + " not in layer");
 217         }
 218 
 219 
 220         /**
 221          * Updates module {@code source} in the layer to read module
 222          * {@code target}. This method is a no-op if {@code source} already
 223          * reads {@code target}.
 224          *
 225          * @implNote <em>Read edges</em> added by this method are <em>weak</em>
 226          * and do not prevent {@code target} from being GC'ed when {@code source}
 227          * is strongly reachable.
 228          *
 229          * @param  source
 230          *         The source module
 231          * @param  target
 232          *         The target module to read
 233          *
 234          * @return This controller
 235          *
 236          * @throws IllegalArgumentException
 237          *         If {@code source} is not in the module layer
 238          *
 239          * @see Module#addReads
 240          */
 241         public Controller addReads(Module source, Module target) {
 242             ensureInLayer(source);
 243             source.implAddReads(target);
 244             return this;
 245         }
 246 
 247         /**
 248          * Updates module {@code source} in the layer to export a package to
 249          * module {@code target}. This method is a no-op if {@code source}
 250          * already exports the package to at least {@code target}.
 251          *
 252          * @param  source
 253          *         The source module
 254          * @param  pn
 255          *         The package name
 256          * @param  target
 257          *         The target module
 258          *
 259          * @return This controller
 260          *
 261          * @throws IllegalArgumentException
 262          *         If {@code source} is not in the module layer or the package
 263          *         is not in the source module
 264          *
 265          * @see Module#addExports
 266          */
 267         public Controller addExports(Module source, String pn, Module target) {
 268             ensureInLayer(source);
 269             source.implAddExports(pn, target);
 270             return this;
 271         }
 272 
 273         /**
 274          * Updates module {@code source} in the layer to open a package to
 275          * module {@code target}. This method is a no-op if {@code source}
 276          * already opens the package to at least {@code target}.
 277          *
 278          * @param  source
 279          *         The source module
 280          * @param  pn
 281          *         The package name
 282          * @param  target
 283          *         The target module
 284          *
 285          * @return This controller
 286          *
 287          * @throws IllegalArgumentException
 288          *         If {@code source} is not in the module layer or the package
 289          *         is not in the source module
 290          *
 291          * @see Module#addOpens
 292          */
 293         public Controller addOpens(Module source, String pn, Module target) {
 294             ensureInLayer(source);
 295             source.implAddOpens(pn, target);
 296             return this;
 297         }
 298     }
 299 
 300 
 301     /**
 302      * Creates a new module layer, with this layer as its parent, by defining the
 303      * modules in the given {@code Configuration} to the Java virtual machine.
 304      * This method creates one class loader and defines all modules to that
 305      * class loader. The {@link ClassLoader#getParent() parent} of each class
 306      * loader is the given parent class loader. This method works exactly as
 307      * specified by the static {@link
 308      * #defineModulesWithOneLoader(Configuration,List,ClassLoader)
 309      * defineModulesWithOneLoader} method when invoked with this layer as the
 310      * parent. In other words, if this layer is {@code thisLayer} then this
 311      * method is equivalent to invoking:
 312      * <pre> {@code
 313      *     ModuleLayer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer();
 314      * }</pre>
 315      *
 316      * @param  cf
 317      *         The configuration for the layer
 318      * @param  parentLoader
 319      *         The parent class loader for the class loader created by this
 320      *         method; may be {@code null} for the bootstrap class loader
 321      *
 322      * @return The newly created layer
 323      *
 324      * @throws IllegalArgumentException
 325      *         If the given configuration has more than one parent or the parent
 326      *         of the configuration is not the configuration for this layer
 327      * @throws LayerInstantiationException
 328      *         If the layer cannot be created for any of the reasons specified
 329      *         by the static {@code defineModulesWithOneLoader} method
 330      * @throws SecurityException
 331      *         If {@code RuntimePermission("createClassLoader")} or
 332      *         {@code RuntimePermission("getClassLoader")} is denied by
 333      *         the security manager
 334      *
 335      * @see #findLoader
 336      */
 337     public ModuleLayer defineModulesWithOneLoader(Configuration cf,
 338                                                   ClassLoader parentLoader) {
 339         return defineModulesWithOneLoader(cf, List.of(this), parentLoader).layer();
 340     }
 341 
 342 
 343     /**
 344      * Creates a new module layer, with this layer as its parent, by defining the
 345      * modules in the given {@code Configuration} to the Java virtual machine.
 346      * Each module is defined to its own {@link ClassLoader} created by this
 347      * method. The {@link ClassLoader#getParent() parent} of each class loader
 348      * is the given parent class loader. This method works exactly as specified
 349      * by the static {@link
 350      * #defineModulesWithManyLoaders(Configuration,List,ClassLoader)
 351      * defineModulesWithManyLoaders} method when invoked with this layer as the
 352      * parent. In other words, if this layer is {@code thisLayer} then this
 353      * method is equivalent to invoking:
 354      * <pre> {@code
 355      *     ModuleLayer.defineModulesWithManyLoaders(cf, List.of(thisLayer), parentLoader).layer();
 356      * }</pre>
 357      *
 358      * @param  cf
 359      *         The configuration for the layer
 360      * @param  parentLoader
 361      *         The parent class loader for each of the class loaders created by
 362      *         this method; may be {@code null} for the bootstrap class loader
 363      *
 364      * @return The newly created layer
 365      *
 366      * @throws IllegalArgumentException
 367      *         If the given configuration has more than one parent or the parent
 368      *         of the configuration is not the configuration for this layer
 369      * @throws LayerInstantiationException
 370      *         If the layer cannot be created for any of the reasons specified
 371      *         by the static {@code defineModulesWithManyLoaders} method
 372      * @throws SecurityException
 373      *         If {@code RuntimePermission("createClassLoader")} or
 374      *         {@code RuntimePermission("getClassLoader")} is denied by
 375      *         the security manager
 376      *
 377      * @see #findLoader
 378      */
 379     public ModuleLayer defineModulesWithManyLoaders(Configuration cf,
 380                                                     ClassLoader parentLoader) {
 381         return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer();
 382     }
 383 
 384 
 385     /**
 386      * Creates a new module layer, with this layer as its parent, by defining the
 387      * modules in the given {@code Configuration} to the Java virtual machine.
 388      * Each module is mapped, by name, to its class loader by means of the
 389      * given function. This method works exactly as specified by the static
 390      * {@link #defineModules(Configuration,List,Function) defineModules}
 391      * method when invoked with this layer as the parent. In other words, if
 392      * this layer is {@code thisLayer} then this method is equivalent to
 393      * invoking:
 394      * <pre> {@code
 395      *     ModuleLayer.defineModules(cf, List.of(thisLayer), clf).layer();
 396      * }</pre>
 397      *
 398      * @param  cf
 399      *         The configuration for the layer
 400      * @param  clf
 401      *         The function to map a module name to a class loader
 402      *
 403      * @return The newly created layer
 404      *
 405      * @throws IllegalArgumentException
 406      *         If the given configuration has more than one parent or the parent
 407      *         of the configuration is not the configuration for this layer
 408      * @throws LayerInstantiationException
 409      *         If the layer cannot be created for any of the reasons specified
 410      *         by the static {@code defineModules} method
 411      * @throws SecurityException
 412      *         If {@code RuntimePermission("getClassLoader")} is denied by
 413      *         the security manager
 414      */
 415     public ModuleLayer defineModules(Configuration cf,
 416                                      Function<String, ClassLoader> clf) {
 417         return defineModules(cf, List.of(this), clf).layer();
 418     }
 419 
 420     /**
 421      * Creates a new module layer by defining the modules in the given {@code
 422      * Configuration} to the Java virtual machine. This method creates one
 423      * class loader and defines all modules to that class loader.
 424      *
 425      * <p> The class loader created by this method implements <em>direct
 426      * delegation</em> when loading classes from modules. If the {@link
 427      * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
 428      * load a class then it uses the package name of the class to map it to a
 429      * module. This may be a module in this layer and hence defined to the same
 430      * class loader. It may be a package in a module in a parent layer that is
 431      * exported to one or more of the modules in this layer. The class
 432      * loader delegates to the class loader of the module, throwing {@code
 433      * ClassNotFoundException} if not found by that class loader.
 434      * When {@code loadClass} is invoked to load classes that do not map to a
 435      * module then it delegates to the parent class loader. </p>
 436      *
 437      * <p> The class loader created by this method locates resources
 438      * ({@link ClassLoader#getResource(String) getResource}, {@link
 439      * ClassLoader#getResources(String) getResources}, and other resource
 440      * methods) in all modules in the layer before searching the parent class
 441      * loader. </p>
 442      *
 443      * <p> Attempting to create a layer with all modules defined to the same
 444      * class loader can fail for the following reasons:
 445      *
 446      * <ul>
 447      *
 448      *     <li><p> <em>Overlapping packages</em>: Two or more modules in the
 449      *     configuration have the same package. </p></li>
 450      *
 451      *     <li><p> <em>Split delegation</em>: The resulting class loader would
 452      *     need to delegate to more than one class loader in order to load
 453      *     classes in a specific package. </p></li>
 454      *
 455      * </ul>
 456      *
 457      * <p> In addition, a layer cannot be created if the configuration contains
 458      * a module named "{@code java.base}", or a module contains a package named
 459      * "{@code java}" or a package with a name starting with "{@code java.}". </p>
 460      *
 461      * <p> If there is a security manager then the class loader created by
 462      * this method will load classes and resources with privileges that are
 463      * restricted by the calling context of this method. </p>
 464      *
 465      * @param  cf
 466      *         The configuration for the layer
 467      * @param  parentLayers
 468      *         The list of parent layers in search order
 469      * @param  parentLoader
 470      *         The parent class loader for the class loader created by this
 471      *         method; may be {@code null} for the bootstrap class loader
 472      *
 473      * @return A controller that controls the newly created layer
 474      *
 475      * @throws IllegalArgumentException
 476      *         If the parent(s) of the given configuration do not match the
 477      *         configuration of the parent layers, including order
 478      * @throws LayerInstantiationException
 479      *         If all modules cannot be defined to the same class loader for any
 480      *         of the reasons listed above
 481      * @throws SecurityException
 482      *         If {@code RuntimePermission("createClassLoader")} or
 483      *         {@code RuntimePermission("getClassLoader")} is denied by
 484      *         the security manager
 485      *
 486      * @see #findLoader
 487      */
 488     public static Controller defineModulesWithOneLoader(Configuration cf,
 489                                                         List<ModuleLayer> parentLayers,
 490                                                         ClassLoader parentLoader)
 491     {
 492         List<ModuleLayer> parents = new ArrayList<>(parentLayers);
 493         checkConfiguration(cf, parents);
 494 
 495         checkCreateClassLoaderPermission();
 496         checkGetClassLoaderPermission();
 497 
 498         try {
 499             Loader loader = new Loader(cf.modules(), parentLoader);
 500             loader.initRemotePackageMap(cf, parents);
 501             ModuleLayer layer = new ModuleLayer(cf, parents, mn -> loader);
 502             return new Controller(layer);
 503         } catch (IllegalArgumentException | IllegalStateException e) {
 504             throw new LayerInstantiationException(e.getMessage());
 505         }
 506     }
 507 
 508     /**
 509      * Creates a new module layer by defining the modules in the given {@code
 510      * Configuration} to the Java virtual machine. Each module is defined to
 511      * its own {@link ClassLoader} created by this method. The {@link
 512      * ClassLoader#getParent() parent} of each class loader is the given parent
 513      * class loader.
 514      *
 515      * <p> The class loaders created by this method implement <em>direct
 516      * delegation</em> when loading classes from modules. If the {@link
 517      * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
 518      * load a class then it uses the package name of the class to map it to a
 519      * module. The package may be in the module defined to the class loader.
 520      * The package may be exported by another module in this layer to the
 521      * module defined to the class loader. It may be in a package exported by a
 522      * module in a parent layer. The class loader delegates to the class loader
 523      * of the module, throwing {@code ClassNotFoundException} if not found by
 524      * that class loader. When {@code loadClass} is invoked to load a class
 525      * that does not map to a module then it delegates to the parent class
 526      * loader. </p>
 527      *
 528      * <p> The class loaders created by this method locate resources
 529      * ({@link ClassLoader#getResource(String) getResource}, {@link
 530      * ClassLoader#getResources(String) getResources}, and other resource
 531      * methods) in the module defined to the class loader before searching
 532      * the parent class loader. </p>
 533      *
 534      * <p> If there is a security manager then the class loaders created by
 535      * this method will load classes and resources with privileges that are
 536      * restricted by the calling context of this method. </p>
 537      *
 538      * @param  cf
 539      *         The configuration for the layer
 540      * @param  parentLayers
 541      *         The list of parent layers in search order
 542      * @param  parentLoader
 543      *         The parent class loader for each of the class loaders created by
 544      *         this method; may be {@code null} for the bootstrap class loader
 545      *
 546      * @return A controller that controls the newly created layer
 547      *
 548      * @throws IllegalArgumentException
 549      *         If the parent(s) of the given configuration do not match the
 550      *         configuration of the parent layers, including order
 551      * @throws LayerInstantiationException
 552      *         If the layer cannot be created because the configuration contains
 553      *         a module named "{@code java.base}" or a module contains a package
 554      *         named "{@code java}" or a package with a name starting with
 555      *         "{@code java.}"
 556      *
 557      * @throws SecurityException
 558      *         If {@code RuntimePermission("createClassLoader")} or
 559      *         {@code RuntimePermission("getClassLoader")} is denied by
 560      *         the security manager
 561      *
 562      * @see #findLoader
 563      */
 564     public static Controller defineModulesWithManyLoaders(Configuration cf,
 565                                                           List<ModuleLayer> parentLayers,
 566                                                           ClassLoader parentLoader)
 567     {
 568         List<ModuleLayer> parents = new ArrayList<>(parentLayers);
 569         checkConfiguration(cf, parents);
 570 
 571         checkCreateClassLoaderPermission();
 572         checkGetClassLoaderPermission();
 573 
 574         LoaderPool pool = new LoaderPool(cf, parents, parentLoader);
 575         try {
 576             ModuleLayer layer = new ModuleLayer(cf, parents, pool::loaderFor);
 577             return new Controller(layer);
 578         } catch (IllegalArgumentException | IllegalStateException e) {
 579             throw new LayerInstantiationException(e.getMessage());
 580         }
 581     }
 582 
 583     /**
 584      * Creates a new module layer by defining the modules in the given {@code
 585      * Configuration} to the Java virtual machine. The given function maps each
 586      * module in the configuration, by name, to a class loader. Creating the
 587      * layer informs the Java virtual machine about the classes that may be
 588      * loaded so that the Java virtual machine knows which module that each
 589      * class is a member of.
 590      *
 591      * <p> The class loader delegation implemented by the class loaders must
 592      * respect module readability. The class loaders should be
 593      * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to
 594      * avoid deadlocks during class loading. In addition, the entity creating
 595      * a new layer with this method should arrange that the class loaders be
 596      * ready to load from these modules before there are any attempts to load
 597      * classes or resources. </p>
 598      *
 599      * <p> Creating a layer can fail for the following reasons: </p>
 600      *
 601      * <ul>
 602      *
 603      *     <li><p> Two or more modules with the same package are mapped to the
 604      *     same class loader. </p></li>
 605      *
 606      *     <li><p> A module is mapped to a class loader that already has a
 607      *     module of the same name defined to it. </p></li>
 608      *
 609      *     <li><p> A module is mapped to a class loader that has already
 610      *     defined types in any of the packages in the module. </p></li>
 611      *
 612      * </ul>
 613      *
 614      * <p> In addition, a layer cannot be created if the configuration contains
 615      * a module named "{@code java.base}", a configuration contains a module
 616      * with a package named "{@code java}" or a package name starting with
 617      * "{@code java.}", or the function to map a module name to a class loader
 618      * returns {@code null} or the {@linkplain ClassLoader#getPlatformClassLoader()
 619      * platform class loader}. </p>
 620      *
 621      * <p> If the function to map a module name to class loader throws an error
 622      * or runtime exception then it is propagated to the caller of this method.
 623      * </p>
 624      *
 625      * @apiNote It is implementation specific as to whether creating a layer
 626      * with this method is an atomic operation or not. Consequentially it is
 627      * possible for this method to fail with some modules, but not all, defined
 628      * to the Java virtual machine.
 629      *
 630      * @param  cf
 631      *         The configuration for the layer
 632      * @param  parentLayers
 633      *         The list of parent layers in search order
 634      * @param  clf
 635      *         The function to map a module name to a class loader
 636      *
 637      * @return A controller that controls the newly created layer
 638      *
 639      * @throws IllegalArgumentException
 640      *         If the parent(s) of the given configuration do not match the
 641      *         configuration of the parent layers, including order
 642      * @throws LayerInstantiationException
 643      *         If creating the layer fails for any of the reasons listed above
 644      * @throws SecurityException
 645      *         If {@code RuntimePermission("getClassLoader")} is denied by
 646      *         the security manager
 647      */
 648     public static Controller defineModules(Configuration cf,
 649                                            List<ModuleLayer> parentLayers,
 650                                            Function<String, ClassLoader> clf)
 651     {
 652         List<ModuleLayer> parents = new ArrayList<>(parentLayers);
 653         checkConfiguration(cf, parents);
 654         Objects.requireNonNull(clf);
 655 
 656         checkGetClassLoaderPermission();
 657 
 658         // The boot layer is checked during module system initialization
 659         if (boot() != null) {
 660             checkForDuplicatePkgs(cf, clf);
 661         }
 662 
 663         try {
 664             ModuleLayer layer = new ModuleLayer(cf, parents, clf);
 665             return new Controller(layer);
 666         } catch (IllegalArgumentException | IllegalStateException e) {
 667             throw new LayerInstantiationException(e.getMessage());
 668         }
 669     }
 670 
 671 
 672     /**
 673      * Checks that the parent configurations match the configuration of
 674      * the parent layers.
 675      */
 676     private static void checkConfiguration(Configuration cf,
 677                                            List<ModuleLayer> parentLayers)
 678     {
 679         Objects.requireNonNull(cf);
 680 
 681         List<Configuration> parentConfigurations = cf.parents();
 682         if (parentLayers.size() != parentConfigurations.size())
 683             throw new IllegalArgumentException("wrong number of parents");
 684 
 685         int index = 0;
 686         for (ModuleLayer parent : parentLayers) {
 687             if (parent.configuration() != parentConfigurations.get(index)) {
 688                 throw new IllegalArgumentException(
 689                         "Parent of configuration != configuration of this Layer");
 690             }
 691             index++;
 692         }
 693     }
 694 
 695     private static void checkCreateClassLoaderPermission() {
 696         SecurityManager sm = System.getSecurityManager();
 697         if (sm != null)
 698             sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
 699     }
 700 
 701     private static void checkGetClassLoaderPermission() {
 702         SecurityManager sm = System.getSecurityManager();
 703         if (sm != null)
 704             sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 705     }
 706 
 707     /**
 708      * Checks a configuration and the module-to-loader mapping to ensure that
 709      * no two modules mapped to the same class loader have the same package.
 710      * It also checks that no two automatic modules have the same package.
 711      *
 712      * @throws LayerInstantiationException
 713      */
 714     private static void checkForDuplicatePkgs(Configuration cf,
 715                                               Function<String, ClassLoader> clf)
 716     {
 717         // HashMap allows null keys
 718         Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>();
 719         for (ResolvedModule resolvedModule : cf.modules()) {
 720             ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
 721             ClassLoader loader = clf.apply(descriptor.name());
 722 
 723             Set<String> loaderPackages
 724                 = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>());
 725 
 726             for (String pkg : descriptor.packages()) {
 727                 boolean added = loaderPackages.add(pkg);
 728                 if (!added) {
 729                     throw fail("More than one module with package %s mapped" +
 730                                " to the same class loader", pkg);
 731                 }
 732             }
 733         }
 734     }
 735 
 736     /**
 737      * Creates a LayerInstantiationException with the a message formatted from
 738      * the given format string and arguments.
 739      */
 740     private static LayerInstantiationException fail(String fmt, Object ... args) {
 741         String msg = String.format(fmt, args);
 742         return new LayerInstantiationException(msg);
 743     }
 744 
 745 
 746     /**
 747      * Returns the configuration for this layer.
 748      *
 749      * @return The configuration for this layer
 750      */
 751     public Configuration configuration() {
 752         return cf;
 753     }
 754 
 755 
 756     /**
 757      * Returns the list of this layer's parents unless this is the
 758      * {@linkplain #empty empty layer}, which has no parents and so an
 759      * empty list is returned.
 760      *
 761      * @return The list of this layer's parents
 762      */
 763     public List<ModuleLayer> parents() {
 764         return parents;
 765     }
 766 
 767 
 768     /**
 769      * Returns an ordered stream of layers. The first element is this layer,
 770      * the remaining elements are the parent layers in DFS order.
 771      *
 772      * @implNote For now, the assumption is that the number of elements will
 773      * be very low and so this method does not use a specialized spliterator.
 774      */
 775     Stream<ModuleLayer> layers() {
 776         List<ModuleLayer> allLayers = this.allLayers;
 777         if (allLayers != null)
 778             return allLayers.stream();
 779 
 780         allLayers = new ArrayList<>();
 781         Set<ModuleLayer> visited = new HashSet<>();
 782         Deque<ModuleLayer> stack = new ArrayDeque<>();
 783         visited.add(this);
 784         stack.push(this);
 785 
 786         while (!stack.isEmpty()) {
 787             ModuleLayer layer = stack.pop();
 788             allLayers.add(layer);
 789 
 790             // push in reverse order
 791             for (int i = layer.parents.size() - 1; i >= 0; i--) {
 792                 ModuleLayer parent = layer.parents.get(i);
 793                 if (!visited.contains(parent)) {
 794                     visited.add(parent);
 795                     stack.push(parent);
 796                 }
 797             }
 798         }
 799 
 800         this.allLayers = allLayers = Collections.unmodifiableList(allLayers);
 801         return allLayers.stream();
 802     }
 803 
 804     private volatile List<ModuleLayer> allLayers;
 805 
 806     /**
 807      * Returns the set of the modules in this layer.
 808      *
 809      * @return A possibly-empty unmodifiable set of the modules in this layer
 810      */
 811     public Set<Module> modules() {
 812         Set<Module> modules = this.modules;
 813         if (modules == null) {
 814             this.modules = modules =
 815                 Collections.unmodifiableSet(new HashSet<>(nameToModule.values()));
 816         }
 817         return modules;
 818     }
 819 
 820     private volatile Set<Module> modules;
 821 
 822 
 823     /**
 824      * Returns the module with the given name in this layer, or if not in this
 825      * layer, the {@linkplain #parents() parent} layers. Finding a module in
 826      * parent layers is equivalent to invoking {@code findModule} on each
 827      * parent, in search order, until the module is found or all parents have
 828      * been searched. In a <em>tree of layers</em>  then this is equivalent to
 829      * a depth-first search.
 830      *
 831      * @param  name
 832      *         The name of the module to find
 833      *
 834      * @return The module with the given name or an empty {@code Optional}
 835      *         if there isn't a module with this name in this layer or any
 836      *         parent layer
 837      */
 838     public Optional<Module> findModule(String name) {
 839         Objects.requireNonNull(name);
 840         if (this == EMPTY_LAYER)
 841             return Optional.empty();
 842         Module m = nameToModule.get(name);
 843         if (m != null)
 844             return Optional.of(m);
 845 
 846         return layers()
 847                 .skip(1)  // skip this layer
 848                 .map(l -> l.nameToModule.get(name))
 849                 .filter(Objects::nonNull)
 850                 .findAny();
 851     }
 852 
 853 
 854     /**
 855      * Returns the {@code ClassLoader} for the module with the given name. If
 856      * a module of the given name is not in this layer then the {@link #parents()
 857      * parent} layers are searched in the manner specified by {@link
 858      * #findModule(String) findModule}.
 859      *
 860      * <p> If there is a security manager then its {@code checkPermission}
 861      * method is called with a {@code RuntimePermission("getClassLoader")}
 862      * permission to check that the caller is allowed to get access to the
 863      * class loader. </p>
 864      *
 865      * @apiNote This method does not return an {@code Optional<ClassLoader>}
 866      * because `null` must be used to represent the bootstrap class loader.
 867      *
 868      * @param  name
 869      *         The name of the module to find
 870      *
 871      * @return The ClassLoader that the module is defined to
 872      *
 873      * @throws IllegalArgumentException if a module of the given name is not
 874      *         defined in this layer or any parent of this layer
 875      *
 876      * @throws SecurityException if denied by the security manager
 877      */
 878     public ClassLoader findLoader(String name) {
 879         Optional<Module> om = findModule(name);
 880 
 881         // can't use map(Module::getClassLoader) as class loader can be null
 882         if (om.isPresent()) {
 883             return om.get().getClassLoader();
 884         } else {
 885             throw new IllegalArgumentException("Module " + name
 886                                                + " not known to this layer");
 887         }
 888     }
 889 
 890     /**
 891      * Returns a string describing this module layer.
 892      *
 893      * @return A possibly empty string describing this module layer
 894      */
 895     @Override
 896     public String toString() {
 897         return modules().stream()
 898                 .map(Module::getName)
 899                 .collect(Collectors.joining(", "));
 900     }
 901 
 902     /**
 903      * Returns the <em>empty</em> layer. There are no modules in the empty
 904      * layer. It has no parents.
 905      *
 906      * @return The empty layer
 907      */
 908     public static ModuleLayer empty() {
 909         return EMPTY_LAYER;
 910     }
 911 
 912 
 913     /**
 914      * Returns the boot layer. The boot layer contains at least one module,
 915      * {@code java.base}. Its parent is the {@link #empty() empty} layer.
 916      *
 917      * @apiNote This method returns {@code null} during startup and before
 918      *          the boot layer is fully initialized.
 919      *
 920      * @return The boot layer
 921      */
 922     public static ModuleLayer boot() {
 923         return System.bootLayer;
 924     }
 925 
 926     /**
 927      * Returns the ServicesCatalog for this Layer, creating it if not
 928      * already created.
 929      */
 930     ServicesCatalog getServicesCatalog() {
 931         ServicesCatalog servicesCatalog = this.servicesCatalog;
 932         if (servicesCatalog != null)
 933             return servicesCatalog;
 934 
 935         synchronized (this) {
 936             servicesCatalog = this.servicesCatalog;
 937             if (servicesCatalog == null) {
 938                 servicesCatalog = ServicesCatalog.create();
 939                 nameToModule.values().forEach(servicesCatalog::register);
 940                 this.servicesCatalog = servicesCatalog;
 941             }
 942         }
 943 
 944         return servicesCatalog;
 945     }
 946 
 947     private volatile ServicesCatalog servicesCatalog;
 948 
 949 
 950     /**
 951      * Record that this layer has at least one module defined to the given
 952      * class loader.
 953      */
 954     void bindToLoader(ClassLoader loader) {
 955         // CLV.computeIfAbsent(loader, (cl, clv) -> new CopyOnWriteArrayList<>())
 956         List<ModuleLayer> list = CLV.get(loader);
 957         if (list == null) {
 958             list = new CopyOnWriteArrayList<>();
 959             List<ModuleLayer> previous = CLV.putIfAbsent(loader, list);
 960             if (previous != null) list = previous;
 961         }
 962         list.add(this);
 963     }
 964 
 965     /**
 966      * Returns a stream of the layers that have at least one module defined to
 967      * the given class loader.
 968      */
 969     static Stream<ModuleLayer> layers(ClassLoader loader) {
 970         List<ModuleLayer> list = CLV.get(loader);
 971         if (list != null) {
 972             return list.stream();
 973         } else {
 974             return Stream.empty();
 975         }
 976     }
 977 
 978     // the list of layers with modules defined to a class loader
 979     private static final ClassLoaderValue<List<ModuleLayer>> CLV = new ClassLoaderValue<>();
 980 }
--- EOF ---