1 /*
   2  * Copyright (c) 2014, 2016, 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.reflect;
  27 
  28 import java.lang.module.Configuration;
  29 import java.lang.module.ModuleDescriptor;
  30 import java.lang.module.ResolvedModule;
  31 import java.util.Collections;
  32 import java.util.HashMap;
  33 import java.util.HashSet;
  34 import java.util.Map;
  35 import java.util.Objects;
  36 import java.util.Optional;
  37 import java.util.Set;
  38 import java.util.function.Function;
  39 import java.util.stream.Collectors;
  40 
  41 import jdk.internal.loader.Loader;
  42 import jdk.internal.loader.LoaderPool;
  43 import jdk.internal.misc.SharedSecrets;
  44 import sun.security.util.SecurityConstants;
  45 
  46 
  47 /**
  48  * A layer of modules in the Java virtual machine.
  49  *
  50  * <p> A layer is created from a graph of modules that is the {@link
  51  * Configuration} and a function that maps each module to a {@link ClassLoader}.
  52  * Creating a layer informs the Java virtual machine about the classes that
  53  * may be loaded from modules so that the Java virtual machine knows which
  54  * module that each class is a member of. Each layer, except the {@link
  55  * #empty() empty} layer, has a {@link #parent() parent}. </p>
  56  *
  57  * <p> Creating a layer creates a {@link Module} object for each {@link
  58  * ResolvedModule} in the configuration. For each resolved module that is
  59  * {@link ResolvedModule#reads() read}, the {@code Module} {@link
  60  * Module#canRead reads} the corresponding run-time {@code Module}, which may
  61  * be in the same layer or a parent layer. The {@code Module} {@link
  62  * Module#isExported(String) exports} the packages described by its {@link
  63  * ModuleDescriptor}. </p>
  64  *
  65  * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
  66  * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
  67  * provide convenient ways to create a {@code Layer} where all modules are
  68  * mapped to a single class loader or where each module is mapped to its own
  69  * class loader. The {@link #defineModules defineModules} method is for more
  70  * advanced cases where modules are mapped to custom class loaders by means of
  71  * a function specified to the method. </p>
  72  *
  73  * <p> A Java virtual machine has at least one non-empty layer, the {@link
  74  * #boot() boot} layer, that is created when the Java virtual machine is
  75  * started. The <em>system modules</em>, including {@code java.base}, are in
  76  * the boot layer. The modules in the boot layer are mapped to the bootstrap
  77  * class loader and other class loaders that are built-in into the ava virtual
  78  * machine. The boot layer will often be the {@link #parent() parent} when
  79  * creating additional layers. </p>
  80  *
  81  * <p> As when creating a {@code Configuration},
  82  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive
  83  * <a href="../module/Configuration.html#automaticmoduleresolution">special
  84  * treatment</a> when creating a layer. An automatic module is created in the
  85  * Java virtual machine as a {@code Module} that reads every unnamed {@code
  86  * Module} in the Java virtual machine. </p>
  87  *
  88  * <p> Unless otherwise specified, passing a {@code null} argument to a method
  89  * in this class causes a {@link NullPointerException NullPointerException} to
  90  * be thrown. </p>
  91  *
  92  * <h3> Example usage: </h3>
  93  *
  94  * <p> This example creates a configuration by resolving a module named
  95  * "{@code myapp}" with the configuration for the boot layer as the parent. It
  96  * then creates a new layer with the modules in this configuration. All modules
  97  * are defined to the same class loader. </p>
  98  *
  99  * <pre>{@code
 100  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
 101  *
 102  *     Layer parent = Layer.boot();
 103  *
 104  *     Configuration cf = parent.configuration()
 105  *         .resolveRequires(finder, ModuleFinder.empty(), Set.of("myapp"));
 106  *
 107  *     ClassLoader scl = ClassLoader.getSystemClassLoader();
 108  *
 109  *     Layer layer = parent.defineModulesWithOneLoader(cf, scl);
 110  *
 111  *     Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
 112  * }</pre>
 113  *
 114  * @since 9
 115  * @see Module#getLayer()
 116  */
 117 
 118 public final class Layer {
 119 
 120     // the empty Layer
 121     private static final Layer EMPTY_LAYER
 122         = new Layer(Configuration.empty(), null, null);
 123 
 124     // the configuration from which this Layer was created
 125     private final Configuration cf;
 126 
 127     // parent layer, null in the case of the empty layer
 128     private final Layer parent;
 129 
 130     // maps module name to jlr.Module
 131     private final Map<String, Module> nameToModule;
 132 
 133 
 134     /**
 135      * Creates a new Layer from the modules in the given configuration.
 136      */
 137     private Layer(Configuration cf,
 138                   Layer parent,
 139                   Function<String, ClassLoader> clf)
 140     {
 141         this.cf = cf;
 142         this.parent = parent;
 143 
 144         Map<String, Module> map;
 145         if (parent == null) {
 146             map = Collections.emptyMap();
 147         } else {
 148             map = Module.defineModules(cf, clf, this);
 149         }
 150         this.nameToModule = map; // no need to do defensive copy
 151     }
 152 
 153 
 154     /**
 155      * Creates a new layer, with this layer as its parent, by defining the
 156      * modules in the given {@code Configuration} to the Java virtual machine.
 157      * This method creates one class loader and defines all modules to that
 158      * class loader.
 159      *
 160      * <p> The class loader created by this method implements <em>direct
 161      * delegation</em> when loading types from modules. When its {@link
 162      * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
 163      * load a class then it uses the package name of the class to map it to a
 164      * module. This may be a module in this layer and hence defined to the same
 165      * class loader. It may be a package in a module in a parent layer that is
 166      * exported to one or more of the modules in this layer. The class
 167      * loader delegates to the class loader of the module, throwing {@code
 168      * ClassNotFoundException} if not found by that class loader.
 169      *
 170      * When {@code loadClass} is invoked to load classes that do not map to a
 171      * module then it delegates to the parent class loader. </p>
 172      *
 173      * <p> Attempting to create a layer with all modules defined to the same
 174      * class loader can fail for the following reasons:
 175      *
 176      * <ul>
 177      *
 178      *     <li><p> <em>Overlapping packages</em>: Two or more modules in the
 179      *     configuration have the same package (exported or concealed). </p></li>
 180      *
 181      *     <li><p> <em>Split delegation</em>: The resulting class loader would
 182      *     need to delegate to more than one class loader in order to load types
 183      *     in a specific package. </p></li>
 184      *
 185      * </ul>
 186      *
 187      * <p> If there is a security manager then the class loader created by
 188      * this method will load classes and resources with privileges that are
 189      * restricted by the calling context of this method. </p>
 190      *
 191      * @param  cf
 192      *         The configuration for the layer
 193      * @param  parentLoader
 194      *         The parent class loader for the class loader created by this
 195      *         method; may be {@code null} for the bootstrap class loader
 196      *
 197      * @return The newly created layer
 198      *
 199      * @throws IllegalArgumentException
 200      *         If the parent of the given configuration is not the configuration
 201      *         for this layer
 202      * @throws LayerInstantiationException
 203      *         If all modules cannot be defined to the same class loader for any
 204      *         of the reasons listed above
 205      * @throws SecurityException
 206      *         If {@code RuntimePermission("createClassLoader")} or
 207      *         {@code RuntimePermission("getClassLoader")} is denied by
 208      *         the security manager
 209      *
 210      * @see #findLoader
 211      */
 212     public Layer defineModulesWithOneLoader(Configuration cf,
 213                                             ClassLoader parentLoader)
 214     {
 215         checkConfiguration(cf);
 216         checkCreateClassLoaderPermission();
 217         checkGetClassLoaderPermission();
 218 
 219         Loader loader;
 220         try {
 221             loader = new Loader(cf.modules(), parentLoader);
 222             loader.initRemotePackageMap(cf, this);
 223         } catch (IllegalArgumentException e) {
 224             throw new LayerInstantiationException(e.getMessage());
 225         }
 226         return new Layer(cf, this, mn -> loader);
 227     }
 228 
 229 
 230     /**
 231      * Creates a new layer, with this layer as its parent, by defining the
 232      * modules in the given {@code Configuration} to the Java virtual machine.
 233      * Each module is defined to its own {@link ClassLoader} created by this
 234      * method. The {@link ClassLoader#getParent() parent} of each class loader
 235      * is the given parent class loader.
 236      *
 237      * <p> The class loaders created by this method implement <em>direct
 238      * delegation</em> when loading types from modules. When {@link
 239      * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
 240      * load a class then it uses the package name of the class to map it to a
 241      * module. The package may be in the module defined to the class loader.
 242      * The package may be exported by another module in this layer to the
 243      * module defined to the class loader. It may be in a package exported by a
 244      * module in a parent layer. The class loader delegates to the class loader
 245      * of the module, throwing {@code ClassNotFoundException} if not found by
 246      * that class loader.
 247      *
 248      * When {@code loadClass} is invoked to load classes that do not map to a
 249      * module then it delegates to the parent class loader. </p>
 250      *
 251      * <p> If there is a security manager then the class loaders created by
 252      * this method will load classes and resources with privileges that are
 253      * restricted by the calling context of this method. </p>
 254      *
 255      * @param  cf
 256      *         The configuration for the layer
 257      * @param  parentLoader
 258      *         The parent class loader for each of the class loaders created by
 259      *         this method; may be {@code null} for the bootstrap class loader
 260      *
 261      * @return The newly created layer
 262      *
 263      * @throws IllegalArgumentException
 264      *         If the parent of the given configuration is not the configuration
 265      *         for this layer
 266      * @throws SecurityException
 267      *         If {@code RuntimePermission("createClassLoader")} or
 268      *         {@code RuntimePermission("getClassLoader")} is denied by
 269      *         the security manager
 270      *
 271      * @see #findLoader
 272      */
 273     public Layer defineModulesWithManyLoaders(Configuration cf,
 274                                               ClassLoader parentLoader)
 275     {
 276         checkConfiguration(cf);
 277         checkCreateClassLoaderPermission();
 278         checkGetClassLoaderPermission();
 279 
 280         LoaderPool pool = new LoaderPool(cf, this, parentLoader);
 281         return new Layer(cf, this, pool::loaderFor);
 282     }
 283 
 284 
 285     /**
 286      * Creates a new layer, with this layer as its parent, by defining the
 287      * modules in the given {@code Configuration} to the Java virtual machine.
 288      * Each module is mapped, by name, to its class loader by means of the
 289      * given function. The class loader delegation implemented by these class
 290      * loaders must respect module readability. In addition, the caller needs
 291      * to arrange that the class loaders are ready to load from these module
 292      * before there are any attempts to load classes or resources.
 293      *
 294      * <p> Creating a {@code Layer} can fail for the following reasons: </p>
 295      *
 296      * <ul>
 297      *
 298      *     <li><p> Two or more modules with the same package (exported or
 299      *     concealed) are mapped to the same class loader. </p></li>
 300      *
 301      *     <li><p> A module is mapped to a class loader that already has a
 302      *     module of the same name defined to it. </p></li>
 303      *
 304      *     <li><p> A module is mapped to a class loader that has already
 305      *     defined types in any of the packages in the module. </p></li>
 306      *
 307      * </ul>
 308      *
 309      * <p> If the function to map a module name to class loader throws an error
 310      * or runtime exception then it is propagated to the caller of this method.
 311      * </p>
 312      *
 313      * @apiNote It is implementation specific as to whether creating a Layer
 314      * with this method is an atomic operation or not. Consequentially it is
 315      * possible for this method to fail with some modules, but not all, defined
 316      * to Java virtual machine.
 317      *
 318      * @param  cf
 319      *         The configuration for the layer
 320      * @param  clf
 321      *         The function to map a module name to a class loader
 322      *
 323      * @return The newly created layer
 324      *
 325      * @throws IllegalArgumentException
 326      *         If the parent of the given configuration is not the configuration
 327      *         for this layer
 328      * @throws LayerInstantiationException
 329      *         If creating the {@code Layer} fails for any of the reasons
 330      *         listed above
 331      * @throws SecurityException
 332      *         If {@code RuntimePermission("getClassLoader")} is denied by
 333      *         the security manager
 334      */
 335     public Layer defineModules(Configuration cf,
 336                                Function<String, ClassLoader> clf)
 337     {
 338         checkConfiguration(cf);
 339         Objects.requireNonNull(clf);
 340 
 341         checkGetClassLoaderPermission();
 342 
 343         // For now, no two modules in the boot Layer may contain the same
 344         // package so we use a simple check for the boot Layer to keep
 345         // the overhead at startup to a minimum
 346         if (boot() == null) {
 347             checkBootModulesForDuplicatePkgs(cf);
 348         } else {
 349             checkForDuplicatePkgs(cf, clf);
 350         }
 351 
 352         try {
 353             return new Layer(cf, this, clf);
 354         } catch (IllegalArgumentException iae) {
 355             // IAE is thrown by VM when defining the module fails
 356             throw new LayerInstantiationException(iae.getMessage());
 357         }
 358     }
 359 
 360 
 361     private void checkConfiguration(Configuration cf) {
 362         Objects.requireNonNull(cf);
 363 
 364         Optional<Configuration> oparent = cf.parent();
 365         if (!oparent.isPresent() || oparent.getWhenPresent() != this.configuration()) {
 366             throw new IllegalArgumentException(
 367                     "Parent of configuration != configuration of this Layer");
 368         }
 369     }
 370 
 371     private static void checkCreateClassLoaderPermission() {
 372         SecurityManager sm = System.getSecurityManager();
 373         if (sm != null)
 374             sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
 375     }
 376 
 377     private static void checkGetClassLoaderPermission() {
 378         SecurityManager sm = System.getSecurityManager();
 379         if (sm != null)
 380             sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 381     }
 382 
 383     /**
 384      * Checks a configuration for the boot Layer to ensure that no two modules
 385      * have the same package.
 386      *
 387      * @throws LayerInstantiationException
 388      */
 389     private static void checkBootModulesForDuplicatePkgs(Configuration cf) {
 390         Map<String, String> packageToModule = new HashMap<>();
 391         for (ResolvedModule resolvedModule : cf.modules()) {
 392             ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
 393             String name = descriptor.name();
 394             for (String p : descriptor.packages()) {
 395                 String other = packageToModule.putIfAbsent(p, name);
 396                 if (other != null) {
 397                     throw fail("Package " + p + " in both module "
 398                                + name + " and module " + other);
 399                 }
 400             }
 401         }
 402     }
 403 
 404     /**
 405      * Checks a configuration and the module-to-loader mapping to ensure that
 406      * no two modules mapped to the same class loader have the same package.
 407      * It also checks that no two automatic modules have the same package.
 408      *
 409      * @throws LayerInstantiationException
 410      */
 411     private static void checkForDuplicatePkgs(Configuration cf,
 412                                               Function<String, ClassLoader> clf)
 413     {
 414         // HashMap allows null keys
 415         Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>();
 416         for (ResolvedModule resolvedModule : cf.modules()) {
 417             ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
 418             ClassLoader loader = clf.apply(descriptor.name());
 419 
 420             Set<String> loaderPackages
 421                 = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>());
 422 
 423             for (String pkg : descriptor.packages()) {
 424                 boolean added = loaderPackages.add(pkg);
 425                 if (!added) {
 426                     throw fail("More than one module with package %s mapped" +
 427                                " to the same class loader", pkg);
 428                 }
 429             }
 430         }
 431     }
 432 
 433     /**
 434      * Creates a LayerInstantiationException with the a message formatted from
 435      * the given format string and arguments.
 436      */
 437     private static LayerInstantiationException fail(String fmt, Object ... args) {
 438         String msg = String.format(fmt, args);
 439         return new LayerInstantiationException(msg);
 440     }
 441 
 442 
 443     /**
 444      * Returns the configuration for this layer.
 445      *
 446      * @return The configuration for this layer
 447      */
 448     public Configuration configuration() {
 449         return cf;
 450     }
 451 
 452 
 453     /**
 454      * Returns this layer's parent unless this is the {@linkplain #empty empty
 455      * layer}, which has no parent.
 456      *
 457      * @return This layer's parent
 458      */
 459     public Optional<Layer> parent() {
 460         return Optional.ofNullable(parent);
 461     }
 462 
 463 
 464     /**
 465      * Returns a set of the modules in this layer.
 466      *
 467      * @return A possibly-empty unmodifiable set of the modules in this layer
 468      */
 469     public Set<Module> modules() {
 470         return Collections.unmodifiableSet(
 471                 nameToModule.values().stream().collect(Collectors.toSet()));
 472     }
 473 
 474 
 475     /**
 476      * Returns the module with the given name in this layer, or if not in this
 477      * layer, the {@linkplain #parent parent} layer.
 478      *
 479      * @param  name
 480      *         The name of the module to find
 481      *
 482      * @return The module with the given name or an empty {@code Optional}
 483      *         if there isn't a module with this name in this layer or any
 484      *         parent layer
 485      */
 486     public Optional<Module> findModule(String name) {
 487         Module m = nameToModule.get(Objects.requireNonNull(name));
 488         if (m != null)
 489             return Optional.of(m);
 490         return parent().flatMap(l -> l.findModule(name));
 491     }
 492 
 493 
 494     /**
 495      * Returns the {@code ClassLoader} for the module with the given name. If
 496      * a module of the given name is not in this layer then the {@link #parent}
 497      * layer is checked.
 498      *
 499      * <p> If there is a security manager then its {@code checkPermission}
 500      * method is called with a {@code RuntimePermission("getClassLoader")}
 501      * permission to check that the caller is allowed to get access to the
 502      * class loader. </p>
 503      *
 504      * @apiNote This method does not return an {@code Optional<ClassLoader>}
 505      * because `null` must be used to represent the bootstrap class loader.
 506      *
 507      * @param  name
 508      *         The name of the module to find
 509      *
 510      * @return The ClassLoader that the module is defined to
 511      *
 512      * @throws IllegalArgumentException if a module of the given name is not
 513      *         defined in this layer or any parent of this layer
 514      *
 515      * @throws SecurityException if denied by the security manager
 516      */
 517     public ClassLoader findLoader(String name) {
 518         Module m = nameToModule.get(Objects.requireNonNull(name));
 519         if (m != null)
 520             return m.getClassLoader();
 521         Optional<Layer> ol = parent();
 522         if (ol.isPresent())
 523             return ol.getWhenPresent().findLoader(name);
 524         throw new IllegalArgumentException("Module " + name
 525                                            + " not known to this layer");
 526     }
 527 
 528 
 529     /**
 530      * Returns the <em>empty</em> layer. There are no modules in the empty
 531      * layer. It has no parent.
 532      *
 533      * @return The empty layer
 534      */
 535     public static Layer empty() {
 536         return EMPTY_LAYER;
 537     }
 538 
 539 
 540     /**
 541      * Returns the boot layer. The boot layer contains at least one module,
 542      * {@code java.base}. Its parent is the {@link #empty() empty} layer.
 543      *
 544      * @apiNote This method returns {@code null} during startup and before
 545      *          the boot layer is fully initialized.
 546      *
 547      * @return The boot layer
 548      */
 549     public static Layer boot() {
 550         return SharedSecrets.getJavaLangAccess().getBootLayer();
 551     }
 552 }