109 private final ModuleDescriptor descriptor;
110
111
112 /**
113 * Creates a new named Module. The resulting Module will be defined to the
114 * VM but will not read any other modules, will not have any exports setup
115 * and will not be registered in the service catalog.
116 */
117 Module(ModuleLayer layer,
118 ClassLoader loader,
119 ModuleDescriptor descriptor,
120 URI uri)
121 {
122 this.layer = layer;
123 this.name = descriptor.name();
124 this.loader = loader;
125 this.descriptor = descriptor;
126
127 // define module to VM
128
129 boolean isOpen = descriptor.isOpen();
130 Version version = descriptor.version().orElse(null);
131 String vs = Objects.toString(version, null);
132 String loc = Objects.toString(uri, null);
133 String[] packages = descriptor.packages().toArray(new String[0]);
134 defineModule0(this, isOpen, vs, loc, packages);
135 }
136
137
138 /**
139 * Create the unnamed Module for the given ClassLoader.
140 *
141 * @see ClassLoader#getUnnamedModule
142 */
143 Module(ClassLoader loader) {
144 this.layer = null;
145 this.name = null;
146 this.loader = loader;
147 this.descriptor = null;
148 }
149
1025 if (c == '/' || c == ';' || c == '[') {
1026 throw new IllegalArgumentException("Illegal character: " + c);
1027 }
1028 }
1029
1030 // create extraPackages if needed
1031 Map<String, Boolean> extraPackages = this.extraPackages;
1032 if (extraPackages == null) {
1033 synchronized (this) {
1034 extraPackages = this.extraPackages;
1035 if (extraPackages == null)
1036 this.extraPackages = extraPackages = new ConcurrentHashMap<>();
1037 }
1038 }
1039
1040 // update VM first in case it fails. This is a no-op if another thread
1041 // beats us to add the package first
1042 if (syncVM) {
1043 // throws IllegalStateException if defined to another module
1044 addPackage0(this, pn);
1045 if (descriptor.isOpen() || descriptor.isAutomatic()) {
1046 addExportsToAll0(this, pn);
1047 }
1048 }
1049 extraPackages.putIfAbsent(pn, Boolean.TRUE);
1050 }
1051
1052
1053 // -- creating Module objects --
1054
1055 /**
1056 * Defines all module in a configuration to the runtime.
1057 *
1058 * @return a map of module name to runtime {@code Module}
1059 *
1060 * @throws IllegalArgumentException
1061 * If defining any of the modules to the VM fails
1062 */
1063 static Map<String, Module> defineModules(Configuration cf,
1064 Function<String, ClassLoader> clf,
1065 ModuleLayer layer)
1066 {
1067 Map<String, Module> nameToModule = new HashMap<>();
1128 if (m2 != null)
1129 break;
1130 }
1131 assert m2 != null;
1132 if (nameToSource.isEmpty())
1133 nameToSource = new HashMap<>();
1134 nameToSource.put(other.name(), m2);
1135 }
1136 reads.add(m2);
1137
1138 // update VM view
1139 addReads0(m, m2);
1140 }
1141 m.reads = reads;
1142
1143 // automatic modules read all unnamed modules
1144 if (descriptor.isAutomatic()) {
1145 m.implAddReads(ALL_UNNAMED_MODULE, true);
1146 }
1147
1148 // exports and opens
1149 initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
1150 }
1151
1152 // register the modules in the boot layer
1153 if (isBootLayer) {
1154 for (ResolvedModule resolvedModule : cf.modules()) {
1155 ModuleReference mref = resolvedModule.reference();
1156 ModuleDescriptor descriptor = mref.descriptor();
1157 if (!descriptor.provides().isEmpty()) {
1158 String name = descriptor.name();
1159 Module m = nameToModule.get(name);
1160 ClassLoader loader = moduleToLoader.get(name);
1161 ServicesCatalog catalog;
1162 if (loader == null) {
1163 catalog = BootLoader.getServicesCatalog();
1164 } else {
1165 catalog = ServicesCatalog.getServicesCatalog(loader);
1166 }
1167 catalog.register(m);
1168 }
1169 }
1170 }
1190 .filter(l -> l.configuration() == cf)
1191 .findAny()
1192 .map(layer -> {
1193 Optional<Module> om = layer.findModule(dn);
1194 assert om.isPresent() : dn + " not found in layer";
1195 Module m = om.get();
1196 assert m.getLayer() == layer : m + " not in expected layer";
1197 return m;
1198 })
1199 .orElse(null);
1200 }
1201
1202
1203 /**
1204 * Initialize the maps of exported and open packages for module m.
1205 */
1206 private static void initExportsAndOpens(Module m,
1207 Map<String, Module> nameToSource,
1208 Map<String, Module> nameToModule,
1209 List<ModuleLayer> parents) {
1210 // The VM doesn't special case open or automatic modules so need to
1211 // export all packages
1212 ModuleDescriptor descriptor = m.getDescriptor();
1213 if (descriptor.isOpen() || descriptor.isAutomatic()) {
1214 assert descriptor.opens().isEmpty();
1215 for (String source : descriptor.packages()) {
1216 addExportsToAll0(m, source);
1217 }
1218 return;
1219 }
1220
1221 Map<String, Set<Module>> openPackages = new HashMap<>();
1222 Map<String, Set<Module>> exportedPackages = new HashMap<>();
1223
1224 // process the open packages first
1225 for (Opens opens : descriptor.opens()) {
1226 String source = opens.source();
1227
1228 if (opens.isQualified()) {
1229 // qualified opens
1230 Set<Module> targets = new HashSet<>();
1231 for (String target : opens.targets()) {
1232 Module m2 = findModule(target, nameToSource, nameToModule, parents);
1233 if (m2 != null) {
1234 addExports0(m, source, m2);
1235 targets.add(m2);
1236 }
1237 }
1238 if (!targets.isEmpty()) {
1239 openPackages.put(source, targets);
1240 }
1241 } else {
1242 // unqualified opens
1243 addExportsToAll0(m, source);
1244 openPackages.put(source, EVERYONE_SET);
|
109 private final ModuleDescriptor descriptor;
110
111
112 /**
113 * Creates a new named Module. The resulting Module will be defined to the
114 * VM but will not read any other modules, will not have any exports setup
115 * and will not be registered in the service catalog.
116 */
117 Module(ModuleLayer layer,
118 ClassLoader loader,
119 ModuleDescriptor descriptor,
120 URI uri)
121 {
122 this.layer = layer;
123 this.name = descriptor.name();
124 this.loader = loader;
125 this.descriptor = descriptor;
126
127 // define module to VM
128
129 boolean isOpen = descriptor.isOpen() || descriptor.isAutomatic();
130 Version version = descriptor.version().orElse(null);
131 String vs = Objects.toString(version, null);
132 String loc = Objects.toString(uri, null);
133 String[] packages = descriptor.packages().toArray(new String[0]);
134 defineModule0(this, isOpen, vs, loc, packages);
135 }
136
137
138 /**
139 * Create the unnamed Module for the given ClassLoader.
140 *
141 * @see ClassLoader#getUnnamedModule
142 */
143 Module(ClassLoader loader) {
144 this.layer = null;
145 this.name = null;
146 this.loader = loader;
147 this.descriptor = null;
148 }
149
1025 if (c == '/' || c == ';' || c == '[') {
1026 throw new IllegalArgumentException("Illegal character: " + c);
1027 }
1028 }
1029
1030 // create extraPackages if needed
1031 Map<String, Boolean> extraPackages = this.extraPackages;
1032 if (extraPackages == null) {
1033 synchronized (this) {
1034 extraPackages = this.extraPackages;
1035 if (extraPackages == null)
1036 this.extraPackages = extraPackages = new ConcurrentHashMap<>();
1037 }
1038 }
1039
1040 // update VM first in case it fails. This is a no-op if another thread
1041 // beats us to add the package first
1042 if (syncVM) {
1043 // throws IllegalStateException if defined to another module
1044 addPackage0(this, pn);
1045 }
1046 extraPackages.putIfAbsent(pn, Boolean.TRUE);
1047 }
1048
1049
1050 // -- creating Module objects --
1051
1052 /**
1053 * Defines all module in a configuration to the runtime.
1054 *
1055 * @return a map of module name to runtime {@code Module}
1056 *
1057 * @throws IllegalArgumentException
1058 * If defining any of the modules to the VM fails
1059 */
1060 static Map<String, Module> defineModules(Configuration cf,
1061 Function<String, ClassLoader> clf,
1062 ModuleLayer layer)
1063 {
1064 Map<String, Module> nameToModule = new HashMap<>();
1125 if (m2 != null)
1126 break;
1127 }
1128 assert m2 != null;
1129 if (nameToSource.isEmpty())
1130 nameToSource = new HashMap<>();
1131 nameToSource.put(other.name(), m2);
1132 }
1133 reads.add(m2);
1134
1135 // update VM view
1136 addReads0(m, m2);
1137 }
1138 m.reads = reads;
1139
1140 // automatic modules read all unnamed modules
1141 if (descriptor.isAutomatic()) {
1142 m.implAddReads(ALL_UNNAMED_MODULE, true);
1143 }
1144
1145 // export and open packages, skipped for open and automatic
1146 // modules since they are treated as if all packages are open
1147 if (!descriptor.isOpen() && !descriptor.isAutomatic()) {
1148 initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
1149 }
1150 }
1151
1152 // register the modules in the boot layer
1153 if (isBootLayer) {
1154 for (ResolvedModule resolvedModule : cf.modules()) {
1155 ModuleReference mref = resolvedModule.reference();
1156 ModuleDescriptor descriptor = mref.descriptor();
1157 if (!descriptor.provides().isEmpty()) {
1158 String name = descriptor.name();
1159 Module m = nameToModule.get(name);
1160 ClassLoader loader = moduleToLoader.get(name);
1161 ServicesCatalog catalog;
1162 if (loader == null) {
1163 catalog = BootLoader.getServicesCatalog();
1164 } else {
1165 catalog = ServicesCatalog.getServicesCatalog(loader);
1166 }
1167 catalog.register(m);
1168 }
1169 }
1170 }
1190 .filter(l -> l.configuration() == cf)
1191 .findAny()
1192 .map(layer -> {
1193 Optional<Module> om = layer.findModule(dn);
1194 assert om.isPresent() : dn + " not found in layer";
1195 Module m = om.get();
1196 assert m.getLayer() == layer : m + " not in expected layer";
1197 return m;
1198 })
1199 .orElse(null);
1200 }
1201
1202
1203 /**
1204 * Initialize the maps of exported and open packages for module m.
1205 */
1206 private static void initExportsAndOpens(Module m,
1207 Map<String, Module> nameToSource,
1208 Map<String, Module> nameToModule,
1209 List<ModuleLayer> parents) {
1210 Map<String, Set<Module>> openPackages = new HashMap<>();
1211 Map<String, Set<Module>> exportedPackages = new HashMap<>();
1212
1213 // process the open packages first
1214 ModuleDescriptor descriptor = m.getDescriptor();
1215 for (Opens opens : descriptor.opens()) {
1216 String source = opens.source();
1217
1218 if (opens.isQualified()) {
1219 // qualified opens
1220 Set<Module> targets = new HashSet<>();
1221 for (String target : opens.targets()) {
1222 Module m2 = findModule(target, nameToSource, nameToModule, parents);
1223 if (m2 != null) {
1224 addExports0(m, source, m2);
1225 targets.add(m2);
1226 }
1227 }
1228 if (!targets.isEmpty()) {
1229 openPackages.put(source, targets);
1230 }
1231 } else {
1232 // unqualified opens
1233 addExportsToAll0(m, source);
1234 openPackages.put(source, EVERYONE_SET);
|