--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java Fri Aug 04 23:29:09 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,469 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.module;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleFinder;
-import java.lang.module.ModuleReader;
-import java.lang.module.ModuleReference;
-import java.net.URI;
-import java.net.URLConnection;
-import java.nio.ByteBuffer;
-import java.util.ArrayDeque;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import jdk.internal.jimage.ImageLocation;
-import jdk.internal.jimage.ImageReader;
-import jdk.internal.jimage.ImageReaderFactory;
-import jdk.internal.misc.JavaNetUriAccess;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.module.ModuleHashes.HashSupplier;
-import jdk.internal.perf.PerfCounter;
-
-/**
- * A {@code ModuleFinder} that finds modules that are linked into the
- * run-time image.
- *
- * The modules linked into the run-time image are assumed to have the
- * Packages attribute.
- */
-
-public class SystemModuleFinder implements ModuleFinder {
-
- private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
-
- private static final PerfCounter initTime
- = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime");
- private static final PerfCounter moduleCount
- = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules");
- private static final PerfCounter packageCount
- = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages");
- private static final PerfCounter exportsCount
- = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports");
-
- // singleton finder to find modules in the run-time images
- private static final SystemModuleFinder INSTANCE;
-
- public static SystemModuleFinder getInstance() {
- return INSTANCE;
- }
-
- /**
- * For now, the module references are created eagerly on the assumption
- * that service binding will require all modules to be located.
- */
- static {
- long t0 = System.nanoTime();
-
- INSTANCE = new SystemModuleFinder();
-
- initTime.addElapsedTimeFrom(t0);
- }
-
- /**
- * Holder class for the ImageReader
- */
- private static class SystemImage {
- static final ImageReader READER;
- static {
- long t0 = System.nanoTime();
- READER = ImageReaderFactory.getImageReader();
- initTime.addElapsedTimeFrom(t0);
- }
-
- static ImageReader reader() {
- return READER;
- }
- }
-
- private static boolean isFastPathSupported() {
- return SystemModules.MODULE_NAMES.length > 0;
- }
-
- private static String[] moduleNames() {
- if (isFastPathSupported())
- // module names recorded at link time
- return SystemModules.MODULE_NAMES;
-
- // this happens when java.base is patched with java.base
- // from an exploded image
- return SystemImage.reader().getModuleNames();
- }
-
- // the set of modules in the run-time image
- private final Set<ModuleReference> modules;
-
- // maps module name to module reference
- private final Map<String, ModuleReference> nameToModule;
-
- // module name to hashes
- private final Map<String, byte[]> hashes;
-
- private SystemModuleFinder() {
- String[] names = moduleNames();
- int n = names.length;
- moduleCount.add(n);
-
- // fastpath is enabled by default.
- // It can be disabled for troubleshooting purpose.
- boolean disabled =
- System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
-
- ModuleDescriptor[] descriptors;
- ModuleTarget[] targets;
- ModuleHashes[] recordedHashes;
- ModuleResolution[] moduleResolutions;
-
- // fast loading of ModuleDescriptor of system modules
- if (isFastPathSupported() && !disabled) {
- descriptors = SystemModules.descriptors();
- targets = SystemModules.targets();
- recordedHashes = SystemModules.hashes();
- moduleResolutions = SystemModules.moduleResolutions();
- } else {
- // if fast loading of ModuleDescriptors is disabled
- // fallback to read module-info.class
- descriptors = new ModuleDescriptor[n];
- targets = new ModuleTarget[n];
- recordedHashes = new ModuleHashes[n];
- moduleResolutions = new ModuleResolution[n];
- ImageReader imageReader = SystemImage.reader();
- for (int i = 0; i < names.length; i++) {
- String mn = names[i];
- ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
- ModuleInfo.Attributes attrs =
- ModuleInfo.read(imageReader.getResourceBuffer(loc), null);
- descriptors[i] = attrs.descriptor();
- targets[i] = attrs.target();
- recordedHashes[i] = attrs.recordedHashes();
- moduleResolutions[i] = attrs.moduleResolution();
- }
- }
-
- Map<String, byte[]> hashes = null;
- boolean secondSeen = false;
- // record the hashes to build HashSupplier
- for (ModuleHashes mh : recordedHashes) {
- if (mh != null) {
- // if only one module contain ModuleHashes, use it
- if (hashes == null) {
- hashes = mh.hashes();
- } else {
- if (!secondSeen) {
- hashes = new HashMap<>(hashes);
- secondSeen = true;
- }
- hashes.putAll(mh.hashes());
- }
- }
- }
- this.hashes = (hashes == null) ? Map.of() : hashes;
-
- ModuleReference[] mods = new ModuleReference[n];
-
- @SuppressWarnings(value = {"rawtypes", "unchecked"})
- Entry<String, ModuleReference>[] map
- = (Entry<String, ModuleReference>[])new Entry[n];
-
- for (int i = 0; i < n; i++) {
- ModuleDescriptor md = descriptors[i];
-
- // create the ModuleReference
- ModuleReference mref = toModuleReference(md,
- targets[i],
- recordedHashes[i],
- hashSupplier(names[i]),
- moduleResolutions[i]);
- mods[i] = mref;
- map[i] = Map.entry(names[i], mref);
-
- // counters
- packageCount.add(md.packages().size());
- exportsCount.add(md.exports().size());
- }
-
- modules = Set.of(mods);
- nameToModule = Map.ofEntries(map);
- }
-
- @Override
- public Optional<ModuleReference> find(String name) {
- Objects.requireNonNull(name);
- return Optional.ofNullable(nameToModule.get(name));
- }
-
- @Override
- public Set<ModuleReference> findAll() {
- return modules;
- }
-
- private ModuleReference toModuleReference(ModuleDescriptor md,
- ModuleTarget target,
- ModuleHashes recordedHashes,
- HashSupplier hasher,
- ModuleResolution mres) {
- String mn = md.name();
- URI uri = JNUA.create("jrt", "/".concat(mn));
-
- Supplier<ModuleReader> readerSupplier = new Supplier<>() {
- @Override
- public ModuleReader get() {
- return new ImageModuleReader(mn, uri);
- }
- };
-
- ModuleReference mref = new ModuleReferenceImpl(md,
- uri,
- readerSupplier,
- null,
- target,
- recordedHashes,
- hasher,
- mres);
-
- // may need a reference to a patched module if --patch-module specified
- mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
-
- return mref;
- }
-
- private HashSupplier hashSupplier(String name) {
- if (!hashes.containsKey(name))
- return null;
-
- return new HashSupplier() {
- @Override
- public byte[] generate(String algorithm) {
- return hashes.get(name);
- }
- };
- }
-
- /**
- * A ModuleReader for reading resources from a module linked into the
- * run-time image.
- */
- static class ImageModuleReader implements ModuleReader {
- private final String module;
- private volatile boolean closed;
-
- /**
- * If there is a security manager set then check permission to
- * connect to the run-time image.
- */
- private static void checkPermissionToConnect(URI uri) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- try {
- URLConnection uc = uri.toURL().openConnection();
- sm.checkPermission(uc.getPermission());
- } catch (IOException ioe) {
- throw new UncheckedIOException(ioe);
- }
- }
- }
-
- ImageModuleReader(String module, URI uri) {
- checkPermissionToConnect(uri);
- this.module = module;
- }
-
- /**
- * Returns the ImageLocation for the given resource, {@code null}
- * if not found.
- */
- private ImageLocation findImageLocation(String name) throws IOException {
- Objects.requireNonNull(name);
- if (closed)
- throw new IOException("ModuleReader is closed");
- ImageReader imageReader = SystemImage.reader();
- if (imageReader != null) {
- return imageReader.findLocation(module, name);
- } else {
- // not an images build
- return null;
- }
- }
-
- @Override
- public Optional<URI> find(String name) throws IOException {
- ImageLocation location = findImageLocation(name);
- if (location != null) {
- URI u = URI.create("jrt:/" + module + "/" + name);
- return Optional.of(u);
- } else {
- return Optional.empty();
- }
- }
-
- @Override
- public Optional<InputStream> open(String name) throws IOException {
- return read(name).map(this::toInputStream);
- }
-
- private InputStream toInputStream(ByteBuffer bb) { // ## -> ByteBuffer?
- try {
- int rem = bb.remaining();
- byte[] bytes = new byte[rem];
- bb.get(bytes);
- return new ByteArrayInputStream(bytes);
- } finally {
- release(bb);
- }
- }
-
- @Override
- public Optional<ByteBuffer> read(String name) throws IOException {
- ImageLocation location = findImageLocation(name);
- if (location != null) {
- return Optional.of(SystemImage.reader().getResourceBuffer(location));
- } else {
- return Optional.empty();
- }
- }
-
- @Override
- public void release(ByteBuffer bb) {
- Objects.requireNonNull(bb);
- ImageReader.releaseByteBuffer(bb);
- }
-
- @Override
- public Stream<String> list() throws IOException {
- if (closed)
- throw new IOException("ModuleReader is closed");
-
- Spliterator<String> s = new ModuleContentSpliterator(module);
- return StreamSupport.stream(s, false);
- }
-
- @Override
- public void close() {
- // nothing else to do
- closed = true;
- }
- }
-
- /**
- * A Spliterator for traversing the resources of a module linked into the
- * run-time image.
- */
- static class ModuleContentSpliterator implements Spliterator<String> {
- final String moduleRoot;
- final Deque<ImageReader.Node> stack;
- Iterator<ImageReader.Node> iterator;
-
- ModuleContentSpliterator(String module) throws IOException {
- moduleRoot = "/modules/" + module;
- stack = new ArrayDeque<>();
-
- // push the root node to the stack to get started
- ImageReader.Node dir = SystemImage.reader().findNode(moduleRoot);
- if (dir == null || !dir.isDirectory())
- throw new IOException(moduleRoot + " not a directory");
- stack.push(dir);
- iterator = Collections.emptyIterator();
- }
-
- /**
- * Returns the name of the next non-directory node or {@code null} if
- * there are no remaining nodes to visit.
- */
- private String next() throws IOException {
- for (;;) {
- while (iterator.hasNext()) {
- ImageReader.Node node = iterator.next();
- String name = node.getName();
- if (node.isDirectory()) {
- // build node
- ImageReader.Node dir = SystemImage.reader().findNode(name);
- assert dir.isDirectory();
- stack.push(dir);
- } else {
- // strip /modules/$MODULE/ prefix
- return name.substring(moduleRoot.length() + 1);
- }
- }
-
- if (stack.isEmpty()) {
- return null;
- } else {
- ImageReader.Node dir = stack.poll();
- assert dir.isDirectory();
- iterator = dir.getChildren().iterator();
- }
- }
- }
-
- @Override
- public boolean tryAdvance(Consumer<? super String> action) {
- String next;
- try {
- next = next();
- } catch (IOException ioe) {
- throw new UncheckedIOException(ioe);
- }
- if (next != null) {
- action.accept(next);
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public Spliterator<String> trySplit() {
- return null;
- }
-
- @Override
- public int characteristics() {
- return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE;
- }
-
- @Override
- public long estimateSize() {
- return Long.MAX_VALUE;
- }
- }
-}