--- old/src/java.base/share/classes/jdk/internal/jimage/UTF8String.java 2015-11-11 21:05:46.644592200 +0530 +++ new/src/java.base/share/classes/jdk/internal/jimage/UTF8String.java 2015-11-11 21:05:46.109561600 +0530 @@ -258,10 +258,10 @@ @Override public String toString() { - ByteBuffer buffer = ByteBuffer.allocate(bytes.length+2); + ByteBuffer buffer = ByteBuffer.allocate(count+2); buffer.order(ByteOrder.BIG_ENDIAN); - buffer.putShort((short)bytes.length); - buffer.put(bytes); + buffer.putShort((short)count); + buffer.put(bytes, offset, count); ByteArrayInputStream stream = new ByteArrayInputStream(buffer.array()); DataInputStream in = new DataInputStream(stream); try { --- old/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java 2015-11-11 21:05:49.766770800 +0530 +++ new/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java 2015-11-11 21:05:49.180737200 +0530 @@ -232,48 +232,48 @@ } // These methods throw read only file system exception - final void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime) + final void setTimes(AbstractJrtPath jrtPath, FileTime mtime, FileTime atime, FileTime ctime) throws IOException { throw readOnly(); } - final void createDirectory(byte[] path, FileAttribute... attrs) throws IOException { + final void createDirectory(AbstractJrtPath jrtPath, FileAttribute... attrs) throws IOException { throw readOnly(); } - final void deleteFile(byte[] path, boolean failIfNotExists) + final void deleteFile(AbstractJrtPath jrtPath, boolean failIfNotExists) throws IOException { throw readOnly(); } - final OutputStream newOutputStream(byte[] path, OpenOption... options) + final OutputStream newOutputStream(AbstractJrtPath jrtPath, OpenOption... options) throws IOException { throw readOnly(); } - final void copyFile(boolean deletesrc, byte[] src, byte[] dst, CopyOption... options) + final void copyFile(boolean deletesrc, AbstractJrtPath srcPath, AbstractJrtPath dstPath, CopyOption... options) throws IOException { throw readOnly(); } - final FileChannel newFileChannel(byte[] path, + final FileChannel newFileChannel(AbstractJrtPath jrtPath, Set options, FileAttribute... attrs) throws IOException { throw new UnsupportedOperationException("newFileChannel"); } - final InputStream newInputStream(byte[] path) throws IOException { - return new ByteArrayInputStream(getFileContent(path)); + final InputStream newInputStream(AbstractJrtPath jrtPath) throws IOException { + return new ByteArrayInputStream(getFileContent(jrtPath)); } - final SeekableByteChannel newByteChannel(byte[] path, + final SeekableByteChannel newByteChannel(AbstractJrtPath jrtPath, Set options, FileAttribute... attrs) throws IOException { checkOptions(options); - byte[] buf = getFileContent(path); + byte[] buf = getFileContent(jrtPath); final ReadableByteChannel rbc = Channels.newChannel(new ByteArrayInputStream(buf)); final long size = buf.length; @@ -328,8 +328,8 @@ }; } - final JrtFileStore getFileStore(AbstractJrtPath path) { - return new JrtFileStore(path); + final JrtFileStore getFileStore(AbstractJrtPath jrtPath) { + return new JrtFileStore(jrtPath); } final void ensureOpen() throws IOException { @@ -341,29 +341,26 @@ // abstract methods to be implemented by a particular jrt file system abstract AbstractJrtPath getRootPath(); - abstract boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException; + abstract boolean isSameFile(AbstractJrtPath jrtPath1, AbstractJrtPath jrtPath2) throws IOException; abstract boolean isLink(AbstractJrtPath jrtPath) throws IOException; abstract AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException; - abstract AbstractJrtFileAttributes getFileAttributes(byte[] path, LinkOption... options) throws IOException; + abstract AbstractJrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException; - abstract boolean exists(byte[] path) throws IOException; + abstract boolean exists(AbstractJrtPath jrtPath) throws IOException; - abstract boolean isDirectory(byte[] path, boolean resolveLinks) throws IOException; + abstract boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException; /** * 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 - * in which case absolute child paths are returned * @return iterator for child paths of the given directory path */ - abstract Iterator iteratorOf(byte[] path, String childPrefix) - throws IOException; + abstract Iterator iteratorOf(AbstractJrtPath jrtPath) throws IOException; // returns the content of the file resource specified by the path - abstract byte[] getFileContent(byte[] path) throws IOException; + abstract byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException; } --- old/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java 2015-11-11 21:05:52.950952900 +0530 +++ new/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java 2015-11-11 21:05:52.411922100 +0530 @@ -685,7 +685,7 @@ final void createDirectory(FileAttribute... attrs) throws IOException { - jrtfs.createDirectory(getResolvedPath(), attrs); + jrtfs.createDirectory(this, attrs); } final InputStream newInputStream(OpenOption... options) throws IOException { @@ -696,7 +696,7 @@ } } } - return jrtfs.newInputStream(getResolvedPath()); + return jrtfs.newInputStream(this); } final DirectoryStream newDirectoryStream(Filter filter) @@ -705,15 +705,15 @@ } final void delete() throws IOException { - jrtfs.deleteFile(getResolvedPath(), true); + jrtfs.deleteFile(this, true); } final void deleteIfExists() throws IOException { - jrtfs.deleteFile(getResolvedPath(), false); + jrtfs.deleteFile(this, false); } final AbstractJrtFileAttributes getAttributes(LinkOption... options) throws IOException { - AbstractJrtFileAttributes zfas = jrtfs.getFileAttributes(getResolvedPath(), options); + AbstractJrtFileAttributes zfas = jrtfs.getFileAttributes(this, options); if (zfas == null) { throw new NoSuchFileException(toString()); } @@ -741,7 +741,7 @@ final void setTimes(FileTime mtime, FileTime atime, FileTime ctime) throws IOException { - jrtfs.setTimes(getResolvedPath(), mtime, atime, ctime); + jrtfs.setTimes(this, mtime, atime, ctime); } final Map readAttributes(String attributes, LinkOption... options) @@ -789,13 +789,13 @@ final SeekableByteChannel newByteChannel(Set options, FileAttribute... attrs) throws IOException { - return jrtfs.newByteChannel(getResolvedPath(), options, attrs); + return jrtfs.newByteChannel(this, options, attrs); } final FileChannel newFileChannel(Set options, FileAttribute... attrs) throws IOException { - return jrtfs.newFileChannel(getResolvedPath(), options, attrs); + return jrtfs.newFileChannel(this, options, attrs); } final void checkAccess(AccessMode... modes) throws IOException { @@ -816,7 +816,7 @@ } } - BasicFileAttributes attrs = jrtfs.getFileAttributes(getResolvedPath()); + BasicFileAttributes attrs = jrtfs.getFileAttributes(this); if (attrs == null && (path.length != 1 || path[0] != '/')) { throw new NoSuchFileException(toString()); } @@ -831,7 +831,7 @@ final boolean exists() { try { - return jrtfs.exists(getResolvedPath()); + return jrtfs.exists(this); } catch (IOException x) { } return false; @@ -839,17 +839,17 @@ final OutputStream newOutputStream(OpenOption... options) throws IOException { if (options.length == 0) { - return jrtfs.newOutputStream(getResolvedPath(), + return jrtfs.newOutputStream(this, CREATE_NEW, WRITE); } - return jrtfs.newOutputStream(getResolvedPath(), options); + return jrtfs.newOutputStream(this, options); } final void move(AbstractJrtPath target, CopyOption... options) throws IOException { if (this.jrtfs == target.jrtfs) { jrtfs.copyFile(true, - getResolvedPath(), target.getResolvedPath(), + this, target, options); } else { copyToTarget(target, options); @@ -861,7 +861,7 @@ throws IOException { if (this.jrtfs == target.jrtfs) { jrtfs.copyFile(false, - getResolvedPath(), target.getResolvedPath(), + this, target, options); } else { copyToTarget(target, options); @@ -901,7 +901,7 @@ // create directory or file target.createDirectory(); } else { - try (InputStream is = jrtfs.newInputStream(getResolvedPath()); OutputStream os = target.newOutputStream()) { + try (InputStream is = jrtfs.newInputStream(this); OutputStream os = target.newOutputStream()) { byte[] buf = new byte[8192]; int n; while ((n = is.read(buf)) != -1) { --- old/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java 2015-11-11 21:05:55.910122100 +0530 +++ new/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java 2015-11-11 21:05:55.363090900 +0530 @@ -39,10 +39,7 @@ final class JrtDirectoryStream implements DirectoryStream { private final AbstractJrtFileSystem jrtfs; - private final byte[] path; - // prefix to be used for children of this directory - // so that child path are reported relatively (if needed) - private final String childPrefix; + private final AbstractJrtPath dir; private final DirectoryStream.Filter filter; private volatile boolean isClosed; private volatile Iterator itr; @@ -51,22 +48,12 @@ DirectoryStream.Filter filter) throws IOException { this.jrtfs = jrtPath.getFileSystem(); - this.path = jrtPath.getResolvedPath(); + this.dir = jrtPath; // sanity check - if (!jrtfs.isDirectory(path, true)) { + if (!jrtfs.isDirectory(dir, true)) { throw new NotDirectoryException(jrtPath.toString()); } - // absolute path and does not have funky chars in front like /./java.base - if (jrtPath.isAbsolute() && (path.length == jrtPath.getPathLength())) { - childPrefix = null; - } else { - // cases where directory content needs to modified with prefix - // like ./java.base, /./java.base, java.base and so on. - String dirName = jrtPath.toString(); - int idx = dirName.indexOf(JrtFileSystem.getString(path).substring(1)); - childPrefix = dirName.substring(0, idx); - } this.filter = filter; } @@ -80,7 +67,7 @@ } try { - itr = jrtfs.iteratorOf(path, childPrefix); + itr = jrtfs.iteratorOf(dir); } catch (IOException e) { throw new IllegalStateException(e); } --- old/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java 2015-11-11 21:05:58.886292400 +0530 +++ new/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java 2015-11-11 21:05:58.266256900 +0530 @@ -293,26 +293,26 @@ } @Override - boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException { - Node n1 = checkNode(p1.getName()); - Node n2 = checkNode(p2.getName()); + boolean isSameFile(AbstractJrtPath jrtPath1, AbstractJrtPath jrtPath2) throws IOException { + Node n1 = checkNode(jrtPath1); + Node n2 = checkNode(jrtPath2); return n1 == n2; } @Override boolean isLink(AbstractJrtPath jrtPath) throws IOException { - return checkNode(jrtPath.getName()).isLink(); + return checkNode(jrtPath).isLink(); } @Override AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException { - String name = checkNode(jrtPath.getName()).resolveLink().getName(); + String name = checkNode(jrtPath).resolveLink().getName(); return toJrtExplodedPath(name); } @Override - AbstractJrtFileAttributes getFileAttributes(byte[] path, LinkOption... options) throws IOException { - Node node = checkNode(path); + AbstractJrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException { + Node node = checkNode(jrtPath); if (node.isLink() && followLinks(options)) { node = node.resolveLink(true); } @@ -320,9 +320,9 @@ } @Override - boolean exists(byte[] path) throws IOException { + boolean exists(AbstractJrtPath jrtPath) throws IOException { try { - checkNode(path); + checkNode(jrtPath); return true; } catch (NoSuchFileException nsfe) { return false; @@ -330,29 +330,37 @@ } @Override - boolean isDirectory(byte[] path, boolean resolveLinks) throws IOException { - Node node = checkNode(path); + boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException { + Node node = checkNode(jrtPath); return resolveLinks && node.isLink() ? node.resolveLink(true).isDirectory() : node.isDirectory(); } @Override - Iterator iteratorOf(byte[] path, String childPrefix) throws IOException { - Node node = checkNode(path).resolveLink(true); + Iterator iteratorOf(AbstractJrtPath dir) throws IOException { + Node node = checkNode(dir).resolveLink(true); if (!node.isDirectory()) { - throw new NotDirectoryException(getString(path)); + throw new NotDirectoryException(getString(dir.getName())); } - Function f = childPrefix == null - ? child -> toJrtExplodedPath(child.getName()) - : child -> toJrtExplodedPath(childPrefix + child.getName().substring(1)); - return node.getChildren().stream().map(f).collect(toList()).iterator(); + Function nodeToPath = + child -> dir.resolve( + toJrtExplodedPath(child.getName()). + getFileName()); + + return node.getChildren().stream(). + map(nodeToPath).collect(toList()). + iterator(); } @Override - byte[] getFileContent(byte[] path) throws IOException { - return checkNode(path).getContent(); + byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException { + return checkNode(jrtPath).getContent(); + } + + private Node checkNode(AbstractJrtPath jrtPath) throws IOException { + return checkNode(jrtPath.getResolvedPath()); } private Node checkNode(byte[] path) throws IOException { --- old/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java 2015-11-11 21:06:02.019471600 +0530 +++ new/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java 2015-11-11 21:06:01.466440000 +0530 @@ -36,6 +36,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.Function; import static java.util.stream.Collectors.toList; import jdk.internal.jimage.ImageReader; @@ -103,21 +104,21 @@ @Override boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException { ensureOpen(); - NodeAndImage n1 = findNode(p1.getName()); - NodeAndImage n2 = findNode(p2.getName()); - return n1.node.equals(n2.node); + Node node1 = findNode(p1); + Node node2 = findNode(p2); + return node1.equals(node2); } @Override boolean isLink(AbstractJrtPath jrtPath) throws IOException { - return checkNode(jrtPath.getName()).node.isLink(); + return checkNode(jrtPath).isLink(); } @Override AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException { - NodeAndImage ni = checkNode(jrtPath.getName()); - if (ni.node.isLink()) { - Node node = ni.node.resolveLink(); + Node node = checkNode(jrtPath); + if (node.isLink()) { + node = node.resolveLink(); return toJrtPath(node.getName().getBytesCopy()); } @@ -125,19 +126,19 @@ } @Override - JrtFileAttributes getFileAttributes(byte[] path, LinkOption... options) + JrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException { - NodeAndImage ni = checkNode(path); - if (ni.node.isLink() && followLinks(options)) { - return new JrtFileAttributes(ni.node.resolveLink(true)); + Node node = checkNode(jrtPath); + if (node.isLink() && followLinks(options)) { + return new JrtFileAttributes(node.resolveLink(true)); } - return new JrtFileAttributes(ni.node); + return new JrtFileAttributes(node); } @Override - boolean exists(byte[] path) throws IOException { + boolean exists(AbstractJrtPath jrtPath) throws IOException { try { - checkNode(path); + checkNode(jrtPath); } catch (NoSuchFileException exp) { return false; } @@ -145,39 +146,36 @@ } @Override - boolean isDirectory(byte[] path, boolean resolveLinks) + boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException { - NodeAndImage ni = checkNode(path); - return resolveLinks && ni.node.isLink() - ? ni.node.resolveLink(true).isDirectory() - : ni.node.isDirectory(); + Node node = checkNode(jrtPath); + return resolveLinks && node.isLink() + ? node.resolveLink(true).isDirectory() + : node.isDirectory(); } @Override - Iterator iteratorOf(byte[] path, String childPrefix) - throws IOException { - NodeAndImage ni = checkNode(path); - Node node = ni.node.resolveLink(true); - + Iterator iteratorOf(AbstractJrtPath jrtPath) throws IOException { + Node node = checkNode(jrtPath).resolveLink(true); if (!node.isDirectory()) { - throw new NotDirectoryException(getString(path)); + throw new NotDirectoryException(getString(jrtPath.getName())); } if (node.isRootDir()) { - return rootDirIterator(path, childPrefix); + return rootDirIterator(jrtPath); } else if (node.isModulesDir()) { - return modulesDirIterator(path, childPrefix); + return modulesDirIterator(jrtPath); } else if (node.isPackagesDir()) { - return packagesDirIterator(path, childPrefix); + return packagesDirIterator(jrtPath); } - return nodesToIterator(toJrtPath(path), childPrefix, node.getChildren()); + return nodesToIterator(jrtPath, node.getChildren()); } @Override - byte[] getFileContent(byte[] path) throws IOException { - final NodeAndImage ni = checkResource(path); - return ni.getResource(); + byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException { + final Node node = checkResource(jrtPath); + return bootImage.getResource(node); } // Implementation details below this point @@ -196,48 +194,32 @@ } } - private static class NodeAndImage { - - final Node node; - final ImageReader image; - - NodeAndImage(Node node, ImageReader image) { - this.node = node; - this.image = image; - } - - byte[] getResource() throws IOException { - return image.getResource(node); - } - } - - private NodeAndImage lookup(byte[] path) { - ImageReader image = bootImage; - Node node; + private Node lookup(byte[] path) { + Node node = null; try { node = bootImage.findNode(path); } catch (RuntimeException re) { throw new InvalidPathException(getString(path), re.toString()); } - return node != null ? new NodeAndImage(node, image) : null; + return node; } - private NodeAndImage lookupSymbolic(byte[] path) { + private Node 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) { + Node node = lookup(prefix); + if (node == null) { break; } - if (ni.node.isLink()) { - Node link = ni.node.resolveLink(true); + if (node.isLink()) { + Node link = 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); + node = lookup(resPathBytes); + return node != null ? node : lookupSymbolic(resPathBytes); } } } @@ -245,30 +227,42 @@ return null; } - private NodeAndImage findNode(byte[] path) throws IOException { - NodeAndImage ni = lookup(path); - if (ni == null) { - ni = lookupSymbolic(path); - if (ni == null) { + private Node findNode(AbstractJrtPath jrtPath) throws IOException { + return findNode(jrtPath.getResolvedPath()); + } + + private Node findNode(byte[] path) throws IOException { + Node node = lookup(path); + if (node == null) { + node = lookupSymbolic(path); + if (node == null) { throw new NoSuchFileException(getString(path)); } } - return ni; + return node; } - private NodeAndImage checkNode(byte[] path) throws IOException { + private Node checkNode(AbstractJrtPath jrtPath) throws IOException { + return checkNode(jrtPath.getResolvedPath()); + } + + private Node checkNode(byte[] path) throws IOException { ensureOpen(); return findNode(path); } - private NodeAndImage checkResource(byte[] path) throws IOException { - NodeAndImage ni = checkNode(path); - if (ni.node.isDirectory()) { + private Node checkResource(AbstractJrtPath jrtPath) throws IOException { + return checkResource(jrtPath.getResolvedPath()); + } + + private Node checkResource(byte[] path) throws IOException { + Node node = checkNode(path); + if (node.isDirectory()) { throw new FileSystemException(getString(path) + " is a directory"); } - assert ni.node.isResource() : "resource node expected here"; - return ni; + assert node.isResource() : "resource node expected here"; + return node; } private JrtPath toJrtPath(String path) { @@ -279,52 +273,54 @@ 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 Iterator nodesToIterator(AbstractJrtPath dir, List childNodes) { + Function nodeToPath = + child -> dir.resolve( + toJrtPath(child.getNameString()).getFileName()); + return childNodes.stream(). + map(nodeToPath).collect(toList()). + iterator(); } private List rootChildren; - private synchronized void initRootChildren(byte[] path) { + private synchronized void initRootChildren(AbstractJrtPath jrtPath) throws IOException { if (rootChildren == null) { rootChildren = new ArrayList<>(); - rootChildren.addAll(bootImage.findNode(path).getChildren()); + rootChildren.addAll(findNode(jrtPath).getChildren()); } } - private Iterator rootDirIterator(byte[] path, String childPrefix) throws IOException { - initRootChildren(path); - return nodesToIterator(rootPath, childPrefix, rootChildren); + private Iterator rootDirIterator(AbstractJrtPath jrtPath) throws IOException { + initRootChildren(jrtPath); + return nodesToIterator(jrtPath, rootChildren); } private List modulesChildren; - private synchronized void initModulesChildren(byte[] path) { + private synchronized void initModulesChildren(AbstractJrtPath jrtPath) throws IOException { if (modulesChildren == null) { modulesChildren = new ArrayList<>(); - modulesChildren.addAll(bootImage.findNode(path).getChildren()); + modulesChildren.addAll(findNode(jrtPath).getChildren()); } } - private Iterator modulesDirIterator(byte[] path, String childPrefix) throws IOException { - initModulesChildren(path); - return nodesToIterator(new JrtPath(this, path), childPrefix, modulesChildren); + private Iterator modulesDirIterator(AbstractJrtPath jrtPath) throws IOException { + initModulesChildren(jrtPath); + return nodesToIterator(jrtPath, modulesChildren); } private List packagesChildren; - private synchronized void initPackagesChildren(byte[] path) { + private synchronized void initPackagesChildren(AbstractJrtPath jrtPath) throws IOException { if (packagesChildren == null) { packagesChildren = new ArrayList<>(); - packagesChildren.addAll(bootImage.findNode(path).getChildren()); + packagesChildren.addAll(findNode(jrtPath).getChildren()); } } - private Iterator packagesDirIterator(byte[] path, String childPrefix) throws IOException { - initPackagesChildren(path); - return nodesToIterator(new JrtPath(this, path), childPrefix, packagesChildren); + private Iterator packagesDirIterator(AbstractJrtPath jrtPath) throws IOException { + initPackagesChildren(jrtPath); + return nodesToIterator(jrtPath, packagesChildren); } } --- old/test/jdk/internal/jrtfs/Basic.java 2015-11-11 21:06:04.969640300 +0530 +++ new/test/jdk/internal/jrtfs/Basic.java 2015-11-11 21:06:04.433609700 +0530 @@ -28,6 +28,7 @@ */ import java.io.InputStream; +import java.io.IOException; import java.io.DataInputStream; import java.nio.file.DirectoryStream; import java.nio.file.InvalidPathException; @@ -583,4 +584,43 @@ } assertTrue(ipe != null); } + + @DataProvider(name="packagesLinkedDirs") + private Object[][] packagesLinkedDirs() { + return new Object[][] { + { "/packages/java.lang/java.base/java/lang/ref" }, + { "/./packages/java.lang/java.base/java/lang/ref" }, + { "packages/java.lang/java.base/java/lang/ref" }, + { "/packages/../packages/java.lang/java.base/java/lang/ref" }, + { "/packages/java.lang/java.base/java/util/zip" }, + { "/./packages/java.lang/java.base/java/util/zip" }, + { "packages/java.lang/java.base/java/util/zip" }, + { "/packages/../packages/java.lang/java.base/java/util/zip" }, + { "/packages/com.oracle/java.xml.ws/com" }, + { "/./packages/com.oracle/java.xml.ws/com" }, + { "packages/com.oracle/java.xml.ws/com" }, + { "/packages/../packages/com.oracle/java.xml.ws/com" } + }; + } + + // @bug 8141521: jrt file system's DirectoryStream reports child paths + // with wrong paths for directories under /packages + @Test(dataProvider = "packagesLinkedDirs") + public void dirStreamPackagesDirTest(String dirName) throws IOException { + FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); + Path path = fs.getPath(dirName); + + int childCount = 0, dirPrefixOkayCount = 0; + try (DirectoryStream dirStream = Files.newDirectoryStream(path)) { + for (Path child : dirStream) { + childCount++; + if (child.toString().startsWith(dirName)) { + dirPrefixOkayCount++; + } + } + } + + assertTrue(childCount != 0); + assertEquals(dirPrefixOkayCount, childCount); + } }