< prev index next >

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

Print this page




   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.module;
  27 
  28 import java.io.File;
  29 import java.io.FilePermission;
  30 import java.nio.file.Files;
  31 import java.nio.file.Path;
  32 import java.nio.file.Paths;
  33 import java.security.AccessController;
  34 import java.security.Permission;
  35 import java.security.PrivilegedAction;
  36 import java.util.Collections;
  37 import java.util.HashMap;
  38 import java.util.HashSet;
  39 import java.util.List;
  40 import java.util.Map;
  41 import java.util.Objects;
  42 import java.util.Optional;
  43 import java.util.Set;
  44 
  45 import jdk.internal.module.ModuleBootstrap;

  46 import jdk.internal.module.ModulePath;
  47 import jdk.internal.module.SystemModuleFinder;
  48 import sun.security.action.GetPropertyAction;
  49 
  50 /**
  51  * A finder of modules. A {@code ModuleFinder} is used to find modules during
  52  * <a href="package-summary.html#resolution">resolution</a> or
  53  * <a href="package-summary.html#servicebinding">service binding</a>.
  54  *
  55  * <p> A {@code ModuleFinder} can only find one module with a given name. A
  56  * {@code ModuleFinder} that finds modules in a sequence of directories, for
  57  * example, will locate the first occurrence of a module of a given name and
  58  * will ignore other modules of that name that appear in directories later in
  59  * the sequence. </p>
  60  *
  61  * <p> Example usage: </p>
  62  *
  63  * <pre>{@code
  64  *     Path dir1, dir2, dir3;
  65  *
  66  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
  67  *
  68  *     Optional<ModuleReference> omref = finder.find("jdk.foo");


 129      * Configuration#resolveAndBind resolveAndBind} that need to scan the
 130      * module path to find modules that provide a specific service.
 131      *
 132      * @return The set of all module references that this finder locates
 133      *
 134      * @throws FindException
 135      *         If an error occurs finding all modules
 136      *
 137      * @throws SecurityException
 138      *         If denied by the security manager
 139      */
 140     Set<ModuleReference> findAll();
 141 
 142     /**
 143      * Returns a module finder that locates the <em>system modules</em>. The
 144      * system modules are the modules in the Java run-time image.
 145      * The module finder will always find {@code java.base}.
 146      *
 147      * <p> If there is a security manager set then its {@link
 148      * SecurityManager#checkPermission(Permission) checkPermission} method is
 149      * invoked to check that the caller has been granted {@link FilePermission}
 150      * to recursively read the directory that is the value of the system
 151      * property {@code java.home}. </p>
 152      *
 153      * @return A {@code ModuleFinder} that locates the system modules
 154      *
 155      * @throws SecurityException
 156      *         If denied by the security manager
 157      */
 158     static ModuleFinder ofSystem() {
 159         String home;
 160 
 161         SecurityManager sm = System.getSecurityManager();
 162         if (sm != null) {
 163             PrivilegedAction<String> pa = new GetPropertyAction("java.home");
 164             home = AccessController.doPrivileged(pa);
 165             Permission p = new FilePermission(home + File.separator + "-", "read");
 166             sm.checkPermission(p);
 167         } else {
 168             home = System.getProperty("java.home");

 169         }
 170 






 171         Path modules = Paths.get(home, "lib", "modules");
 172         if (Files.isRegularFile(modules)) {
 173             return SystemModuleFinder.getInstance();
 174         } else {
 175             Path mlib = Paths.get(home, "modules");
 176             if (Files.isDirectory(mlib)) {
 177                 // exploded build may be patched
 178                 return ModulePath.of(ModuleBootstrap.patcher(), mlib);
 179             } else {
 180                 throw new InternalError("Unable to detect the run-time image");
 181             }
 182         }
 183     }
 184 
 185     /**




















 186      * Returns a module finder that locates modules on the file system by
 187      * searching a sequence of directories and/or packaged modules.
 188      *
 189      * Each element in the given array is one of:
 190      * <ol>
 191      *     <li><p> A path to a directory of modules.</p></li>
 192      *     <li><p> A path to the <em>top-level</em> directory of an
 193      *         <em>exploded module</em>. </p></li>
 194      *     <li><p> A path to a <em>packaged module</em>. </p></li>
 195      * </ol>
 196      *
 197      * The module finder locates modules by searching each directory, exploded
 198      * module, or packaged module in array index order. It finds the first
 199      * occurrence of a module with a given name and ignores other modules of
 200      * that name that appear later in the sequence.
 201      *
 202      * <p> If an element is a path to a directory of modules then each entry in
 203      * the directory is a packaged module or the top-level directory of an
 204      * exploded module. It it an error if a directory contains more than one
 205      * module with the same name. If an element is a path to a directory, and
 206      * that directory contains a file named {@code module-info.class}, then the
 207      * directory is treated as an exploded module rather than a directory of
 208      * modules. </p>
 209      *
 210      * <p> The module finder returned by this method supports modules that are
 211      * packaged as JAR files. A JAR file with a {@code module-info.class} in
 212      * the top-level directory of the JAR file (or overridden by a versioned
 213      * entry in a {@link java.util.jar.JarFile#isMultiRelease() multi-release}
 214      * JAR file) is a modular JAR and is an <em>explicit module</em>.
 215      * A JAR file that does not have a {@code module-info.class} in the
 216      * top-level directory is created as an automatic module. The components
 217      * for the automatic module are derived as follows:
 218      *
 219      * <ul>
 220      *
 221      *     <li><p> The module {@link ModuleDescriptor#name() name}, and {@link
 222      *     ModuleDescriptor#version() version} if applicable, is derived from
 223      *     the file name of the JAR file as follows: </p>
 224      *




   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.module;
  27 


  28 import java.nio.file.Files;
  29 import java.nio.file.Path;
  30 import java.nio.file.Paths;
  31 import java.security.AccessController;
  32 import java.security.Permission;
  33 import java.security.PrivilegedAction;
  34 import java.util.Collections;
  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 
  43 import jdk.internal.module.ModuleBootstrap;
  44 import jdk.internal.module.ModulePatcher;
  45 import jdk.internal.module.ModulePath;
  46 import jdk.internal.module.SystemModuleFinder;

  47 
  48 /**
  49  * A finder of modules. A {@code ModuleFinder} is used to find modules during
  50  * <a href="package-summary.html#resolution">resolution</a> or
  51  * <a href="package-summary.html#servicebinding">service binding</a>.
  52  *
  53  * <p> A {@code ModuleFinder} can only find one module with a given name. A
  54  * {@code ModuleFinder} that finds modules in a sequence of directories, for
  55  * example, will locate the first occurrence of a module of a given name and
  56  * will ignore other modules of that name that appear in directories later in
  57  * the sequence. </p>
  58  *
  59  * <p> Example usage: </p>
  60  *
  61  * <pre>{@code
  62  *     Path dir1, dir2, dir3;
  63  *
  64  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
  65  *
  66  *     Optional<ModuleReference> omref = finder.find("jdk.foo");


 127      * Configuration#resolveAndBind resolveAndBind} that need to scan the
 128      * module path to find modules that provide a specific service.
 129      *
 130      * @return The set of all module references that this finder locates
 131      *
 132      * @throws FindException
 133      *         If an error occurs finding all modules
 134      *
 135      * @throws SecurityException
 136      *         If denied by the security manager
 137      */
 138     Set<ModuleReference> findAll();
 139 
 140     /**
 141      * Returns a module finder that locates the <em>system modules</em>. The
 142      * system modules are the modules in the Java run-time image.
 143      * The module finder will always find {@code java.base}.
 144      *
 145      * <p> If there is a security manager set then its {@link
 146      * SecurityManager#checkPermission(Permission) checkPermission} method is
 147      * invoked to check that the caller has been granted
 148      * {@link RuntimePermission RuntimePermission("accessSystemModules")}
 149      * to access the system modules. </p>
 150      *
 151      * @return A {@code ModuleFinder} that locates the system modules
 152      *
 153      * @throws SecurityException
 154      *         If denied by the security manager
 155      */
 156     static ModuleFinder ofSystem() {


 157         SecurityManager sm = System.getSecurityManager();
 158         if (sm != null) {
 159             sm.checkPermission(new RuntimePermission("accessSystemModules"));
 160             PrivilegedAction<ModuleFinder> pa = ModuleFinder::privilegedOfSystem;
 161             return AccessController.doPrivileged(pa);

 162         } else {
 163             return privilegedOfSystem();
 164         }
 165     }
 166 
 167     /**
 168      * Returns a module finder that locates the system modules. This method
 169      * assumes it has permissions to access the runtime image.
 170      */
 171     private static ModuleFinder privilegedOfSystem() {
 172         String home = System.getProperty("java.home");
 173         Path modules = Paths.get(home, "lib", "modules");
 174         if (Files.isRegularFile(modules)) {
 175             return SystemModuleFinder.getInstance();
 176         } else {
 177             Path dir = Paths.get(home, "modules");
 178             if (Files.isDirectory(dir)) {
 179                 return privilegedOf(ModuleBootstrap.patcher(), dir);

 180             } else {
 181                 throw new InternalError("Unable to detect the run-time image");
 182             }
 183         }
 184     }
 185 
 186     /**
 187      * Returns a module finder that locates the system modules in an exploded
 188      * image. The image may be patched.
 189      */
 190     private static ModuleFinder privilegedOf(ModulePatcher patcher, Path dir) {
 191         ModuleFinder finder = ModulePath.of(patcher, dir);
 192         return new ModuleFinder() {
 193             @Override
 194             public Optional<ModuleReference> find(String name) {
 195                 PrivilegedAction<Optional<ModuleReference>> pa = () -> finder.find(name);
 196                 return AccessController.doPrivileged(pa);
 197             }
 198             @Override
 199             public Set<ModuleReference> findAll() {
 200                 PrivilegedAction<Set<ModuleReference>> pa = finder::findAll;
 201                 return AccessController.doPrivileged(pa);
 202             }
 203         };
 204     }
 205 
 206     /**
 207      * Returns a module finder that locates modules on the file system by
 208      * searching a sequence of directories and/or packaged modules.
 209      *
 210      * Each element in the given array is one of:
 211      * <ol>
 212      *     <li><p> A path to a directory of modules.</p></li>
 213      *     <li><p> A path to the <em>top-level</em> directory of an
 214      *         <em>exploded module</em>. </p></li>
 215      *     <li><p> A path to a <em>packaged module</em>. </p></li>
 216      * </ol>
 217      *
 218      * The module finder locates modules by searching each directory, exploded
 219      * module, or packaged module in array index order. It finds the first
 220      * occurrence of a module with a given name and ignores other modules of
 221      * that name that appear later in the sequence.
 222      *
 223      * <p> If an element is a path to a directory of modules then each entry in
 224      * the directory is a packaged module or the top-level directory of an
 225      * exploded module. It is an error if a directory contains more than one
 226      * module with the same name. If an element is a path to a directory, and
 227      * that directory contains a file named {@code module-info.class}, then the
 228      * directory is treated as an exploded module rather than a directory of
 229      * modules. </p>
 230      *
 231      * <p> The module finder returned by this method supports modules that are
 232      * packaged as JAR files. A JAR file with a {@code module-info.class} in
 233      * the top-level directory of the JAR file (or overridden by a versioned
 234      * entry in a {@link java.util.jar.JarFile#isMultiRelease() multi-release}
 235      * JAR file) is a modular JAR and is an <em>explicit module</em>.
 236      * A JAR file that does not have a {@code module-info.class} in the
 237      * top-level directory is created as an automatic module. The components
 238      * for the automatic module are derived as follows:
 239      *
 240      * <ul>
 241      *
 242      *     <li><p> The module {@link ModuleDescriptor#name() name}, and {@link
 243      *     ModuleDescriptor#version() version} if applicable, is derived from
 244      *     the file name of the JAR file as follows: </p>
 245      *


< prev index next >