30 import java.io.InputStream; |
30 import java.io.InputStream; |
31 import java.io.UncheckedIOException; |
31 import java.io.UncheckedIOException; |
32 import java.net.URI; |
32 import java.net.URI; |
33 import java.net.URLConnection; |
33 import java.net.URLConnection; |
34 import java.nio.ByteBuffer; |
34 import java.nio.ByteBuffer; |
|
35 import java.util.ArrayDeque; |
35 import java.util.Collections; |
36 import java.util.Collections; |
|
37 import java.util.Deque; |
36 import java.util.HashMap; |
38 import java.util.HashMap; |
37 import java.util.HashSet; |
39 import java.util.HashSet; |
|
40 import java.util.Iterator; |
38 import java.util.Map; |
41 import java.util.Map; |
39 import java.util.Objects; |
42 import java.util.Objects; |
40 import java.util.Optional; |
43 import java.util.Optional; |
41 import java.util.Set; |
44 import java.util.Set; |
|
45 import java.util.Spliterator; |
|
46 import java.util.function.Consumer; |
42 import java.util.function.Supplier; |
47 import java.util.function.Supplier; |
|
48 import java.util.stream.Stream; |
|
49 import java.util.stream.StreamSupport; |
43 |
50 |
44 import jdk.internal.jimage.ImageLocation; |
51 import jdk.internal.jimage.ImageLocation; |
45 import jdk.internal.jimage.ImageReader; |
52 import jdk.internal.jimage.ImageReader; |
46 import jdk.internal.jimage.ImageReaderFactory; |
53 import jdk.internal.jimage.ImageReaderFactory; |
47 import jdk.internal.misc.JavaNetUriAccess; |
54 import jdk.internal.misc.JavaNetUriAccess; |
60 * ConcealedPackages attribute. |
67 * ConcealedPackages attribute. |
61 */ |
68 */ |
62 |
69 |
63 class SystemModuleFinder implements ModuleFinder { |
70 class SystemModuleFinder implements ModuleFinder { |
64 |
71 |
|
72 private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess(); |
|
73 |
65 private static final PerfCounter initTime |
74 private static final PerfCounter initTime |
66 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime"); |
75 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime"); |
67 private static final PerfCounter moduleCount |
76 private static final PerfCounter moduleCount |
68 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules"); |
77 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules"); |
69 private static final PerfCounter packageCount |
78 private static final PerfCounter packageCount |
70 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages"); |
79 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages"); |
71 private static final PerfCounter exportsCount |
80 private static final PerfCounter exportsCount |
72 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports"); |
81 = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports"); |
73 // ImageReader used to access all modules in the image |
82 // ImageReader used to access all modules in the image |
74 private static final ImageReader imageReader; |
83 private static final ImageReader imageReader; |
75 |
|
76 private static final JavaNetUriAccess jnua = SharedSecrets.getJavaNetUriAccess(); |
|
77 |
84 |
78 // the set of modules in the run-time image |
85 // the set of modules in the run-time image |
79 private static final Set<ModuleReference> modules; |
86 private static final Set<ModuleReference> modules; |
80 |
87 |
81 // maps module name to module reference |
88 // maps module name to module reference |
168 |
175 |
169 private static ModuleReference toModuleReference(ModuleDescriptor md, |
176 private static ModuleReference toModuleReference(ModuleDescriptor md, |
170 HashSupplier hash) |
177 HashSupplier hash) |
171 { |
178 { |
172 String mn = md.name(); |
179 String mn = md.name(); |
173 |
180 URI uri = JNUA.create("jrt", "/".concat(mn)); |
174 URI uri = jnua.create("jrt", "/".concat(mn)); |
|
175 |
181 |
176 Supplier<ModuleReader> readerSupplier = new Supplier<>() { |
182 Supplier<ModuleReader> readerSupplier = new Supplier<>() { |
177 @Override |
183 @Override |
178 public ModuleReader get() { |
184 public ModuleReader get() { |
179 return new ImageModuleReader(mn, uri); |
185 return new ImageModuleReader(mn, uri); |
330 Objects.requireNonNull(bb); |
336 Objects.requireNonNull(bb); |
331 ImageReader.releaseByteBuffer(bb); |
337 ImageReader.releaseByteBuffer(bb); |
332 } |
338 } |
333 |
339 |
334 @Override |
340 @Override |
|
341 public Stream<String> list() throws IOException { |
|
342 if (closed) |
|
343 throw new IOException("ModuleReader is closed"); |
|
344 |
|
345 Spliterator<String> s = new ModuleContentSpliterator(module); |
|
346 return StreamSupport.stream(s, false); |
|
347 } |
|
348 |
|
349 @Override |
335 public void close() { |
350 public void close() { |
336 // nothing else to do |
351 // nothing else to do |
337 closed = true; |
352 closed = true; |
338 } |
353 } |
339 } |
354 } |
340 |
355 |
|
356 /** |
|
357 * A Spliterator for traversing the resources of a module linked into the |
|
358 * run-time image. |
|
359 */ |
|
360 static class ModuleContentSpliterator implements Spliterator<String> { |
|
361 final String moduleRoot; |
|
362 final Deque<ImageReader.Node> stack; |
|
363 Iterator<ImageReader.Node> iterator; |
|
364 |
|
365 ModuleContentSpliterator(String module) throws IOException { |
|
366 moduleRoot = "/modules/" + module; |
|
367 stack = new ArrayDeque<>(); |
|
368 |
|
369 // push the root node to the stack to get started |
|
370 ImageReader.Node dir = imageReader.findNode(moduleRoot); |
|
371 if (dir == null || !dir.isDirectory()) |
|
372 throw new IOException(moduleRoot + " not a directory"); |
|
373 stack.push(dir); |
|
374 iterator = Collections.emptyIterator(); |
|
375 } |
|
376 |
|
377 /** |
|
378 * Returns the name of the next non-directory node or {@code null} if |
|
379 * there are no remaining nodes to visit. |
|
380 */ |
|
381 private String next() throws IOException { |
|
382 for (;;) { |
|
383 while (iterator.hasNext()) { |
|
384 ImageReader.Node node = iterator.next(); |
|
385 String name = node.getName(); |
|
386 if (node.isDirectory()) { |
|
387 // build node |
|
388 ImageReader.Node dir = imageReader.findNode(name); |
|
389 assert dir.isDirectory(); |
|
390 stack.push(dir); |
|
391 } else { |
|
392 // strip /modules/$MODULE/ prefix |
|
393 return name.substring(moduleRoot.length() + 1); |
|
394 } |
|
395 } |
|
396 |
|
397 if (stack.isEmpty()) { |
|
398 return null; |
|
399 } else { |
|
400 ImageReader.Node dir = stack.poll(); |
|
401 assert dir.isDirectory(); |
|
402 iterator = dir.getChildren().iterator(); |
|
403 } |
|
404 } |
|
405 } |
|
406 |
|
407 @Override |
|
408 public boolean tryAdvance(Consumer<? super String> action) { |
|
409 String next; |
|
410 try { |
|
411 next = next(); |
|
412 } catch (IOException ioe) { |
|
413 throw new UncheckedIOException(ioe); |
|
414 } |
|
415 if (next != null) { |
|
416 action.accept(next); |
|
417 return true; |
|
418 } else { |
|
419 return false; |
|
420 } |
|
421 } |
|
422 |
|
423 @Override |
|
424 public Spliterator<String> trySplit() { |
|
425 return null; |
|
426 } |
|
427 |
|
428 @Override |
|
429 public int characteristics() { |
|
430 return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE; |
|
431 } |
|
432 |
|
433 @Override |
|
434 public long estimateSize() { |
|
435 return Long.MAX_VALUE; |
|
436 } |
|
437 } |
341 } |
438 } |