jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java
changeset 46110 e256651a360a
parent 46109 198011f2d98b
parent 46106 45a4132e9886
child 46111 14df107500cc
--- 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;
-        }
-    }
-}