24 */ |
24 */ |
25 |
25 |
26 package com.sun.tools.jdeps; |
26 package com.sun.tools.jdeps; |
27 |
27 |
28 import java.lang.module.ModuleDescriptor; |
28 import java.lang.module.ModuleDescriptor; |
29 import java.lang.module.ModuleDescriptor.Exports; |
|
30 import java.lang.module.ModuleDescriptor.Opens; |
|
31 import java.net.URI; |
29 import java.net.URI; |
32 import java.util.Collections; |
30 import java.util.Collections; |
33 import java.util.HashMap; |
31 import java.util.HashMap; |
34 import java.util.HashSet; |
32 import java.util.HashSet; |
35 import java.util.Map; |
33 import java.util.Map; |
53 } |
51 } |
54 } |
52 } |
55 |
53 |
56 private final ModuleDescriptor descriptor; |
54 private final ModuleDescriptor descriptor; |
57 private final Map<String, Set<String>> exports; |
55 private final Map<String, Set<String>> exports; |
|
56 private final Map<String, Set<String>> opens; |
58 private final boolean isSystem; |
57 private final boolean isSystem; |
59 private final URI location; |
58 private final URI location; |
60 |
59 |
61 protected Module(String name) { |
60 protected Module(String name) { |
62 super(name); |
61 super(name); |
63 this.descriptor = null; |
62 this.descriptor = null; |
64 this.location = null; |
63 this.location = null; |
65 this.exports = Collections.emptyMap(); |
64 this.exports = Collections.emptyMap(); |
|
65 this.opens = Collections.emptyMap(); |
66 this.isSystem = true; |
66 this.isSystem = true; |
67 } |
67 } |
68 |
68 |
69 private Module(String name, |
69 private Module(String name, |
70 URI location, |
70 URI location, |
71 ModuleDescriptor descriptor, |
71 ModuleDescriptor descriptor, |
72 Map<String, Set<String>> exports, |
72 Map<String, Set<String>> exports, |
|
73 Map<String, Set<String>> opens, |
73 boolean isSystem, |
74 boolean isSystem, |
74 ClassFileReader reader) { |
75 ClassFileReader reader) { |
75 super(name, location, reader); |
76 super(name, location, reader); |
76 this.descriptor = descriptor; |
77 this.descriptor = descriptor; |
77 this.location = location; |
78 this.location = location; |
78 this.exports = Collections.unmodifiableMap(exports); |
79 this.exports = Collections.unmodifiableMap(exports); |
|
80 this.opens = Collections.unmodifiableMap(opens); |
79 this.isSystem = isSystem; |
81 this.isSystem = isSystem; |
80 } |
82 } |
81 |
83 |
82 /** |
84 /** |
83 * Returns module name |
85 * Returns module name |
122 |
124 |
123 public Set<String> packages() { |
125 public Set<String> packages() { |
124 return descriptor.packages(); |
126 return descriptor.packages(); |
125 } |
127 } |
126 |
128 |
127 /** |
|
128 * Tests if the package of the given name is exported. |
|
129 */ |
|
130 public boolean isExported(String pn) { |
|
131 return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false; |
|
132 } |
|
133 |
|
134 public boolean isJDKUnsupported() { |
129 public boolean isJDKUnsupported() { |
135 return JDK_UNSUPPORTED.equals(this.name()); |
130 return JDK_UNSUPPORTED.equals(this.name()); |
136 } |
131 } |
137 |
132 |
138 /** |
133 /** |
139 * Converts this module to a strict module with the given dependences |
134 * Converts this module to a normal module with the given dependences |
140 * |
135 * |
141 * @throws IllegalArgumentException if this module is not an automatic module |
136 * @throws IllegalArgumentException if this module is not an automatic module |
142 */ |
137 */ |
143 public Module toStrictModule(Map<String, Boolean> requires) { |
138 public Module toNormalModule(Map<String, Boolean> requires) { |
144 if (!isAutomatic()) { |
139 if (!isAutomatic()) { |
145 throw new IllegalArgumentException(name() + " already a strict module"); |
140 throw new IllegalArgumentException(name() + " not an automatic module"); |
146 } |
141 } |
147 return new StrictModule(this, requires); |
142 return new NormalModule(this, requires); |
148 } |
143 } |
149 |
144 |
150 /** |
145 /** |
151 * Tests if the package of the given name is qualifiedly exported |
146 * Tests if the package of the given name is exported. |
152 * to the target. |
147 */ |
|
148 public boolean isExported(String pn) { |
|
149 return exports.containsKey(pn) && exports.get(pn).isEmpty(); |
|
150 } |
|
151 |
|
152 /** |
|
153 * Tests if the package of the given name is exported to the target |
|
154 * in a qualified fashion. |
153 */ |
155 */ |
154 public boolean isExported(String pn, String target) { |
156 public boolean isExported(String pn, String target) { |
155 return isExported(pn) || exports.containsKey(pn) && exports.get(pn).contains(target); |
157 return isExported(pn) |
|
158 || exports.containsKey(pn) && exports.get(pn).contains(target); |
|
159 } |
|
160 |
|
161 /** |
|
162 * Tests if the package of the given name is open. |
|
163 */ |
|
164 public boolean isOpen(String pn) { |
|
165 return opens.containsKey(pn) && opens.get(pn).isEmpty(); |
|
166 } |
|
167 |
|
168 /** |
|
169 * Tests if the package of the given name is open to the target |
|
170 * in a qualified fashion. |
|
171 */ |
|
172 public boolean isOpen(String pn, String target) { |
|
173 return isOpen(pn) |
|
174 || opens.containsKey(pn) && opens.get(pn).contains(target); |
156 } |
175 } |
157 |
176 |
158 @Override |
177 @Override |
159 public String toString() { |
178 public String toString() { |
160 return name(); |
179 return name(); |
191 if (descriptor.isAutomatic() && isSystem) { |
210 if (descriptor.isAutomatic() && isSystem) { |
192 throw new InternalError("JDK module: " + name + " can't be automatic module"); |
211 throw new InternalError("JDK module: " + name + " can't be automatic module"); |
193 } |
212 } |
194 |
213 |
195 Map<String, Set<String>> exports = new HashMap<>(); |
214 Map<String, Set<String>> exports = new HashMap<>(); |
196 |
215 Map<String, Set<String>> opens = new HashMap<>(); |
197 descriptor.exports().stream() |
216 |
198 .forEach(exp -> exports.computeIfAbsent(exp.source(), _k -> new HashSet<>()) |
217 if (descriptor.isAutomatic()) { |
199 .addAll(exp.targets())); |
218 // ModuleDescriptor::exports and opens returns an empty set |
200 |
219 descriptor.packages().forEach(pn -> exports.put(pn, Collections.emptySet())); |
201 return new Module(name, location, descriptor, exports, isSystem, reader); |
220 descriptor.packages().forEach(pn -> opens.put(pn, Collections.emptySet())); |
|
221 } else { |
|
222 descriptor.exports().stream() |
|
223 .forEach(exp -> exports.computeIfAbsent(exp.source(), _k -> new HashSet<>()) |
|
224 .addAll(exp.targets())); |
|
225 descriptor.opens().stream() |
|
226 .forEach(exp -> opens.computeIfAbsent(exp.source(), _k -> new HashSet<>()) |
|
227 .addAll(exp.targets())); |
|
228 } |
|
229 return new Module(name, location, descriptor, exports, opens, isSystem, reader); |
202 } |
230 } |
203 } |
231 } |
204 |
232 |
205 private static class UnnamedModule extends Module { |
233 private static class UnnamedModule extends Module { |
206 private UnnamedModule() { |
234 private UnnamedModule() { |
207 super("unnamed", null, null, |
235 super("unnamed", null, null, |
208 Collections.emptyMap(), |
236 Collections.emptyMap(), Collections.emptyMap(), |
209 false, null); |
237 false, null); |
210 } |
238 } |
211 |
239 |
212 @Override |
240 @Override |
213 public String name() { |
241 public String name() { |
228 public boolean isExported(String pn) { |
256 public boolean isExported(String pn) { |
229 return true; |
257 return true; |
230 } |
258 } |
231 } |
259 } |
232 |
260 |
233 private static class StrictModule extends Module { |
261 /** |
|
262 * A normal module has a module-info.class |
|
263 */ |
|
264 private static class NormalModule extends Module { |
234 private final ModuleDescriptor md; |
265 private final ModuleDescriptor md; |
235 |
266 |
236 /** |
267 /** |
237 * Converts the given automatic module to a strict module. |
268 * Converts the given automatic module to a normal module. |
238 * |
269 * |
239 * Replace this module's dependences with the given requires and also |
270 * Replace this module's dependences with the given requires and also |
240 * declare service providers, if specified in META-INF/services configuration file |
271 * declare service providers, if specified in META-INF/services configuration file |
241 */ |
272 */ |
242 private StrictModule(Module m, Map<String, Boolean> requires) { |
273 private NormalModule(Module m, Map<String, Boolean> requires) { |
243 super(m.name(), m.location, m.descriptor, m.exports, m.isSystem, m.reader()); |
274 super(m.name(), m.location, m.descriptor, m.exports, m.opens, m.isSystem, m.reader()); |
244 |
275 |
245 ModuleDescriptor.Builder builder = ModuleDescriptor.module(m.name()); |
276 ModuleDescriptor.Builder builder = ModuleDescriptor.newModule(m.name()); |
246 requires.keySet().forEach(mn -> { |
277 requires.keySet().forEach(mn -> { |
247 if (requires.get(mn).equals(Boolean.TRUE)) { |
278 if (requires.get(mn).equals(Boolean.TRUE)) { |
248 builder.requires(Set.of(ModuleDescriptor.Requires.Modifier.TRANSITIVE), mn); |
279 builder.requires(Set.of(ModuleDescriptor.Requires.Modifier.TRANSITIVE), mn); |
249 } else { |
280 } else { |
250 builder.requires(mn); |
281 builder.requires(mn); |
251 } |
282 } |
252 }); |
283 }); |
253 m.descriptor.exports().forEach(e -> builder.exports(e)); |
284 // exports all packages |
254 m.descriptor.opens().forEach(o -> builder.opens(o)); |
285 m.descriptor.packages().forEach(builder::exports); |
255 m.descriptor.uses().forEach(s -> builder.uses(s)); |
286 m.descriptor.uses().forEach(builder::uses); |
256 m.descriptor.provides().forEach(p -> builder.provides(p)); |
287 m.descriptor.provides().forEach(builder::provides); |
257 |
|
258 Set<String> concealed = new HashSet<>(m.descriptor.packages()); |
|
259 m.descriptor.exports().stream().map(Exports::source).forEach(concealed::remove); |
|
260 m.descriptor.opens().stream().map(Opens::source).forEach(concealed::remove); |
|
261 concealed.forEach(builder::contains); |
|
262 |
|
263 this.md = builder.build(); |
288 this.md = builder.build(); |
264 } |
289 } |
265 |
290 |
266 @Override |
291 @Override |
267 public ModuleDescriptor descriptor() { |
292 public ModuleDescriptor descriptor() { |