< prev index next >

src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java

Print this page

        

*** 29,41 **** import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; - import java.nio.file.AccessMode; import java.nio.file.ClosedFileSystemException; import java.nio.file.CopyOption; import java.nio.file.FileStore; import java.nio.file.FileSystem; import java.nio.file.FileSystemException; import java.nio.file.FileSystemNotFoundException; import java.nio.file.Files; --- 29,41 ---- import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import java.nio.file.ClosedFileSystemException; import java.nio.file.CopyOption; + import java.nio.file.LinkOption; import java.nio.file.FileStore; import java.nio.file.FileSystem; import java.nio.file.FileSystemException; import java.nio.file.FileSystemNotFoundException; import java.nio.file.Files;
*** 43,81 **** import java.nio.file.NotDirectoryException; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.ReadOnlyFileSystemException; - import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.nio.file.WatchService; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.UserPrincipalLookupService; import java.nio.file.spi.FileSystemProvider; ! import java.security.AccessController; ! import java.security.PrivilegedActionException; ! import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; ! import java.util.stream.Collectors; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReader.Node; import jdk.internal.jimage.UTF8String; /** * A FileSystem built on System jimage files. */ class JrtFileSystem extends FileSystem { private static final Charset UTF_8 = Charset.forName("UTF-8"); private final JrtFileSystemProvider provider; // System image readers private ImageReader bootImage; private ImageReader extImage; private ImageReader appImage; --- 43,80 ---- import java.nio.file.NotDirectoryException; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.ReadOnlyFileSystemException; import java.nio.file.StandardOpenOption; import java.nio.file.WatchService; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.UserPrincipalLookupService; import java.nio.file.spi.FileSystemProvider; ! import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; + import java.util.function.Function; import java.util.regex.Pattern; ! import static java.util.stream.Collectors.toList; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReader.Node; import jdk.internal.jimage.UTF8String; /** * A FileSystem built on System jimage files. */ class JrtFileSystem extends FileSystem { private static final Charset UTF_8 = Charset.forName("UTF-8"); + private final JrtFileSystemProvider provider; // System image readers private ImageReader bootImage; private ImageReader extImage; private ImageReader appImage;
*** 107,117 **** // open image files this.bootImage = openImage(SystemImages.bootImagePath); this.extImage = openImage(SystemImages.extImagePath); this.appImage = openImage(SystemImages.appImagePath); ! rootPath = new JrtPath(this, new byte[]{'/'}); isOpen = true; } @Override public FileSystemProvider provider() { --- 106,117 ---- // open image files this.bootImage = openImage(SystemImages.bootImagePath); this.extImage = openImage(SystemImages.extImagePath); this.appImage = openImage(SystemImages.appImagePath); ! byte[] root = new byte[] { '/' }; ! rootPath = new JrtPath(this, root); isOpen = true; } @Override public FileSystemProvider provider() {
*** 147,162 **** } synchronized(this) { isOpen = false; ! // close all image readers and null out bootImage.close(); - extImage.close(); - appImage.close(); bootImage = null; extImage = null; appImage = null; } } private void ensureOpen() throws IOException { --- 147,162 ---- } synchronized(this) { isOpen = false; ! // close all image reader and null out bootImage.close(); bootImage = null; + extImage.close(); extImage = null; + appImage.close(); appImage = null; } } private void ensureOpen() throws IOException {
*** 287,311 **** byte[] getResource() throws IOException { return image.getResource(node); } } ! private NodeAndImage findNode(byte[] path) throws IOException { ! ImageReader image = bootImage; Node node = bootImage.findNode(path); if (node == null) { - image = extImage; node = extImage.findNode(path); } if (node == null) { - image = appImage; node = appImage.findNode(path); } ! if (node == null || node.isHidden()) { throw new NoSuchFileException(getString(path)); } ! return new NodeAndImage(node, image); } private NodeAndImage checkNode(byte[] path) throws IOException { ensureOpen(); return findNode(path); --- 287,342 ---- byte[] getResource() throws IOException { return image.getResource(node); } } ! private NodeAndImage lookup(byte[] path) { Node node = bootImage.findNode(path); + ImageReader image = bootImage; if (node == null) { node = extImage.findNode(path); + image = extImage; } if (node == null) { node = appImage.findNode(path); + image = appImage; + } + return node != null? new NodeAndImage(node, image) : null; + } + + private NodeAndImage lookupSymbolic(byte[] path) { + for (int i = 1; i < path.length; i++) { + if (path[i] == (byte)'/') { + byte[] prefix = Arrays.copyOfRange(path, 0, i); + NodeAndImage ni = lookup(prefix); + if (ni == null) { + break; + } + + if (ni.node.isLink()) { + Node link = ni.node.resolveLink(true); + // resolved symbolic path concatenated to the rest of the path + UTF8String resPath = link.getName().concat(new UTF8String(path, i)); + byte[] resPathBytes = resPath.getBytesCopy(); + ni = lookup(resPathBytes); + return ni != null? ni : lookupSymbolic(resPathBytes); } ! } ! } ! ! return null; ! } ! ! private NodeAndImage findNode(byte[] path) throws IOException { ! NodeAndImage ni = lookup(path); ! if (ni == null) { ! ni = lookupSymbolic(path); ! if (ni == null) { throw new NoSuchFileException(getString(path)); } ! } ! return ni; } private NodeAndImage checkNode(byte[] path) throws IOException { ensureOpen(); return findNode(path);
*** 319,332 **** assert ni.node.isResource() : "resource node expected here"; return ni; } // package private helpers ! JrtFileAttributes getFileAttributes(byte[] path) throws IOException { NodeAndImage ni = checkNode(path); return new JrtFileAttributes(ni.node); } void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime) throws IOException { --- 350,381 ---- assert ni.node.isResource() : "resource node expected here"; return ni; } + static boolean followLinks(LinkOption... options) { + if (options != null) { + for (LinkOption lo : options) { + if (lo == LinkOption.NOFOLLOW_LINKS) { + return false; + } else if (lo == null) { + throw new NullPointerException(); + } else { + throw new AssertionError("should not reach here"); + } + } + } + return true; + } + // package private helpers ! JrtFileAttributes getFileAttributes(byte[] path, LinkOption... options) throws IOException { NodeAndImage ni = checkNode(path); + if (ni.node.isLink() && followLinks(options)) { + return new JrtFileAttributes(ni.node.resolveLink(true)); + } return new JrtFileAttributes(ni.node); } void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime) throws IOException {
*** 341,365 **** return false; } return true; } ! boolean isDirectory(byte[] path) throws IOException { ensureOpen(); NodeAndImage ni = checkNode(path); ! return ni.node.isDirectory(); } JrtPath toJrtPath(String path) { return toJrtPath(getBytes(path)); } JrtPath toJrtPath(byte[] path) { return new JrtPath(this, path); } /** * returns the list of child paths of the given directory "path" * * @param path name of the directory whose content is listed * @param childPrefix prefix added to returned children names - may be null --- 390,438 ---- return false; } return true; } ! boolean isDirectory(byte[] path, boolean resolveLinks) throws IOException { ensureOpen(); NodeAndImage ni = checkNode(path); ! return resolveLinks && ni.node.isLink()? ! ni.node.resolveLink(true).isDirectory() : ! ni.node.isDirectory(); } JrtPath toJrtPath(String path) { return toJrtPath(getBytes(path)); } JrtPath toJrtPath(byte[] path) { return new JrtPath(this, path); } + boolean isSameFile(JrtPath p1, JrtPath p2) throws IOException { + NodeAndImage n1 = findNode(p1.getName()); + NodeAndImage n2 = findNode(p2.getName()); + return n1.node.equals(n2.node); + } + + boolean isLink(JrtPath jrtPath) throws IOException { + return findNode(jrtPath.getName()).node.isLink(); + } + + JrtPath resolveLink(JrtPath jrtPath) throws IOException { + NodeAndImage ni = findNode(jrtPath.getName()); + if (ni.node.isLink()) { + Node node = ni.node.resolveLink(); + return toJrtPath(node.getName().getBytesCopy()); + } + + return jrtPath; + } + + private Map<UTF8String, List<Node>> packagesTreeChildren = new ConcurrentHashMap<>(); + /** * returns the list of child paths of the given directory "path" * * @param path name of the directory whose content is listed * @param childPrefix prefix added to returned children names - may be null
*** 367,427 **** * @return iterator for child paths of the given directory path */ Iterator<Path> iteratorOf(byte[] path, String childPrefix) throws IOException { NodeAndImage ni = checkNode(path); ! if (!ni.node.isDirectory()) { throw new NotDirectoryException(getString(path)); } ! if (ni.node.isRootDir()) { return rootDirIterator(path, childPrefix); } ! return nodesToIterator(toJrtPath(path), childPrefix, ni.node.getChildren()); } ! private Iterator<Path> nodesToIterator(Path path, String childPrefix, List<Node> childNodes) { ! List<Path> childPaths; ! if (childPrefix == null) { ! childPaths = childNodes.stream() ! .filter(Node::isVisible) ! .map(child -> toJrtPath(child.getNameString())) ! .collect(Collectors.toCollection(ArrayList::new)); ! } else { ! childPaths = childNodes.stream() ! .filter(Node::isVisible) ! .map(child -> toJrtPath(childPrefix + child.getNameString().substring(1))) ! .collect(Collectors.toCollection(ArrayList::new)); } - return childPaths.iterator(); } ! private List<Node> rootChildren; ! private static void addRootDirContent(List<Node> dest, List<Node> src) { ! for (Node n : src) { ! // only module directories at the top level. Filter other stuff! ! if (n.isModuleDir()) { ! dest.add(n); } } } private synchronized void initRootChildren(byte[] path) { if (rootChildren == null) { rootChildren = new ArrayList<>(); ! addRootDirContent(rootChildren, bootImage.findNode(path).getChildren()); ! addRootDirContent(rootChildren, extImage.findNode(path).getChildren()); ! addRootDirContent(rootChildren, appImage.findNode(path).getChildren()); } } private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException { initRootChildren(path); return nodesToIterator(rootPath, childPrefix, rootChildren); } void createDirectory(byte[] dir, FileAttribute<?>... attrs) throws IOException { throw readOnly(); } --- 440,553 ---- * @return iterator for child paths of the given directory path */ Iterator<Path> iteratorOf(byte[] path, String childPrefix) throws IOException { NodeAndImage ni = checkNode(path); ! Node node = ni.node.resolveLink(true); ! ! if (!node.isDirectory()) { throw new NotDirectoryException(getString(path)); } ! if (node.isRootDir()) { return rootDirIterator(path, childPrefix); + } else if (node.isModulesDir()) { + return modulesDirIterator(path, childPrefix); + } else if (node.isPackagesDir()) { + return packagesDirIterator(path, childPrefix); + } else if (node.getNameString().startsWith("/packages/")) { + if (ni.image != appImage) { + UTF8String name = node.getName(); + List<Node> children = packagesTreeChildren.get(name); + if (children != null) { + return nodesToIterator(toJrtPath(path), childPrefix, children); + } + + children = new ArrayList<>(); + children.addAll(node.getChildren()); + Node tmpNode = null; + // found in boot + if (ni.image == bootImage) { + tmpNode = extImage.findNode(name); + if (tmpNode != null) { + children.addAll(tmpNode.getChildren()); + } } ! // found in ext ! tmpNode = appImage.findNode(name); ! if (tmpNode != null) { ! children.addAll(tmpNode.getChildren()); } ! packagesTreeChildren.put(name, children); ! return nodesToIterator(toJrtPath(path), childPrefix, children); } } ! return nodesToIterator(toJrtPath(path), childPrefix, node.getChildren()); ! } ! ! private Iterator<Path> nodesToIterator(Path path, String childPrefix, List<Node> childNodes) { ! Function<Node, Path> f = childPrefix == null ! ? child -> toJrtPath(child.getNameString()) ! : child -> toJrtPath(childPrefix + child.getNameString().substring(1)); ! return childNodes.stream().map(f).collect(toList()).iterator(); ! } ! ! private void addRootDirContent(List<Node> children) { ! for (Node child : children) { ! if (!(child.isModulesDir() || child.isPackagesDir())) { ! rootChildren.add(child); } } } + private List<Node> rootChildren; private synchronized void initRootChildren(byte[] path) { if (rootChildren == null) { rootChildren = new ArrayList<>(); ! rootChildren.addAll(bootImage.findNode(path).getChildren()); ! addRootDirContent(extImage.findNode(path).getChildren()); ! addRootDirContent(appImage.findNode(path).getChildren()); } } private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException { initRootChildren(path); return nodesToIterator(rootPath, childPrefix, rootChildren); } + private List<Node> modulesChildren; + private synchronized void initModulesChildren(byte[] path) { + if (modulesChildren == null) { + modulesChildren = new ArrayList<>(); + modulesChildren.addAll(bootImage.findNode(path).getChildren()); + modulesChildren.addAll(appImage.findNode(path).getChildren()); + modulesChildren.addAll(extImage.findNode(path).getChildren()); + } + } + + private Iterator<Path> modulesDirIterator(byte[] path, String childPrefix) throws IOException { + initModulesChildren(path); + return nodesToIterator(new JrtPath(this, path), childPrefix, modulesChildren); + } + + private List<Node> packagesChildren; + private synchronized void initPackagesChildren(byte[] path) { + if (packagesChildren == null) { + packagesChildren = new ArrayList<>(); + packagesChildren.addAll(bootImage.findNode(path).getChildren()); + packagesChildren.addAll(extImage.findNode(path).getChildren()); + packagesChildren.addAll(appImage.findNode(path).getChildren()); + } + } + private Iterator<Path> packagesDirIterator(byte[] path, String childPrefix) throws IOException { + initPackagesChildren(path); + return nodesToIterator(new JrtPath(this, path), childPrefix, packagesChildren); + } + void createDirectory(byte[] dir, FileAttribute<?>... attrs) throws IOException { throw readOnly(); }
< prev index next >