< 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 >