--- old/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java 2015-11-05 15:11:01.831555900 +0530 +++ new/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java 2015-11-05 15:11:01.342527900 +0530 @@ -158,7 +158,6 @@ throws IOException { NodeAndImage ni = checkNode(path); Node node = ni.node.resolveLink(true); - if (!node.isDirectory()) { throw new NotDirectoryException(getString(path)); } @@ -171,7 +170,7 @@ return packagesDirIterator(path, childPrefix); } - return nodesToIterator(toJrtPath(path), childPrefix, node.getChildren()); + return nodesToIterator(toJrtPath(path), ni.symLink, childPrefix, node.getChildren()); } @Override @@ -200,10 +199,13 @@ final Node node; final ImageReader image; + // was there a symlink somewhere while resolving this Node from name? + final boolean symLink; - NodeAndImage(Node node, ImageReader image) { + NodeAndImage(Node node, ImageReader image, boolean symLink) { this.node = node; this.image = image; + this.symLink = symLink; } byte[] getResource() throws IOException { @@ -212,6 +214,10 @@ } private NodeAndImage lookup(byte[] path) { + return lookup(path, false); + } + + private NodeAndImage lookup(byte[] path, boolean symLink) { ImageReader image = bootImage; Node node; try { @@ -219,14 +225,14 @@ } catch (RuntimeException re) { throw new InvalidPathException(getString(path), re.toString()); } - return node != null ? new NodeAndImage(node, image) : null; + return node != null ? new NodeAndImage(node, image, symLink) : 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); + NodeAndImage ni = lookup(prefix, true); if (ni == null) { break; } @@ -236,7 +242,7 @@ // 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); + ni = lookup(resPathBytes, true); return ni != null ? ni : lookupSymbolic(resPathBytes); } } @@ -279,11 +285,30 @@ return new JrtPath(this, path); } - private Iterator nodesToIterator(Path path, String childPrefix, List childNodes) { - Function f = childPrefix == null - ? child -> toJrtPath(child.getNameString()) - : child -> toJrtPath(childPrefix + child.getNameString().substring(1)); - return childNodes.stream().map(f).collect(toList()).iterator(); + private static final int MODULES_LEN = "/modules/".length(); + private static final int PACKAGES_LEN = "/packages/".length(); + + private Iterator nodesToIterator(Path path, boolean symLink, String childPrefix, List childNodes) { + // Function that maps name -> Path (adding prefix if needed) + Function prefixHandler = childPrefix == null + ? childStr -> toJrtPath(childStr) + : childStr -> toJrtPath(childPrefix + childStr.substring(1)); + + // function to map Node->name + Function nodeHandler; + if (symLink) { + // There was a symlink in the parent dir! We need to make sure that the child paths + // use the appropriate parent prefix in the name. + String parentStr = path.toAbsolutePath().toString(); + // "/packages/java.lang/java.base/java/" -> "/packages/java.lang/" + String parentPrefix = parentStr.substring(0, 1 + parentStr.indexOf('/', PACKAGES_LEN)); + + nodeHandler = node -> parentPrefix + node.getNameString().substring(MODULES_LEN); + } else { + nodeHandler = Node::getNameString; + } + + return childNodes.stream().map(nodeHandler.andThen(prefixHandler)).collect(toList()).iterator(); } private List rootChildren; @@ -297,7 +322,7 @@ private Iterator rootDirIterator(byte[] path, String childPrefix) throws IOException { initRootChildren(path); - return nodesToIterator(rootPath, childPrefix, rootChildren); + return nodesToIterator(rootPath, false, childPrefix, rootChildren); } private List modulesChildren; @@ -311,7 +336,7 @@ private Iterator modulesDirIterator(byte[] path, String childPrefix) throws IOException { initModulesChildren(path); - return nodesToIterator(new JrtPath(this, path), childPrefix, modulesChildren); + return nodesToIterator(new JrtPath(this, path), false, childPrefix, modulesChildren); } private List packagesChildren; @@ -325,6 +350,6 @@ private Iterator packagesDirIterator(byte[] path, String childPrefix) throws IOException { initPackagesChildren(path); - return nodesToIterator(new JrtPath(this, path), childPrefix, packagesChildren); + return nodesToIterator(new JrtPath(this, path), false, childPrefix, packagesChildren); } }