--- old/src/java.base/share/classes/java/lang/module/ModuleReferences.java 2016-12-15 09:19:29.643271773 +0000 +++ /dev/null 2016-12-10 08:16:53.177999985 +0000 @@ -1,443 +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 java.lang.module; - -import java.io.File; -import java.io.IOError; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.net.URI; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.zip.ZipFile; - -import jdk.internal.jmod.JmodFile; -import jdk.internal.misc.JavaLangAccess; -import jdk.internal.misc.SharedSecrets; -import jdk.internal.module.ModuleBootstrap; -import jdk.internal.module.ModuleHashes; -import jdk.internal.module.ModuleHashes.HashSupplier; -import jdk.internal.module.ModulePatcher; -import jdk.internal.util.jar.VersionedStream; -import sun.net.www.ParseUtil; - - -/** - * A factory for creating ModuleReference implementations where the modules are - * packaged as modular JAR file, JMOD files or where the modules are exploded - * on the file system. - */ - -class ModuleReferences { - - private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); - - private ModuleReferences() { } - - /** - * Creates a ModuleReference to a module or to patched module when - * creating modules for the boot Layer and --patch-module is specified. - */ - private static ModuleReference newModule(ModuleDescriptor md, - URI uri, - Supplier supplier, - HashSupplier hasher) { - - ModuleReference mref = new ModuleReference(md, uri, supplier, hasher); - if (JLA.getBootLayer() == null) - mref = ModuleBootstrap.patcher().patchIfNeeded(mref); - - return mref; - } - - /** - * Creates a ModuleReference to a module packaged as a modular JAR. - */ - static ModuleReference newJarModule(ModuleDescriptor md, Path file) { - URI uri = file.toUri(); - Supplier supplier = () -> new JarModuleReader(file, uri); - HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a); - return newModule(md, uri, supplier, hasher); - } - - /** - * Creates a ModuleReference to a module packaged as a JMOD. - */ - static ModuleReference newJModModule(ModuleDescriptor md, Path file) { - URI uri = file.toUri(); - Supplier supplier = () -> new JModModuleReader(file, uri); - HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a); - return newModule(md, file.toUri(), supplier, hasher); - } - - /** - * Creates a ModuleReference to an exploded module. - */ - static ModuleReference newExplodedModule(ModuleDescriptor md, Path dir) { - Supplier supplier = () -> new ExplodedModuleReader(dir); - return newModule(md, dir.toUri(), supplier, null); - } - - - /** - * A base module reader that encapsulates machinery required to close the - * module reader safely. - */ - static abstract class SafeCloseModuleReader implements ModuleReader { - - // RW lock to support safe close - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private final Lock readLock = lock.readLock(); - private final Lock writeLock = lock.writeLock(); - private boolean closed; - - SafeCloseModuleReader() { } - - /** - * Returns a URL to resource. This method is invoked by the find - * method to do the actual work of finding the resource. - */ - abstract Optional implFind(String name) throws IOException; - - /** - * Returns an input stream for reading a resource. This method is - * invoked by the open method to do the actual work of opening - * an input stream to the resource. - */ - abstract Optional implOpen(String name) throws IOException; - - /** - * Returns a stream of the names of resources in the module. This - * method is invoked by the list method to do the actual work of - * creating the stream. - */ - abstract Stream implList() throws IOException; - - /** - * Closes the module reader. This method is invoked by close to do the - * actual work of closing the module reader. - */ - abstract void implClose() throws IOException; - - @Override - public final Optional find(String name) throws IOException { - readLock.lock(); - try { - if (!closed) { - return implFind(name); - } else { - throw new IOException("ModuleReader is closed"); - } - } finally { - readLock.unlock(); - } - } - - - @Override - public final Optional open(String name) throws IOException { - readLock.lock(); - try { - if (!closed) { - return implOpen(name); - } else { - throw new IOException("ModuleReader is closed"); - } - } finally { - readLock.unlock(); - } - } - - @Override - public final Stream list() throws IOException { - readLock.lock(); - try { - if (!closed) { - return implList(); - } else { - throw new IOException("ModuleReader is closed"); - } - } finally { - readLock.unlock(); - } - } - - @Override - public final void close() throws IOException { - writeLock.lock(); - try { - if (!closed) { - closed = true; - implClose(); - } - } finally { - writeLock.unlock(); - } - } - } - - - /** - * A ModuleReader for a modular JAR file. - */ - static class JarModuleReader extends SafeCloseModuleReader { - private final JarFile jf; - private final URI uri; - - static JarFile newJarFile(Path path) { - try { - return new JarFile(path.toFile(), - true, // verify - ZipFile.OPEN_READ, - JarFile.runtimeVersion()); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - - JarModuleReader(Path path, URI uri) { - this.jf = newJarFile(path); - this.uri = uri; - } - - private JarEntry getEntry(String name) { - return jf.getJarEntry(Objects.requireNonNull(name)); - } - - @Override - Optional implFind(String name) throws IOException { - JarEntry je = getEntry(name); - if (je != null) { - if (jf.isMultiRelease()) - name = SharedSecrets.javaUtilJarAccess().getRealName(jf, je); - String encodedPath = ParseUtil.encodePath(name, false); - String uris = "jar:" + uri + "!/" + encodedPath; - return Optional.of(URI.create(uris)); - } else { - return Optional.empty(); - } - } - - @Override - Optional implOpen(String name) throws IOException { - JarEntry je = getEntry(name); - if (je != null) { - return Optional.of(jf.getInputStream(je)); - } else { - return Optional.empty(); - } - } - - @Override - Stream implList() throws IOException { - // take snapshot to avoid async close - List names = VersionedStream.stream(jf) - .filter(e -> !e.isDirectory()) - .map(JarEntry::getName) - .collect(Collectors.toList()); - return names.stream(); - } - - @Override - void implClose() throws IOException { - jf.close(); - } - } - - - /** - * A ModuleReader for a JMOD file. - */ - static class JModModuleReader extends SafeCloseModuleReader { - private final JmodFile jf; - private final URI uri; - - static JmodFile newJmodFile(Path path) { - try { - return new JmodFile(path); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - - JModModuleReader(Path path, URI uri) { - this.jf = newJmodFile(path); - this.uri = uri; - } - - private JmodFile.Entry getEntry(String name) { - Objects.requireNonNull(name); - return jf.getEntry(JmodFile.Section.CLASSES, name); - } - - @Override - Optional implFind(String name) { - JmodFile.Entry je = getEntry(name); - if (je != null) { - String encodedPath = ParseUtil.encodePath(name, false); - String uris = "jmod:" + uri + "!/" + encodedPath; - return Optional.of(URI.create(uris)); - } else { - return Optional.empty(); - } - } - - @Override - Optional implOpen(String name) throws IOException { - JmodFile.Entry je = getEntry(name); - if (je != null) { - return Optional.of(jf.getInputStream(je)); - } else { - return Optional.empty(); - } - } - - @Override - Stream implList() throws IOException { - // take snapshot to avoid async close - List names = jf.stream() - .filter(e -> e.section() == JmodFile.Section.CLASSES) - .map(JmodFile.Entry::name) - .collect(Collectors.toList()); - return names.stream(); - } - - @Override - void implClose() throws IOException { - jf.close(); - } - } - - - /** - * A ModuleReader for an exploded module. - */ - static class ExplodedModuleReader implements ModuleReader { - private final Path dir; - private volatile boolean closed; - - ExplodedModuleReader(Path dir) { - this.dir = dir; - - // when running with a security manager then check that the caller - // has access to the directory. - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - boolean unused = Files.isDirectory(dir); - } - } - - /** - * Returns a Path to access to the given resource. - */ - private Path toPath(String name) { - Path path = Paths.get(name.replace('/', File.separatorChar)); - if (path.getRoot() == null) { - return dir.resolve(path); - } else { - // drop the root component so that the resource is - // located relative to the module directory - int n = path.getNameCount(); - return (n > 0) ? dir.resolve(path.subpath(0, n)) : null; - } - } - - /** - * Throws IOException if the module reader is closed; - */ - private void ensureOpen() throws IOException { - if (closed) throw new IOException("ModuleReader is closed"); - } - - @Override - public Optional find(String name) throws IOException { - ensureOpen(); - Path path = toPath(name); - if (path != null && Files.isRegularFile(path)) { - try { - return Optional.of(path.toUri()); - } catch (IOError e) { - throw (IOException) e.getCause(); - } - } else { - return Optional.empty(); - } - } - - @Override - public Optional open(String name) throws IOException { - ensureOpen(); - Path path = toPath(name); - if (path != null && Files.isRegularFile(path)) { - return Optional.of(Files.newInputStream(path)); - } else { - return Optional.empty(); - } - } - - @Override - public Optional read(String name) throws IOException { - ensureOpen(); - Path path = toPath(name); - if (path != null && Files.isRegularFile(path)) { - return Optional.of(ByteBuffer.wrap(Files.readAllBytes(path))); - } else { - return Optional.empty(); - } - } - - @Override - public Stream list() throws IOException { - ensureOpen(); - // sym links not followed - return Files.find(dir, Integer.MAX_VALUE, - (path, attrs) -> attrs.isRegularFile()) - .map(f -> dir.relativize(f) - .toString() - .replace(File.separatorChar, '/')); - } - - @Override - public void close() { - closed = true; - } - } - -} --- /dev/null 2016-12-10 08:16:53.177999985 +0000 +++ new/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java 2016-12-15 09:19:29.442258022 +0000 @@ -0,0 +1,448 @@ +/* + * 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.File; +import java.io.IOError; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Supplier; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipFile; + +import jdk.internal.jmod.JmodFile; +import jdk.internal.misc.JavaLangAccess; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.module.ModuleHashes.HashSupplier; +import jdk.internal.util.jar.VersionedStream; +import sun.net.www.ParseUtil; + + +/** + * A factory for creating ModuleReference implementations where the modules are + * packaged as modular JAR file, JMOD files or where the modules are exploded + * on the file system. + */ + +class ModuleReferences { + + private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + + private ModuleReferences() { } + + /** + * Creates a ModuleReference to a module or to patched module when + * creating modules for the boot Layer and --patch-module is specified. + */ + private static ModuleReference newModule(ModuleInfo.Attributes attrs, + URI uri, + Supplier supplier, + HashSupplier hasher) { + + ModuleReference mref = new ModuleReferenceImpl(attrs.descriptor(), + uri, + supplier, + null, + attrs.recordedHashes(), + hasher, + attrs.moduleResolution()); + if (JLA.getBootLayer() == null) + mref = ModuleBootstrap.patcher().patchIfNeeded(mref); + + return mref; + } + + /** + * Creates a ModuleReference to a module packaged as a modular JAR. + */ + static ModuleReference newJarModule(ModuleInfo.Attributes attrs, Path file) { + URI uri = file.toUri(); + Supplier supplier = () -> new JarModuleReader(file, uri); + HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a); + return newModule(attrs, uri, supplier, hasher); + } + + /** + * Creates a ModuleReference to a module packaged as a JMOD. + */ + static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) { + URI uri = file.toUri(); + Supplier supplier = () -> new JModModuleReader(file, uri); + HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a); + return newModule(attrs, uri, supplier, hasher); + } + + /** + * Creates a ModuleReference to an exploded module. + */ + static ModuleReference newExplodedModule(ModuleInfo.Attributes attrs, Path dir) { + Supplier supplier = () -> new ExplodedModuleReader(dir); + return newModule(attrs, dir.toUri(), supplier, null); + } + + + /** + * A base module reader that encapsulates machinery required to close the + * module reader safely. + */ + static abstract class SafeCloseModuleReader implements ModuleReader { + + // RW lock to support safe close + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + private boolean closed; + + SafeCloseModuleReader() { } + + /** + * Returns a URL to resource. This method is invoked by the find + * method to do the actual work of finding the resource. + */ + abstract Optional implFind(String name) throws IOException; + + /** + * Returns an input stream for reading a resource. This method is + * invoked by the open method to do the actual work of opening + * an input stream to the resource. + */ + abstract Optional implOpen(String name) throws IOException; + + /** + * Returns a stream of the names of resources in the module. This + * method is invoked by the list method to do the actual work of + * creating the stream. + */ + abstract Stream implList() throws IOException; + + /** + * Closes the module reader. This method is invoked by close to do the + * actual work of closing the module reader. + */ + abstract void implClose() throws IOException; + + @Override + public final Optional find(String name) throws IOException { + readLock.lock(); + try { + if (!closed) { + return implFind(name); + } else { + throw new IOException("ModuleReader is closed"); + } + } finally { + readLock.unlock(); + } + } + + + @Override + public final Optional open(String name) throws IOException { + readLock.lock(); + try { + if (!closed) { + return implOpen(name); + } else { + throw new IOException("ModuleReader is closed"); + } + } finally { + readLock.unlock(); + } + } + + @Override + public final Stream list() throws IOException { + readLock.lock(); + try { + if (!closed) { + return implList(); + } else { + throw new IOException("ModuleReader is closed"); + } + } finally { + readLock.unlock(); + } + } + + @Override + public final void close() throws IOException { + writeLock.lock(); + try { + if (!closed) { + closed = true; + implClose(); + } + } finally { + writeLock.unlock(); + } + } + } + + + /** + * A ModuleReader for a modular JAR file. + */ + static class JarModuleReader extends SafeCloseModuleReader { + private final JarFile jf; + private final URI uri; + + static JarFile newJarFile(Path path) { + try { + return new JarFile(path.toFile(), + true, // verify + ZipFile.OPEN_READ, + JarFile.runtimeVersion()); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + + JarModuleReader(Path path, URI uri) { + this.jf = newJarFile(path); + this.uri = uri; + } + + private JarEntry getEntry(String name) { + return jf.getJarEntry(Objects.requireNonNull(name)); + } + + @Override + Optional implFind(String name) throws IOException { + JarEntry je = getEntry(name); + if (je != null) { + if (jf.isMultiRelease()) + name = SharedSecrets.javaUtilJarAccess().getRealName(jf, je); + String encodedPath = ParseUtil.encodePath(name, false); + String uris = "jar:" + uri + "!/" + encodedPath; + return Optional.of(URI.create(uris)); + } else { + return Optional.empty(); + } + } + + @Override + Optional implOpen(String name) throws IOException { + JarEntry je = getEntry(name); + if (je != null) { + return Optional.of(jf.getInputStream(je)); + } else { + return Optional.empty(); + } + } + + @Override + Stream implList() throws IOException { + // take snapshot to avoid async close + List names = VersionedStream.stream(jf) + .filter(e -> !e.isDirectory()) + .map(JarEntry::getName) + .collect(Collectors.toList()); + return names.stream(); + } + + @Override + void implClose() throws IOException { + jf.close(); + } + } + + + /** + * A ModuleReader for a JMOD file. + */ + static class JModModuleReader extends SafeCloseModuleReader { + private final JmodFile jf; + private final URI uri; + + static JmodFile newJmodFile(Path path) { + try { + return new JmodFile(path); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + + JModModuleReader(Path path, URI uri) { + this.jf = newJmodFile(path); + this.uri = uri; + } + + private JmodFile.Entry getEntry(String name) { + Objects.requireNonNull(name); + return jf.getEntry(JmodFile.Section.CLASSES, name); + } + + @Override + Optional implFind(String name) { + JmodFile.Entry je = getEntry(name); + if (je != null) { + String encodedPath = ParseUtil.encodePath(name, false); + String uris = "jmod:" + uri + "!/" + encodedPath; + return Optional.of(URI.create(uris)); + } else { + return Optional.empty(); + } + } + + @Override + Optional implOpen(String name) throws IOException { + JmodFile.Entry je = getEntry(name); + if (je != null) { + return Optional.of(jf.getInputStream(je)); + } else { + return Optional.empty(); + } + } + + @Override + Stream implList() throws IOException { + // take snapshot to avoid async close + List names = jf.stream() + .filter(e -> e.section() == JmodFile.Section.CLASSES) + .map(JmodFile.Entry::name) + .collect(Collectors.toList()); + return names.stream(); + } + + @Override + void implClose() throws IOException { + jf.close(); + } + } + + + /** + * A ModuleReader for an exploded module. + */ + static class ExplodedModuleReader implements ModuleReader { + private final Path dir; + private volatile boolean closed; + + ExplodedModuleReader(Path dir) { + this.dir = dir; + + // when running with a security manager then check that the caller + // has access to the directory. + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + boolean unused = Files.isDirectory(dir); + } + } + + /** + * Returns a Path to access to the given resource. + */ + private Path toPath(String name) { + Path path = Paths.get(name.replace('/', File.separatorChar)); + if (path.getRoot() == null) { + return dir.resolve(path); + } else { + // drop the root component so that the resource is + // located relative to the module directory + int n = path.getNameCount(); + return (n > 0) ? dir.resolve(path.subpath(0, n)) : null; + } + } + + /** + * Throws IOException if the module reader is closed; + */ + private void ensureOpen() throws IOException { + if (closed) throw new IOException("ModuleReader is closed"); + } + + @Override + public Optional find(String name) throws IOException { + ensureOpen(); + Path path = toPath(name); + if (path != null && Files.isRegularFile(path)) { + try { + return Optional.of(path.toUri()); + } catch (IOError e) { + throw (IOException) e.getCause(); + } + } else { + return Optional.empty(); + } + } + + @Override + public Optional open(String name) throws IOException { + ensureOpen(); + Path path = toPath(name); + if (path != null && Files.isRegularFile(path)) { + return Optional.of(Files.newInputStream(path)); + } else { + return Optional.empty(); + } + } + + @Override + public Optional read(String name) throws IOException { + ensureOpen(); + Path path = toPath(name); + if (path != null && Files.isRegularFile(path)) { + return Optional.of(ByteBuffer.wrap(Files.readAllBytes(path))); + } else { + return Optional.empty(); + } + } + + @Override + public Stream list() throws IOException { + ensureOpen(); + // sym links not followed + return Files.find(dir, Integer.MAX_VALUE, + (path, attrs) -> attrs.isRegularFile()) + .map(f -> dir.relativize(f) + .toString() + .replace(File.separatorChar, '/')); + } + + @Override + public void close() { + closed = true; + } + } + +}