< prev index next >

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

Print this page




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package jdk.internal.jrtfs;
  26 
  27 import java.io.ByteArrayInputStream;
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.io.OutputStream;
  31 import java.nio.ByteBuffer;
  32 import java.nio.channels.*;
  33 import java.nio.charset.Charset;
  34 import java.nio.file.AccessMode;
  35 import java.nio.file.ClosedFileSystemException;
  36 import java.nio.file.CopyOption;

  37 import java.nio.file.FileStore;
  38 import java.nio.file.FileSystem;
  39 import java.nio.file.FileSystemException;
  40 import java.nio.file.FileSystemNotFoundException;
  41 import java.nio.file.Files;
  42 import java.nio.file.NoSuchFileException;
  43 import java.nio.file.NotDirectoryException;
  44 import java.nio.file.OpenOption;
  45 import java.nio.file.Path;
  46 import java.nio.file.PathMatcher;
  47 import java.nio.file.ReadOnlyFileSystemException;
  48 import java.nio.file.StandardCopyOption;
  49 import java.nio.file.StandardOpenOption;
  50 import java.nio.file.WatchService;
  51 import java.nio.file.attribute.FileAttribute;
  52 import java.nio.file.attribute.FileTime;
  53 import java.nio.file.attribute.UserPrincipalLookupService;
  54 import java.nio.file.spi.FileSystemProvider;
  55 import java.security.AccessController;
  56 import java.security.PrivilegedActionException;
  57 import java.security.PrivilegedExceptionAction;
  58 import java.util.ArrayList;
  59 import java.util.Arrays;
  60 import java.util.Collections;
  61 import java.util.HashSet;
  62 import java.util.Iterator;
  63 import java.util.List;
  64 import java.util.Map;
  65 import java.util.Set;

  66 import java.util.regex.Pattern;
  67 import java.util.stream.Collectors;
  68 import jdk.internal.jimage.ImageReader;
  69 import jdk.internal.jimage.ImageReader.Node;
  70 import jdk.internal.jimage.UTF8String;
  71 
  72 /**
  73  * A FileSystem built on System jimage files.
  74  */
  75 class JrtFileSystem extends FileSystem {
  76     private static final Charset UTF_8 = Charset.forName("UTF-8");

  77     private final JrtFileSystemProvider provider;
  78     // System image readers
  79     private ImageReader bootImage;
  80     private ImageReader extImage;
  81     private ImageReader appImage;
  82     // root path
  83     private final JrtPath rootPath;
  84     private volatile boolean isOpen;
  85 
  86     private static void checkExists(Path path) {
  87         if (Files.notExists(path)) {
  88             throw new FileSystemNotFoundException(path.toString());
  89         }
  90     }
  91 
  92     // open a .jimage and build directory structure
  93     private static ImageReader openImage(Path path) throws IOException {
  94         ImageReader image = ImageReader.open(path.toString());
  95         image.getRootDirectory();
  96         return image;
  97     }
  98 
  99     JrtFileSystem(JrtFileSystemProvider provider,
 100             Map<String, ?> env)
 101             throws IOException {
 102         this.provider = provider;
 103         checkExists(SystemImages.bootImagePath);
 104         checkExists(SystemImages.extImagePath);
 105         checkExists(SystemImages.appImagePath);
 106 
 107         // open image files
 108         this.bootImage = openImage(SystemImages.bootImagePath);
 109         this.extImage = openImage(SystemImages.extImagePath);
 110         this.appImage = openImage(SystemImages.appImagePath);
 111 
 112         rootPath = new JrtPath(this, new byte[]{'/'});

 113         isOpen = true;
 114     }
 115 
 116     @Override
 117     public FileSystemProvider provider() {
 118         return provider;
 119     }
 120 
 121     @Override
 122     public String getSeparator() {
 123         return "/";
 124     }
 125 
 126     @Override
 127     public boolean isOpen() {
 128         return isOpen;
 129     }
 130 
 131     @Override
 132     public void close() throws IOException {
 133         cleanup();
 134     }
 135 
 136     @Override
 137     protected void finalize() {
 138         try {
 139             cleanup();
 140         } catch (IOException ignored) {}
 141     }
 142 
 143     // clean up this file system - called from finalize and close
 144     private void cleanup() throws IOException {
 145         if (!isOpen) {
 146             return;
 147         }
 148 
 149         synchronized(this) {
 150             isOpen = false;
 151 
 152             // close all image readers and null out
 153             bootImage.close();
 154             extImage.close();
 155             appImage.close();
 156             bootImage = null;

 157             extImage = null;

 158             appImage = null;
 159         }
 160     }
 161 
 162     private void ensureOpen() throws IOException {
 163         if (!isOpen) {
 164             throw new ClosedFileSystemException();
 165         }
 166     }
 167 
 168     @Override
 169     public boolean isReadOnly() {
 170         return true;
 171     }
 172 
 173     private ReadOnlyFileSystemException readOnly() {
 174         return new ReadOnlyFileSystemException();
 175     }
 176 
 177     @Override


 272         return name.getBytes(UTF_8);
 273     }
 274 
 275     static String getString(byte[] name) {
 276         return new String(name, UTF_8);
 277     }
 278 
 279     private static class NodeAndImage {
 280         final Node node;
 281         final ImageReader image;
 282 
 283         NodeAndImage(Node node, ImageReader image) {
 284             this.node = node; this.image = image;
 285         }
 286 
 287         byte[] getResource() throws IOException {
 288             return image.getResource(node);
 289         }
 290     }
 291 
 292     private NodeAndImage findNode(byte[] path) throws IOException {
 293         ImageReader image = bootImage;
 294         Node node = bootImage.findNode(path);

 295         if (node == null) {
 296             image = extImage;
 297             node = extImage.findNode(path);

 298         }
 299         if (node == null) {
 300             image = appImage;
 301             node = appImage.findNode(path);





















 302         }
 303         if (node == null || node.isHidden()) {










 304             throw new NoSuchFileException(getString(path));
 305         }
 306         return new NodeAndImage(node, image);

 307     }
 308 
 309     private NodeAndImage checkNode(byte[] path) throws IOException {
 310         ensureOpen();
 311         return findNode(path);
 312     }
 313 
 314     private NodeAndImage checkResource(byte[] path) throws IOException {
 315         NodeAndImage ni = checkNode(path);
 316         if (ni.node.isDirectory()) {
 317             throw new FileSystemException(getString(path) + " is a directory");
 318         }
 319 
 320         assert ni.node.isResource() : "resource node expected here";
 321         return ni;
 322     }
 323 















 324     // package private helpers
 325     JrtFileAttributes getFileAttributes(byte[] path)
 326             throws IOException {
 327         NodeAndImage ni = checkNode(path);



 328         return new JrtFileAttributes(ni.node);
 329     }
 330 
 331     void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
 332             throws IOException {
 333         throw readOnly();
 334     }
 335 
 336     boolean exists(byte[] path) throws IOException {
 337         ensureOpen();
 338         try {
 339             findNode(path);
 340         } catch (NoSuchFileException exp) {
 341             return false;
 342         }
 343         return true;
 344     }
 345 
 346     boolean isDirectory(byte[] path)
 347             throws IOException {
 348         ensureOpen();
 349         NodeAndImage ni = checkNode(path);
 350         return ni.node.isDirectory();


 351     }
 352 
 353     JrtPath toJrtPath(String path) {
 354         return toJrtPath(getBytes(path));
 355     }
 356 
 357     JrtPath toJrtPath(byte[] path) {
 358         return new JrtPath(this, path);
 359     }
 360 






















 361     /**
 362      * returns the list of child paths of the given directory "path"
 363      *
 364      * @param path name of the directory whose content is listed
 365      * @param childPrefix prefix added to returned children names - may be null
 366               in which case absolute child paths are returned
 367      * @return iterator for child paths of the given directory path
 368      */
 369     Iterator<Path> iteratorOf(byte[] path, String childPrefix)
 370             throws IOException {
 371         NodeAndImage ni = checkNode(path);
 372         if (!ni.node.isDirectory()) {


 373             throw new NotDirectoryException(getString(path));
 374         }
 375 
 376         if (ni.node.isRootDir()) {
 377             return rootDirIterator(path, childPrefix);





















 378         }
 379 
 380         return nodesToIterator(toJrtPath(path), childPrefix, ni.node.getChildren());



 381     }
 382 
 383     private Iterator<Path> nodesToIterator(Path path, String childPrefix, List<Node> childNodes) {
 384         List<Path> childPaths;
 385         if (childPrefix == null) {
 386             childPaths = childNodes.stream()
 387                 .filter(Node::isVisible)
 388                 .map(child -> toJrtPath(child.getNameString()))
 389                 .collect(Collectors.toCollection(ArrayList::new));
 390         } else {
 391             childPaths = childNodes.stream()
 392                 .filter(Node::isVisible)
 393                 .map(child -> toJrtPath(childPrefix + child.getNameString().substring(1)))
 394                 .collect(Collectors.toCollection(ArrayList::new));
 395         }
 396         return childPaths.iterator();
 397     }
 398 
 399     private List<Node> rootChildren;
 400     private static void addRootDirContent(List<Node> dest, List<Node> src) {
 401         for (Node n : src) {
 402             // only module directories at the top level. Filter other stuff!
 403             if (n.isModuleDir()) {
 404                 dest.add(n);








 405             }
 406         }
 407     }
 408 

 409     private synchronized void initRootChildren(byte[] path) {
 410         if (rootChildren == null) {
 411             rootChildren = new ArrayList<>();
 412             addRootDirContent(rootChildren, bootImage.findNode(path).getChildren());
 413             addRootDirContent(rootChildren, extImage.findNode(path).getChildren());
 414             addRootDirContent(rootChildren, appImage.findNode(path).getChildren());
 415         }
 416     }
 417 
 418     private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException {
 419         initRootChildren(path);
 420         return nodesToIterator(rootPath, childPrefix, rootChildren);
 421     }
 422 





























 423     void createDirectory(byte[] dir, FileAttribute<?>... attrs)
 424             throws IOException {
 425         throw readOnly();
 426     }
 427 
 428     void copyFile(boolean deletesrc, byte[] src, byte[] dst, CopyOption... options)
 429             throws IOException {
 430         throw readOnly();
 431     }
 432 
 433     public void deleteFile(byte[] path, boolean failIfNotExists)
 434             throws IOException {
 435         throw readOnly();
 436     }
 437 
 438     OutputStream newOutputStream(byte[] path, OpenOption... options)
 439             throws IOException {
 440         throw readOnly();
 441     }
 442 




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package jdk.internal.jrtfs;
  26 
  27 import java.io.ByteArrayInputStream;
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.io.OutputStream;
  31 import java.nio.ByteBuffer;
  32 import java.nio.channels.*;
  33 import java.nio.charset.Charset;

  34 import java.nio.file.ClosedFileSystemException;
  35 import java.nio.file.CopyOption;
  36 import java.nio.file.LinkOption;
  37 import java.nio.file.FileStore;
  38 import java.nio.file.FileSystem;
  39 import java.nio.file.FileSystemException;
  40 import java.nio.file.FileSystemNotFoundException;
  41 import java.nio.file.Files;
  42 import java.nio.file.NoSuchFileException;
  43 import java.nio.file.NotDirectoryException;
  44 import java.nio.file.OpenOption;
  45 import java.nio.file.Path;
  46 import java.nio.file.PathMatcher;
  47 import java.nio.file.ReadOnlyFileSystemException;

  48 import java.nio.file.StandardOpenOption;
  49 import java.nio.file.WatchService;
  50 import java.nio.file.attribute.FileAttribute;
  51 import java.nio.file.attribute.FileTime;
  52 import java.nio.file.attribute.UserPrincipalLookupService;
  53 import java.nio.file.spi.FileSystemProvider;
  54 import java.util.concurrent.ConcurrentHashMap;


  55 import java.util.ArrayList;
  56 import java.util.Arrays;
  57 import java.util.Collections;
  58 import java.util.HashSet;
  59 import java.util.Iterator;
  60 import java.util.List;
  61 import java.util.Map;
  62 import java.util.Set;
  63 import java.util.function.Function;
  64 import java.util.regex.Pattern;
  65 import static java.util.stream.Collectors.toList;
  66 import jdk.internal.jimage.ImageReader;
  67 import jdk.internal.jimage.ImageReader.Node;
  68 import jdk.internal.jimage.UTF8String;
  69 
  70 /**
  71  * A FileSystem built on System jimage files.
  72  */
  73 class JrtFileSystem extends FileSystem {
  74     private static final Charset UTF_8 = Charset.forName("UTF-8");
  75 
  76     private final JrtFileSystemProvider provider;
  77     // System image readers
  78     private ImageReader bootImage;
  79     private ImageReader extImage;
  80     private ImageReader appImage;
  81     // root path
  82     private final JrtPath rootPath;
  83     private volatile boolean isOpen;
  84 
  85     private static void checkExists(Path path) {
  86         if (Files.notExists(path)) {
  87             throw new FileSystemNotFoundException(path.toString());
  88         }
  89     }
  90 
  91     // open a .jimage and build directory structure
  92     private static ImageReader openImage(Path path) throws IOException {
  93         ImageReader image = ImageReader.open(path.toString());
  94         image.getRootDirectory();
  95         return image;
  96     }
  97 
  98     JrtFileSystem(JrtFileSystemProvider provider,
  99             Map<String, ?> env)
 100             throws IOException {
 101         this.provider = provider;
 102         checkExists(SystemImages.bootImagePath);
 103         checkExists(SystemImages.extImagePath);
 104         checkExists(SystemImages.appImagePath);
 105 
 106         // open image files
 107         this.bootImage = openImage(SystemImages.bootImagePath);
 108         this.extImage = openImage(SystemImages.extImagePath);
 109         this.appImage = openImage(SystemImages.appImagePath);
 110 
 111         byte[] root = new byte[] { '/' };
 112         rootPath = new JrtPath(this, root);
 113         isOpen = true;
 114     }
 115 
 116     @Override
 117     public FileSystemProvider provider() {
 118         return provider;
 119     }
 120 
 121     @Override
 122     public String getSeparator() {
 123         return "/";
 124     }
 125 
 126     @Override
 127     public boolean isOpen() {
 128         return isOpen;
 129     }
 130 
 131     @Override
 132     public void close() throws IOException {
 133         cleanup();
 134     }
 135 
 136     @Override
 137     protected void finalize() {
 138         try {
 139             cleanup();
 140         } catch (IOException ignored) {}
 141     }
 142 
 143     // clean up this file system - called from finalize and close
 144     private void cleanup() throws IOException {
 145         if (!isOpen) {
 146             return;
 147         }
 148 
 149         synchronized(this) {
 150             isOpen = false;
 151 
 152             // close all image reader and null out
 153             bootImage.close();


 154             bootImage = null;
 155             extImage.close();
 156             extImage = null;
 157             appImage.close();
 158             appImage = null;
 159         }
 160     }
 161 
 162     private void ensureOpen() throws IOException {
 163         if (!isOpen) {
 164             throw new ClosedFileSystemException();
 165         }
 166     }
 167 
 168     @Override
 169     public boolean isReadOnly() {
 170         return true;
 171     }
 172 
 173     private ReadOnlyFileSystemException readOnly() {
 174         return new ReadOnlyFileSystemException();
 175     }
 176 
 177     @Override


 272         return name.getBytes(UTF_8);
 273     }
 274 
 275     static String getString(byte[] name) {
 276         return new String(name, UTF_8);
 277     }
 278 
 279     private static class NodeAndImage {
 280         final Node node;
 281         final ImageReader image;
 282 
 283         NodeAndImage(Node node, ImageReader image) {
 284             this.node = node; this.image = image;
 285         }
 286 
 287         byte[] getResource() throws IOException {
 288             return image.getResource(node);
 289         }
 290     }
 291 
 292     private NodeAndImage lookup(byte[] path) {

 293         Node node = bootImage.findNode(path);
 294         ImageReader image = bootImage;
 295         if (node == null) {

 296             node = extImage.findNode(path);
 297             image = extImage;
 298         }
 299         if (node == null) {

 300             node = appImage.findNode(path);
 301             image = appImage;
 302         }
 303         return node != null? new NodeAndImage(node, image) : null;
 304     }
 305 
 306     private NodeAndImage lookupSymbolic(byte[] path) {
 307         for (int i = 1; i < path.length; i++) {
 308             if (path[i] == (byte)'/') {
 309                 byte[] prefix = Arrays.copyOfRange(path, 0, i);
 310                 NodeAndImage ni = lookup(prefix);
 311                 if (ni == null) {
 312                     break;
 313                 }
 314 
 315                 if (ni.node.isLink()) {
 316                     Node link = ni.node.resolveLink(true);
 317                     // resolved symbolic path concatenated to the rest of the path
 318                     UTF8String resPath = link.getName().concat(new UTF8String(path, i));
 319                     byte[] resPathBytes = resPath.getBytesCopy();
 320                     ni = lookup(resPathBytes);
 321                     return ni != null? ni : lookupSymbolic(resPathBytes);
 322                 }
 323             }
 324         }
 325 
 326         return null;
 327     }
 328 
 329     private NodeAndImage findNode(byte[] path) throws IOException {
 330         NodeAndImage ni = lookup(path);
 331         if (ni == null) {
 332             ni = lookupSymbolic(path);
 333             if (ni == null) {
 334                 throw new NoSuchFileException(getString(path));
 335             }
 336         }
 337         return ni;
 338     }
 339 
 340     private NodeAndImage checkNode(byte[] path) throws IOException {
 341         ensureOpen();
 342         return findNode(path);
 343     }
 344 
 345     private NodeAndImage checkResource(byte[] path) throws IOException {
 346         NodeAndImage ni = checkNode(path);
 347         if (ni.node.isDirectory()) {
 348             throw new FileSystemException(getString(path) + " is a directory");
 349         }
 350 
 351         assert ni.node.isResource() : "resource node expected here";
 352         return ni;
 353     }
 354 
 355     static boolean followLinks(LinkOption... options) {
 356         if (options != null) {
 357             for (LinkOption lo : options) {
 358                 if (lo == LinkOption.NOFOLLOW_LINKS) {
 359                     return false;
 360                 } else if (lo == null) {
 361                     throw new NullPointerException();
 362                 } else {
 363                     throw new AssertionError("should not reach here");
 364                 }
 365             }
 366         }
 367         return true;
 368     }
 369 
 370     // package private helpers
 371     JrtFileAttributes getFileAttributes(byte[] path, LinkOption... options)
 372             throws IOException {
 373         NodeAndImage ni = checkNode(path);
 374         if (ni.node.isLink() && followLinks(options)) {
 375             return new JrtFileAttributes(ni.node.resolveLink(true));
 376         }
 377         return new JrtFileAttributes(ni.node);
 378     }
 379 
 380     void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
 381             throws IOException {
 382         throw readOnly();
 383     }
 384 
 385     boolean exists(byte[] path) throws IOException {
 386         ensureOpen();
 387         try {
 388             findNode(path);
 389         } catch (NoSuchFileException exp) {
 390             return false;
 391         }
 392         return true;
 393     }
 394 
 395     boolean isDirectory(byte[] path, boolean resolveLinks)
 396             throws IOException {
 397         ensureOpen();
 398         NodeAndImage ni = checkNode(path);
 399         return resolveLinks && ni.node.isLink()?
 400             ni.node.resolveLink(true).isDirectory() :
 401             ni.node.isDirectory();
 402     }
 403 
 404     JrtPath toJrtPath(String path) {
 405         return toJrtPath(getBytes(path));
 406     }
 407 
 408     JrtPath toJrtPath(byte[] path) {
 409         return new JrtPath(this, path);
 410     }
 411 
 412     boolean isSameFile(JrtPath p1, JrtPath p2) throws IOException {
 413         NodeAndImage n1 = findNode(p1.getName());
 414         NodeAndImage n2 = findNode(p2.getName());
 415         return n1.node.equals(n2.node);
 416     }
 417 
 418     boolean isLink(JrtPath jrtPath) throws IOException {
 419         return findNode(jrtPath.getName()).node.isLink();
 420     }
 421 
 422     JrtPath resolveLink(JrtPath jrtPath) throws IOException {
 423         NodeAndImage ni = findNode(jrtPath.getName());
 424         if (ni.node.isLink()) {
 425             Node node = ni.node.resolveLink();
 426             return toJrtPath(node.getName().getBytesCopy());
 427         }
 428 
 429         return jrtPath;
 430     }
 431 
 432     private Map<UTF8String, List<Node>> packagesTreeChildren = new ConcurrentHashMap<>();
 433 
 434     /**
 435      * returns the list of child paths of the given directory "path"
 436      *
 437      * @param path name of the directory whose content is listed
 438      * @param childPrefix prefix added to returned children names - may be null
 439               in which case absolute child paths are returned
 440      * @return iterator for child paths of the given directory path
 441      */
 442     Iterator<Path> iteratorOf(byte[] path, String childPrefix)
 443             throws IOException {
 444         NodeAndImage ni = checkNode(path);
 445         Node node = ni.node.resolveLink(true);
 446 
 447         if (!node.isDirectory()) {
 448             throw new NotDirectoryException(getString(path));
 449         }
 450 
 451         if (node.isRootDir()) {
 452             return rootDirIterator(path, childPrefix);
 453         } else if (node.isModulesDir()) {
 454             return modulesDirIterator(path, childPrefix);
 455         } else if (node.isPackagesDir()) {
 456             return packagesDirIterator(path, childPrefix);
 457         } else if (node.getNameString().startsWith("/packages/")) {
 458             if (ni.image != appImage) {
 459                 UTF8String name = node.getName();
 460                 List<Node> children = packagesTreeChildren.get(name);
 461                 if (children != null) {
 462                     return nodesToIterator(toJrtPath(path), childPrefix, children);
 463                 }
 464 
 465                 children = new ArrayList<>();
 466                 children.addAll(node.getChildren());
 467                 Node tmpNode = null;
 468                 // found in boot
 469                 if (ni.image == bootImage) {
 470                     tmpNode = extImage.findNode(name);
 471                     if (tmpNode != null) {
 472                         children.addAll(tmpNode.getChildren());
 473                     }
 474                 }
 475 
 476                 // found in ext
 477                 tmpNode = appImage.findNode(name);
 478                 if (tmpNode != null) {
 479                     children.addAll(tmpNode.getChildren());
 480                 }
 481 
 482                 packagesTreeChildren.put(name, children);
 483                 return nodesToIterator(toJrtPath(path), childPrefix, children);










 484             }

 485         }
 486 
 487         return nodesToIterator(toJrtPath(path), childPrefix, node.getChildren());
 488     }
 489 
 490     private Iterator<Path> nodesToIterator(Path path, String childPrefix, List<Node> childNodes) {
 491         Function<Node, Path> f = childPrefix == null
 492                 ? child -> toJrtPath(child.getNameString())
 493                 : child -> toJrtPath(childPrefix + child.getNameString().substring(1));
 494          return childNodes.stream().map(f).collect(toList()).iterator();
 495     }
 496 
 497     private void addRootDirContent(List<Node> children) {
 498         for (Node child : children) {
 499             if (!(child.isModulesDir() || child.isPackagesDir())) {
 500                 rootChildren.add(child);
 501             }
 502         }
 503     }
 504 
 505     private List<Node> rootChildren;
 506     private synchronized void initRootChildren(byte[] path) {
 507         if (rootChildren == null) {
 508             rootChildren = new ArrayList<>();
 509             rootChildren.addAll(bootImage.findNode(path).getChildren());
 510             addRootDirContent(extImage.findNode(path).getChildren());
 511             addRootDirContent(appImage.findNode(path).getChildren());
 512         }
 513     }
 514 
 515     private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException {
 516         initRootChildren(path);
 517         return nodesToIterator(rootPath, childPrefix, rootChildren);
 518     }
 519 
 520     private List<Node> modulesChildren;
 521     private synchronized void initModulesChildren(byte[] path) {
 522         if (modulesChildren == null) {
 523             modulesChildren = new ArrayList<>();
 524             modulesChildren.addAll(bootImage.findNode(path).getChildren());
 525             modulesChildren.addAll(appImage.findNode(path).getChildren());
 526             modulesChildren.addAll(extImage.findNode(path).getChildren());
 527         }
 528     }
 529 
 530     private Iterator<Path> modulesDirIterator(byte[] path, String childPrefix) throws IOException {
 531         initModulesChildren(path);
 532         return nodesToIterator(new JrtPath(this, path), childPrefix, modulesChildren);
 533     }
 534 
 535     private List<Node> packagesChildren;
 536     private synchronized void initPackagesChildren(byte[] path) {
 537         if (packagesChildren == null) {
 538             packagesChildren = new ArrayList<>();
 539             packagesChildren.addAll(bootImage.findNode(path).getChildren());
 540             packagesChildren.addAll(extImage.findNode(path).getChildren());
 541             packagesChildren.addAll(appImage.findNode(path).getChildren());
 542         }
 543     }
 544     private Iterator<Path> packagesDirIterator(byte[] path, String childPrefix) throws IOException {
 545         initPackagesChildren(path);
 546         return nodesToIterator(new JrtPath(this, path), childPrefix, packagesChildren);
 547     }
 548 
 549     void createDirectory(byte[] dir, FileAttribute<?>... attrs)
 550             throws IOException {
 551         throw readOnly();
 552     }
 553 
 554     void copyFile(boolean deletesrc, byte[] src, byte[] dst, CopyOption... options)
 555             throws IOException {
 556         throw readOnly();
 557     }
 558 
 559     public void deleteFile(byte[] path, boolean failIfNotExists)
 560             throws IOException {
 561         throw readOnly();
 562     }
 563 
 564     OutputStream newOutputStream(byte[] path, OpenOption... options)
 565             throws IOException {
 566         throw readOnly();
 567     }
 568 


< prev index next >