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.io.IOException;
29 import java.io.InputStream;
30 import java.lang.annotation.Annotation;
31 import java.lang.module.Configuration;
32 import java.lang.module.ModuleReference;
33 import java.lang.module.ModuleDescriptor;
34 import java.lang.module.ModuleDescriptor.Exports;
35 import java.lang.module.ModuleDescriptor.Opens;
36 import java.lang.module.ModuleDescriptor.Version;
37 import java.lang.module.ResolvedModule;
38 import java.net.URI;
39 import java.net.URL;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.Map;
45 import java.util.Objects;
46 import java.util.Optional;
47 import java.util.Set;
48 import java.util.concurrent.ConcurrentHashMap;
49 import java.util.function.Function;
50 import java.util.stream.Stream;
51
52 import jdk.internal.loader.BuiltinClassLoader;
53 import jdk.internal.loader.BootLoader;
54 import jdk.internal.loader.ResourceHelper;
55 import jdk.internal.misc.JavaLangAccess;
56 import jdk.internal.misc.JavaLangReflectModuleAccess;
57 import jdk.internal.misc.SharedSecrets;
58 import jdk.internal.module.ServicesCatalog;
59 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
60 import jdk.internal.org.objectweb.asm.Attribute;
61 import jdk.internal.org.objectweb.asm.ClassReader;
62 import jdk.internal.org.objectweb.asm.ClassVisitor;
63 import jdk.internal.org.objectweb.asm.ClassWriter;
64 import jdk.internal.org.objectweb.asm.Opcodes;
65 import jdk.internal.reflect.CallerSensitive;
66 import jdk.internal.reflect.Reflection;
67 import sun.security.util.SecurityConstants;
68
69 /**
70 * Represents a run-time module, either {@link #isNamed() named} or unnamed.
71 *
72 * <p> Named modules have a {@link #getName() name} and are constructed by the
73 * Java Virtual Machine when a graph of modules is defined to the Java virtual
74 * machine to create a module {@link Layer Layer}. </p>
75 *
76 * <p> An unnamed module does not have a name. There is an unnamed module for
77 * each {@link ClassLoader ClassLoader}, obtained by invoking its {@link
78 * ClassLoader#getUnnamedModule() getUnnamedModule} method. All types that are
352 */
353 void implAddReads(Module other) {
354 implAddReads(other, true);
355 }
356
357 /**
358 * Updates this module to read another module without notifying the VM.
359 *
360 * @apiNote This method is for VM white-box testing.
361 */
362 void implAddReadsNoSync(Module other) {
363 implAddReads(other, false);
364 }
365
366 /**
367 * Makes the given {@code Module} readable to this module.
368 *
369 * If {@code syncVM} is {@code true} then the VM is notified.
370 */
371 private void implAddReads(Module other, boolean syncVM) {
372 Objects.requireNonNull(other);
373
374 // nothing to do
375 if (other == this || !this.isNamed())
376 return;
377
378 // check if we already read this module
379 Set<Module> reads = this.reads;
380 if (reads != null && reads.contains(other))
381 return;
382
383 // update VM first, just in case it fails
384 if (syncVM) {
385 if (other == ALL_UNNAMED_MODULE) {
386 addReads0(this, null);
387 } else {
388 addReads0(this, other);
389 }
390 }
391
392 // add reflective read
393 reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
394 }
395
396
397 // -- exported and open packages --
398
399 // the packages are open to other modules, can be null
400 // if the value contains EVERYONE_MODULE then the package is open to all
401 private volatile Map<String, Set<Module>> openPackages;
402
403 // the packages that are exported, can be null
404 // if the value contains EVERYONE_MODULE then the package is exported to all
405 private volatile Map<String, Set<Module>> exportedPackages;
406
407 // additional exports or opens added at run-time
408 // this module (1st key), other module (2nd key)
409 // (package name, open?) (value)
410 private static final WeakPairMap<Module, Module, Map<String, Boolean>>
411 reflectivelyExports = new WeakPairMap<>();
412
413
414 /**
536 // all packages in open and automatic modules are open
537 if (descriptor.isOpen() || descriptor.isAutomatic())
538 return containsPackage(pn);
539
540 // exported/opened via module declaration/descriptor
541 if (isStaticallyExportedOrOpen(pn, other, open))
542 return true;
543
544 // exported via addExports/addOpens
545 if (isReflectivelyExportedOrOpen(pn, other, open))
546 return true;
547
548 // not exported or open to other
549 return false;
550 }
551
552 /**
553 * Returns {@code true} if this module exports or opens a package to
554 * the given module via its module declaration.
555 */
556 boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
557 // package is open to everyone or <other>
558 Map<String, Set<Module>> openPackages = this.openPackages;
559 if (openPackages != null) {
560 Set<Module> targets = openPackages.get(pn);
561 if (targets != null) {
562 if (targets.contains(EVERYONE_MODULE))
563 return true;
564 if (other != EVERYONE_MODULE && targets.contains(other))
565 return true;
566 }
567 }
568
569 if (!open) {
570 // package is exported to everyone or <other>
571 Map<String, Set<Module>> exportedPackages = this.exportedPackages;
572 if (exportedPackages != null) {
573 Set<Module> targets = exportedPackages.get(pn);
574 if (targets != null) {
575 if (targets.contains(EVERYONE_MODULE))
576 return true;
892
893 // -- packages --
894
895 // Additional packages that are added to the module at run-time.
896 private volatile Map<String, Boolean> extraPackages;
897
898 private boolean containsPackage(String pn) {
899 if (descriptor.packages().contains(pn))
900 return true;
901 Map<String, Boolean> extraPackages = this.extraPackages;
902 if (extraPackages != null && extraPackages.containsKey(pn))
903 return true;
904 return false;
905 }
906
907
908 /**
909 * Returns an array of the package names of the packages in this module.
910 *
911 * <p> For named modules, the returned array contains an element for each
912 * package in the module. It may contain elements corresponding to packages
913 * added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a>
914 * for example, after it was loaded.
915 *
916 * <p> For unnamed modules, this method is the equivalent to invoking the
917 * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
918 * this module's class loader and returning the array of package names. </p>
919 *
920 * <p> A package name appears at most once in the returned array. </p>
921 *
922 * @apiNote This method returns an array rather than a {@code Set} for
923 * consistency with other {@code java.lang.reflect} types.
924 *
925 * @return an array of the package names of the packages in this module
926 */
927 public String[] getPackages() {
928 if (isNamed()) {
929
930 Set<String> packages = descriptor.packages();
931 Map<String, Boolean> extraPackages = this.extraPackages;
932 if (extraPackages == null) {
933 return packages.toArray(new String[0]);
934 } else {
935 return Stream.concat(packages.stream(),
936 extraPackages.keySet().stream())
937 .toArray(String[]::new);
938 }
939
940 } else {
941 // unnamed module
942 Stream<Package> packages;
943 if (loader == null) {
944 packages = BootLoader.packages();
945 } else {
946 packages = SharedSecrets.getJavaLangAccess().packages(loader);
947 }
948 return packages.map(Package::getName).toArray(String[]::new);
949 }
950 }
951
952 /**
953 * Add a package to this module.
954 *
955 * @apiNote This method is for Proxy use.
956 */
957 void addPackage(String pn) {
958 implAddPackage(pn, true);
959 }
960
961 /**
962 * Add a package to this module without notifying the VM.
963 *
964 * @apiNote This method is VM white-box testing.
965 */
966 void implAddPackageNoSync(String pn) {
967 implAddPackage(pn.replace('/', '.'), false);
968 }
969
970 /**
971 * Add a package to this module.
972 *
973 * If {@code syncVM} is {@code true} then the VM is notified. This method is
974 * a no-op if this is an unnamed module or the module already contains the
975 * package.
976 *
977 * @throws IllegalArgumentException if the package name is not legal
978 * @throws IllegalStateException if the package is defined to another module
979 */
980 private void implAddPackage(String pn, boolean syncVM) {
981 // no-op if unnamed module
1063 // java.base is already defined to the VM
1064 m = Object.class.getModule();
1065 } else {
1066 m = new Module(layer, loader, descriptor, uri);
1067 }
1068 nameToModule.put(name, m);
1069 moduleToLoader.put(name, loader);
1070 }
1071
1072 // setup readability and exports
1073 for (ResolvedModule resolvedModule : cf.modules()) {
1074 ModuleReference mref = resolvedModule.reference();
1075 ModuleDescriptor descriptor = mref.descriptor();
1076
1077 String mn = descriptor.name();
1078 Module m = nameToModule.get(mn);
1079 assert m != null;
1080
1081 // reads
1082 Set<Module> reads = new HashSet<>();
1083 for (ResolvedModule other : resolvedModule.reads()) {
1084 Module m2 = null;
1085 if (other.configuration() == cf) {
1086 String dn = other.reference().descriptor().name();
1087 m2 = nameToModule.get(dn);
1088 } else {
1089 for (Layer parent: layer.parents()) {
1090 m2 = findModule(parent, other);
1091 if (m2 != null)
1092 break;
1093 }
1094 }
1095 assert m2 != null;
1096
1097 reads.add(m2);
1098
1099 // update VM view
1100 addReads0(m, m2);
1101 }
1102 m.reads = reads;
1103
1104 // automatic modules read all unnamed modules
1105 if (descriptor.isAutomatic()) {
1106 m.implAddReads(ALL_UNNAMED_MODULE, true);
1107 }
1108
1109 // exports and opens
1110 initExportsAndOpens(descriptor, nameToModule, m);
1111 }
1112
1113 // register the modules in the boot layer
1114 if (isBootLayer) {
1115 for (ResolvedModule resolvedModule : cf.modules()) {
1116 ModuleReference mref = resolvedModule.reference();
1117 ModuleDescriptor descriptor = mref.descriptor();
1118 if (!descriptor.provides().isEmpty()) {
1119 String name = descriptor.name();
1120 Module m = nameToModule.get(name);
1121 ClassLoader loader = moduleToLoader.get(name);
1122 ServicesCatalog catalog;
1123 if (loader == null) {
1124 catalog = BootLoader.getServicesCatalog();
1125 } else {
1126 catalog = ServicesCatalog.getServicesCatalog(loader);
1127 }
1128 catalog.register(m);
1129 }
1130 }
1142 /**
1143 * Find the runtime Module corresponding to the given ResolvedModule
1144 * in the given parent layer (or its parents).
1145 */
1146 private static Module findModule(Layer parent, ResolvedModule resolvedModule) {
1147 Configuration cf = resolvedModule.configuration();
1148 String dn = resolvedModule.name();
1149 return parent.layers()
1150 .filter(l -> l.configuration() == cf)
1151 .findAny()
1152 .map(layer -> {
1153 Optional<Module> om = layer.findModule(dn);
1154 assert om.isPresent() : dn + " not found in layer";
1155 Module m = om.get();
1156 assert m.getLayer() == layer : m + " not in expected layer";
1157 return m;
1158 })
1159 .orElse(null);
1160 }
1161
1162 /**
1163 * Initialize the maps of exported and open packages for module m.
1164 */
1165 private static void initExportsAndOpens(ModuleDescriptor descriptor,
1166 Map<String, Module> nameToModule,
1167 Module m)
1168 {
1169 // The VM doesn't special case open or automatic modules so need to
1170 // export all packages
1171 if (descriptor.isOpen() || descriptor.isAutomatic()) {
1172 assert descriptor.opens().isEmpty();
1173 for (String source : descriptor.packages()) {
1174 addExportsToAll0(m, source);
1175 }
1176 return;
1177 }
1178
1179 Map<String, Set<Module>> openPackages = new HashMap<>();
1180 Map<String, Set<Module>> exportedPackages = new HashMap<>();
1181
1182 // process the open packages first
1183 for (Opens opens : descriptor.opens()) {
1184 String source = opens.source();
1185
1186 if (opens.isQualified()) {
1187 // qualified opens
1188 Set<Module> targets = new HashSet<>();
1189 for (String target : opens.targets()) {
1190 // only open to modules that are in this configuration
1191 Module m2 = nameToModule.get(target);
1192 if (m2 != null) {
1193 addExports0(m, source, m2);
1194 targets.add(m2);
1195 }
1196 }
1197 if (!targets.isEmpty()) {
1198 openPackages.put(source, targets);
1199 }
1200 } else {
1201 // unqualified opens
1202 addExportsToAll0(m, source);
1203 openPackages.put(source, EVERYONE_SET);
1204 }
1205 }
1206
1207 // next the exports, skipping exports when the package is open
1208 for (Exports exports : descriptor.exports()) {
1209 String source = exports.source();
1210
1211 // skip export if package is already open to everyone
1212 Set<Module> openToTargets = openPackages.get(source);
1213 if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE))
1214 continue;
1215
1216 if (exports.isQualified()) {
1217 // qualified exports
1218 Set<Module> targets = new HashSet<>();
1219 for (String target : exports.targets()) {
1220 // only export to modules that are in this configuration
1221 Module m2 = nameToModule.get(target);
1222 if (m2 != null) {
1223 // skip qualified export if already open to m2
1224 if (openToTargets == null || !openToTargets.contains(m2)) {
1225 addExports0(m, source, m2);
1226 targets.add(m2);
1227 }
1228 }
1229 }
1230 if (!targets.isEmpty()) {
1231 exportedPackages.put(source, targets);
1232 }
1233
1234 } else {
1235 // unqualified exports
1236 addExportsToAll0(m, source);
1237 exportedPackages.put(source, EVERYONE_SET);
1238 }
1239 }
1240
1241 if (!openPackages.isEmpty())
1242 m.openPackages = openPackages;
1243 if (!exportedPackages.isEmpty())
1244 m.exportedPackages = exportedPackages;
1245 }
1246
1247
1248 // -- annotations --
1249
1250 /**
1251 * {@inheritDoc}
1252 * This method returns {@code null} when invoked on an unnamed module.
1253 */
1254 @Override
1255 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1256 return moduleInfoClass().getDeclaredAnnotation(annotationClass);
1257 }
1258
1259 /**
1260 * {@inheritDoc}
1261 * This method returns an empty array when invoked on an unnamed module.
1262 */
1263 @Override
1264 public Annotation[] getAnnotations() {
1265 return moduleInfoClass().getAnnotations();
1266 }
1411 * <p> This method returns {@code null} if the resource is not in this
1412 * module, the resource is encapsulated and cannot be located by the caller,
1413 * or access to the resource is denied by the security manager. </p>
1414 *
1415 * @param name
1416 * The resource name
1417 *
1418 * @return An input stream for reading the resource or {@code null}
1419 *
1420 * @throws IOException
1421 * If an I/O error occurs
1422 *
1423 * @see Class#getResourceAsStream(String)
1424 */
1425 @CallerSensitive
1426 public InputStream getResourceAsStream(String name) throws IOException {
1427 if (name.startsWith("/")) {
1428 name = name.substring(1);
1429 }
1430
1431 if (isNamed() && !ResourceHelper.isSimpleResource(name)) {
1432 Module caller = Reflection.getCallerClass().getModule();
1433 if (caller != this && caller != Object.class.getModule()) {
1434 // ignore packages added for proxies via addPackage
1435 Set<String> packages = getDescriptor().packages();
1436 String pn = ResourceHelper.getPackageName(name);
1437 if (packages.contains(pn) && !isOpen(pn, caller)) {
1438 // resource is in package not open to caller
1439 return null;
1440 }
1441 }
1442 }
1443
1444 String mn = this.name;
1445
1446 // special-case built-in class loaders to avoid URL connection
1447 if (loader == null) {
1448 return BootLoader.findResourceAsStream(mn, name);
1449 } else if (loader instanceof BuiltinClassLoader) {
1450 return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
1451 }
1452
1453 // locate resource in module
1454 JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
1455 URL url = jla.findResource(loader, mn, name);
1456 if (url != null) {
1514 new JavaLangReflectModuleAccess() {
1515 @Override
1516 public Module defineUnnamedModule(ClassLoader loader) {
1517 return new Module(loader);
1518 }
1519 @Override
1520 public Module defineModule(ClassLoader loader,
1521 ModuleDescriptor descriptor,
1522 URI uri) {
1523 return new Module(null, loader, descriptor, uri);
1524 }
1525 @Override
1526 public void addReads(Module m1, Module m2) {
1527 m1.implAddReads(m2, true);
1528 }
1529 @Override
1530 public void addReadsAllUnnamed(Module m) {
1531 m.implAddReads(Module.ALL_UNNAMED_MODULE);
1532 }
1533 @Override
1534 public void addExports(Module m, String pn, Module other) {
1535 m.implAddExportsOrOpens(pn, other, false, true);
1536 }
1537 @Override
1538 public void addOpens(Module m, String pn, Module other) {
1539 m.implAddExportsOrOpens(pn, other, true, true);
1540 }
1541 @Override
1542 public void addExportsToAll(Module m, String pn) {
1543 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
1544 }
1545 @Override
1546 public void addOpensToAll(Module m, String pn) {
1547 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true);
1548 }
1549 @Override
1550 public void addExportsToAllUnnamed(Module m, String pn) {
1551 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
1552 }
1553 @Override
1554 public void addOpensToAllUnnamed(Module m, String pn) {
1555 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
1556 }
1557 @Override
1558 public void addUses(Module m, Class<?> service) {
1559 m.implAddUses(service);
1560 }
1561 @Override
1562 public void addPackage(Module m, String pn) {
1563 m.implAddPackage(pn, true);
1564 }
1565 @Override
1566 public ServicesCatalog getServicesCatalog(Layer layer) {
1567 return layer.getServicesCatalog();
1568 }
1569 @Override
1570 public Stream<Layer> layers(Layer layer) {
1571 return layer.layers();
1572 }
1573 @Override
1574 public Stream<Layer> layers(ClassLoader loader) {
1575 return Layer.layers(loader);
1576 }
1577 @Override
1578 public boolean isStaticallyExported(Module module, String pn, Module other) {
1579 return module.isStaticallyExportedOrOpen(pn, other, false);
1580 }
1581 });
1582 }
1583 }
|
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.io.IOException;
29 import java.io.InputStream;
30 import java.lang.annotation.Annotation;
31 import java.lang.module.Configuration;
32 import java.lang.module.ModuleReference;
33 import java.lang.module.ModuleDescriptor;
34 import java.lang.module.ModuleDescriptor.Exports;
35 import java.lang.module.ModuleDescriptor.Opens;
36 import java.lang.module.ModuleDescriptor.Version;
37 import java.lang.module.ResolvedModule;
38 import java.net.URI;
39 import java.net.URL;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Objects;
48 import java.util.Optional;
49 import java.util.Set;
50 import java.util.concurrent.ConcurrentHashMap;
51 import java.util.function.Function;
52 import java.util.stream.Stream;
53
54 import jdk.internal.loader.BuiltinClassLoader;
55 import jdk.internal.loader.BootLoader;
56 import jdk.internal.misc.JavaLangAccess;
57 import jdk.internal.misc.JavaLangReflectModuleAccess;
58 import jdk.internal.misc.SharedSecrets;
59 import jdk.internal.module.ServicesCatalog;
60 import jdk.internal.module.Resources;
61 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
62 import jdk.internal.org.objectweb.asm.Attribute;
63 import jdk.internal.org.objectweb.asm.ClassReader;
64 import jdk.internal.org.objectweb.asm.ClassVisitor;
65 import jdk.internal.org.objectweb.asm.ClassWriter;
66 import jdk.internal.org.objectweb.asm.Opcodes;
67 import jdk.internal.reflect.CallerSensitive;
68 import jdk.internal.reflect.Reflection;
69 import sun.security.util.SecurityConstants;
70
71 /**
72 * Represents a run-time module, either {@link #isNamed() named} or unnamed.
73 *
74 * <p> Named modules have a {@link #getName() name} and are constructed by the
75 * Java Virtual Machine when a graph of modules is defined to the Java virtual
76 * machine to create a module {@link Layer Layer}. </p>
77 *
78 * <p> An unnamed module does not have a name. There is an unnamed module for
79 * each {@link ClassLoader ClassLoader}, obtained by invoking its {@link
80 * ClassLoader#getUnnamedModule() getUnnamedModule} method. All types that are
354 */
355 void implAddReads(Module other) {
356 implAddReads(other, true);
357 }
358
359 /**
360 * Updates this module to read another module without notifying the VM.
361 *
362 * @apiNote This method is for VM white-box testing.
363 */
364 void implAddReadsNoSync(Module other) {
365 implAddReads(other, false);
366 }
367
368 /**
369 * Makes the given {@code Module} readable to this module.
370 *
371 * If {@code syncVM} is {@code true} then the VM is notified.
372 */
373 private void implAddReads(Module other, boolean syncVM) {
374 if (!canRead(other)) {
375 // update VM first, just in case it fails
376 if (syncVM) {
377 if (other == ALL_UNNAMED_MODULE) {
378 addReads0(this, null);
379 } else {
380 addReads0(this, other);
381 }
382 }
383
384 // add reflective read
385 reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
386 }
387 }
388
389
390 // -- exported and open packages --
391
392 // the packages are open to other modules, can be null
393 // if the value contains EVERYONE_MODULE then the package is open to all
394 private volatile Map<String, Set<Module>> openPackages;
395
396 // the packages that are exported, can be null
397 // if the value contains EVERYONE_MODULE then the package is exported to all
398 private volatile Map<String, Set<Module>> exportedPackages;
399
400 // additional exports or opens added at run-time
401 // this module (1st key), other module (2nd key)
402 // (package name, open?) (value)
403 private static final WeakPairMap<Module, Module, Map<String, Boolean>>
404 reflectivelyExports = new WeakPairMap<>();
405
406
407 /**
529 // all packages in open and automatic modules are open
530 if (descriptor.isOpen() || descriptor.isAutomatic())
531 return containsPackage(pn);
532
533 // exported/opened via module declaration/descriptor
534 if (isStaticallyExportedOrOpen(pn, other, open))
535 return true;
536
537 // exported via addExports/addOpens
538 if (isReflectivelyExportedOrOpen(pn, other, open))
539 return true;
540
541 // not exported or open to other
542 return false;
543 }
544
545 /**
546 * Returns {@code true} if this module exports or opens a package to
547 * the given module via its module declaration.
548 */
549 private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
550 // package is open to everyone or <other>
551 Map<String, Set<Module>> openPackages = this.openPackages;
552 if (openPackages != null) {
553 Set<Module> targets = openPackages.get(pn);
554 if (targets != null) {
555 if (targets.contains(EVERYONE_MODULE))
556 return true;
557 if (other != EVERYONE_MODULE && targets.contains(other))
558 return true;
559 }
560 }
561
562 if (!open) {
563 // package is exported to everyone or <other>
564 Map<String, Set<Module>> exportedPackages = this.exportedPackages;
565 if (exportedPackages != null) {
566 Set<Module> targets = exportedPackages.get(pn);
567 if (targets != null) {
568 if (targets.contains(EVERYONE_MODULE))
569 return true;
885
886 // -- packages --
887
888 // Additional packages that are added to the module at run-time.
889 private volatile Map<String, Boolean> extraPackages;
890
891 private boolean containsPackage(String pn) {
892 if (descriptor.packages().contains(pn))
893 return true;
894 Map<String, Boolean> extraPackages = this.extraPackages;
895 if (extraPackages != null && extraPackages.containsKey(pn))
896 return true;
897 return false;
898 }
899
900
901 /**
902 * Returns an array of the package names of the packages in this module.
903 *
904 * <p> For named modules, the returned array contains an element for each
905 * package in the module. </p>
906 *
907 * <p> For unnamed modules, this method is the equivalent to invoking the
908 * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
909 * this module's class loader and returning the array of package names. </p>
910 *
911 * <p> A package name appears at most once in the returned array. </p>
912 *
913 * @apiNote This method returns an array rather than a {@code Set} for
914 * consistency with other {@code java.lang.reflect} types.
915 *
916 * @return an array of the package names of the packages in this module
917 */
918 public String[] getPackages() {
919 if (isNamed()) {
920
921 Set<String> packages = descriptor.packages();
922 Map<String, Boolean> extraPackages = this.extraPackages;
923 if (extraPackages == null) {
924 return packages.toArray(new String[0]);
925 } else {
926 return Stream.concat(packages.stream(),
927 extraPackages.keySet().stream())
928 .toArray(String[]::new);
929 }
930
931 } else {
932 // unnamed module
933 Stream<Package> packages;
934 if (loader == null) {
935 packages = BootLoader.packages();
936 } else {
937 packages = SharedSecrets.getJavaLangAccess().packages(loader);
938 }
939 return packages.map(Package::getName).toArray(String[]::new);
940 }
941 }
942
943 /**
944 * Add a package to this module without notifying the VM.
945 *
946 * @apiNote This method is VM white-box testing.
947 */
948 void implAddPackageNoSync(String pn) {
949 implAddPackage(pn.replace('/', '.'), false);
950 }
951
952 /**
953 * Add a package to this module.
954 *
955 * If {@code syncVM} is {@code true} then the VM is notified. This method is
956 * a no-op if this is an unnamed module or the module already contains the
957 * package.
958 *
959 * @throws IllegalArgumentException if the package name is not legal
960 * @throws IllegalStateException if the package is defined to another module
961 */
962 private void implAddPackage(String pn, boolean syncVM) {
963 // no-op if unnamed module
1045 // java.base is already defined to the VM
1046 m = Object.class.getModule();
1047 } else {
1048 m = new Module(layer, loader, descriptor, uri);
1049 }
1050 nameToModule.put(name, m);
1051 moduleToLoader.put(name, loader);
1052 }
1053
1054 // setup readability and exports
1055 for (ResolvedModule resolvedModule : cf.modules()) {
1056 ModuleReference mref = resolvedModule.reference();
1057 ModuleDescriptor descriptor = mref.descriptor();
1058
1059 String mn = descriptor.name();
1060 Module m = nameToModule.get(mn);
1061 assert m != null;
1062
1063 // reads
1064 Set<Module> reads = new HashSet<>();
1065
1066 // name -> source Module when in parent layer
1067 Map<String, Module> nameToSource = Collections.emptyMap();
1068
1069 for (ResolvedModule other : resolvedModule.reads()) {
1070 Module m2 = null;
1071 if (other.configuration() == cf) {
1072 // this configuration
1073 m2 = nameToModule.get(other.name());
1074 assert m2 != null;
1075 } else {
1076 // parent layer
1077 for (Layer parent: layer.parents()) {
1078 m2 = findModule(parent, other);
1079 if (m2 != null)
1080 break;
1081 }
1082 assert m2 != null;
1083 if (nameToSource.isEmpty())
1084 nameToSource = new HashMap<>();
1085 nameToSource.put(other.name(), m2);
1086 }
1087 reads.add(m2);
1088
1089 // update VM view
1090 addReads0(m, m2);
1091 }
1092 m.reads = reads;
1093
1094 // automatic modules read all unnamed modules
1095 if (descriptor.isAutomatic()) {
1096 m.implAddReads(ALL_UNNAMED_MODULE, true);
1097 }
1098
1099 // exports and opens
1100 initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
1101 }
1102
1103 // register the modules in the boot layer
1104 if (isBootLayer) {
1105 for (ResolvedModule resolvedModule : cf.modules()) {
1106 ModuleReference mref = resolvedModule.reference();
1107 ModuleDescriptor descriptor = mref.descriptor();
1108 if (!descriptor.provides().isEmpty()) {
1109 String name = descriptor.name();
1110 Module m = nameToModule.get(name);
1111 ClassLoader loader = moduleToLoader.get(name);
1112 ServicesCatalog catalog;
1113 if (loader == null) {
1114 catalog = BootLoader.getServicesCatalog();
1115 } else {
1116 catalog = ServicesCatalog.getServicesCatalog(loader);
1117 }
1118 catalog.register(m);
1119 }
1120 }
1132 /**
1133 * Find the runtime Module corresponding to the given ResolvedModule
1134 * in the given parent layer (or its parents).
1135 */
1136 private static Module findModule(Layer parent, ResolvedModule resolvedModule) {
1137 Configuration cf = resolvedModule.configuration();
1138 String dn = resolvedModule.name();
1139 return parent.layers()
1140 .filter(l -> l.configuration() == cf)
1141 .findAny()
1142 .map(layer -> {
1143 Optional<Module> om = layer.findModule(dn);
1144 assert om.isPresent() : dn + " not found in layer";
1145 Module m = om.get();
1146 assert m.getLayer() == layer : m + " not in expected layer";
1147 return m;
1148 })
1149 .orElse(null);
1150 }
1151
1152
1153 /**
1154 * Initialize the maps of exported and open packages for module m.
1155 */
1156 private static void initExportsAndOpens(Module m,
1157 Map<String, Module> nameToSource,
1158 Map<String, Module> nameToModule,
1159 List<Layer> parents) {
1160 // The VM doesn't special case open or automatic modules so need to
1161 // export all packages
1162 ModuleDescriptor descriptor = m.getDescriptor();
1163 if (descriptor.isOpen() || descriptor.isAutomatic()) {
1164 assert descriptor.opens().isEmpty();
1165 for (String source : descriptor.packages()) {
1166 addExportsToAll0(m, source);
1167 }
1168 return;
1169 }
1170
1171 Map<String, Set<Module>> openPackages = new HashMap<>();
1172 Map<String, Set<Module>> exportedPackages = new HashMap<>();
1173
1174 // process the open packages first
1175 for (Opens opens : descriptor.opens()) {
1176 String source = opens.source();
1177
1178 if (opens.isQualified()) {
1179 // qualified opens
1180 Set<Module> targets = new HashSet<>();
1181 for (String target : opens.targets()) {
1182 Module m2 = findModule(target, nameToSource, nameToModule, parents);
1183 if (m2 != null) {
1184 addExports0(m, source, m2);
1185 targets.add(m2);
1186 }
1187 }
1188 if (!targets.isEmpty()) {
1189 openPackages.put(source, targets);
1190 }
1191 } else {
1192 // unqualified opens
1193 addExportsToAll0(m, source);
1194 openPackages.put(source, EVERYONE_SET);
1195 }
1196 }
1197
1198 // next the exports, skipping exports when the package is open
1199 for (Exports exports : descriptor.exports()) {
1200 String source = exports.source();
1201
1202 // skip export if package is already open to everyone
1203 Set<Module> openToTargets = openPackages.get(source);
1204 if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE))
1205 continue;
1206
1207 if (exports.isQualified()) {
1208 // qualified exports
1209 Set<Module> targets = new HashSet<>();
1210 for (String target : exports.targets()) {
1211 Module m2 = findModule(target, nameToSource, nameToModule, parents);
1212 if (m2 != null) {
1213 // skip qualified export if already open to m2
1214 if (openToTargets == null || !openToTargets.contains(m2)) {
1215 addExports0(m, source, m2);
1216 targets.add(m2);
1217 }
1218 }
1219 }
1220 if (!targets.isEmpty()) {
1221 exportedPackages.put(source, targets);
1222 }
1223
1224 } else {
1225 // unqualified exports
1226 addExportsToAll0(m, source);
1227 exportedPackages.put(source, EVERYONE_SET);
1228 }
1229 }
1230
1231 if (!openPackages.isEmpty())
1232 m.openPackages = openPackages;
1233 if (!exportedPackages.isEmpty())
1234 m.exportedPackages = exportedPackages;
1235 }
1236
1237 /**
1238 * Find the runtime Module with the given name. The module name is the
1239 * name of a target module in a qualified exports or opens directive.
1240 *
1241 * @param target The target module to find
1242 * @param nameToSource The modules in parent layers that are read
1243 * @param nameToModule The modules in the layer under construction
1244 * @param parents The parent layers
1245 */
1246 private static Module findModule(String target,
1247 Map<String, Module> nameToSource,
1248 Map<String, Module> nameToModule,
1249 List<Layer> parents) {
1250 Module m = nameToSource.get(target);
1251 if (m == null) {
1252 m = nameToModule.get(target);
1253 if (m == null) {
1254 for (Layer parent : parents) {
1255 m = parent.findModule(target).orElse(null);
1256 if (m != null) break;
1257 }
1258 }
1259 }
1260 return m;
1261 }
1262
1263
1264 // -- annotations --
1265
1266 /**
1267 * {@inheritDoc}
1268 * This method returns {@code null} when invoked on an unnamed module.
1269 */
1270 @Override
1271 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1272 return moduleInfoClass().getDeclaredAnnotation(annotationClass);
1273 }
1274
1275 /**
1276 * {@inheritDoc}
1277 * This method returns an empty array when invoked on an unnamed module.
1278 */
1279 @Override
1280 public Annotation[] getAnnotations() {
1281 return moduleInfoClass().getAnnotations();
1282 }
1427 * <p> This method returns {@code null} if the resource is not in this
1428 * module, the resource is encapsulated and cannot be located by the caller,
1429 * or access to the resource is denied by the security manager. </p>
1430 *
1431 * @param name
1432 * The resource name
1433 *
1434 * @return An input stream for reading the resource or {@code null}
1435 *
1436 * @throws IOException
1437 * If an I/O error occurs
1438 *
1439 * @see Class#getResourceAsStream(String)
1440 */
1441 @CallerSensitive
1442 public InputStream getResourceAsStream(String name) throws IOException {
1443 if (name.startsWith("/")) {
1444 name = name.substring(1);
1445 }
1446
1447 if (isNamed() && Resources.canEncapsulate(name)) {
1448 Module caller = Reflection.getCallerClass().getModule();
1449 if (caller != this && caller != Object.class.getModule()) {
1450 // ignore packages added for proxies via addPackage
1451 Set<String> packages = getDescriptor().packages();
1452 String pn = Resources.toPackageName(name);
1453 if (packages.contains(pn) && !isOpen(pn, caller)) {
1454 // resource is in package not open to caller
1455 return null;
1456 }
1457 }
1458 }
1459
1460 String mn = this.name;
1461
1462 // special-case built-in class loaders to avoid URL connection
1463 if (loader == null) {
1464 return BootLoader.findResourceAsStream(mn, name);
1465 } else if (loader instanceof BuiltinClassLoader) {
1466 return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
1467 }
1468
1469 // locate resource in module
1470 JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
1471 URL url = jla.findResource(loader, mn, name);
1472 if (url != null) {
1530 new JavaLangReflectModuleAccess() {
1531 @Override
1532 public Module defineUnnamedModule(ClassLoader loader) {
1533 return new Module(loader);
1534 }
1535 @Override
1536 public Module defineModule(ClassLoader loader,
1537 ModuleDescriptor descriptor,
1538 URI uri) {
1539 return new Module(null, loader, descriptor, uri);
1540 }
1541 @Override
1542 public void addReads(Module m1, Module m2) {
1543 m1.implAddReads(m2, true);
1544 }
1545 @Override
1546 public void addReadsAllUnnamed(Module m) {
1547 m.implAddReads(Module.ALL_UNNAMED_MODULE);
1548 }
1549 @Override
1550 public void addExports(Module m, String pn) {
1551 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
1552 }
1553 @Override
1554 public void addExports(Module m, String pn, Module other) {
1555 m.implAddExportsOrOpens(pn, other, false, true);
1556 }
1557 @Override
1558 public void addExportsToAllUnnamed(Module m, String pn) {
1559 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
1560 }
1561 @Override
1562 public void addOpens(Module m, String pn) {
1563 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true);
1564 }
1565 @Override
1566 public void addOpens(Module m, String pn, Module other) {
1567 m.implAddExportsOrOpens(pn, other, true, true);
1568 }
1569 @Override
1570 public void addOpensToAllUnnamed(Module m, String pn) {
1571 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
1572 }
1573 @Override
1574 public void addUses(Module m, Class<?> service) {
1575 m.implAddUses(service);
1576 }
1577 @Override
1578 public ServicesCatalog getServicesCatalog(Layer layer) {
1579 return layer.getServicesCatalog();
1580 }
1581 @Override
1582 public Stream<Layer> layers(Layer layer) {
1583 return layer.layers();
1584 }
1585 @Override
1586 public Stream<Layer> layers(ClassLoader loader) {
1587 return Layer.layers(loader);
1588 }
1589 });
1590 }
1591 }
|