< prev index next >

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

Print this page




 141         } catch (NoSuchFileException exp) {
 142             return false;
 143         }
 144         return true;
 145     }
 146 
 147     @Override
 148     boolean isDirectory(byte[] path, boolean resolveLinks)
 149             throws IOException {
 150         NodeAndImage ni = checkNode(path);
 151         return resolveLinks && ni.node.isLink()
 152                 ? ni.node.resolveLink(true).isDirectory()
 153                 : ni.node.isDirectory();
 154     }
 155 
 156     @Override
 157     Iterator<Path> iteratorOf(byte[] path, String childPrefix)
 158             throws IOException {
 159         NodeAndImage ni = checkNode(path);
 160         Node node = ni.node.resolveLink(true);
 161 
 162         if (!node.isDirectory()) {
 163             throw new NotDirectoryException(getString(path));
 164         }
 165 
 166         if (node.isRootDir()) {
 167             return rootDirIterator(path, childPrefix);
 168         } else if (node.isModulesDir()) {
 169             return modulesDirIterator(path, childPrefix);
 170         } else if (node.isPackagesDir()) {
 171             return packagesDirIterator(path, childPrefix);
 172         }
 173 
 174         return nodesToIterator(toJrtPath(path), childPrefix, node.getChildren());
 175     }
 176 
 177     @Override
 178     byte[] getFileContent(byte[] path) throws IOException {
 179         final NodeAndImage ni = checkResource(path);
 180         return ni.getResource();
 181     }
 182 
 183     // Implementation details below this point
 184     // clean up this file system - called from finalize and close
 185     private void cleanup() throws IOException {
 186         if (!isOpen) {
 187             return;
 188         }
 189 
 190         synchronized (this) {
 191             isOpen = false;
 192 
 193             // close all image reader and null out
 194             bootImage.close();
 195             bootImage = null;
 196         }
 197     }
 198 
 199     private static class NodeAndImage {
 200 
 201         final Node node;
 202         final ImageReader image;


 203 
 204         NodeAndImage(Node node, ImageReader image) {
 205             this.node = node;
 206             this.image = image;

 207         }
 208 
 209         byte[] getResource() throws IOException {
 210             return image.getResource(node);
 211         }
 212     }
 213 
 214     private NodeAndImage lookup(byte[] path) {




 215         ImageReader image = bootImage;
 216         Node node;
 217         try {
 218             node = bootImage.findNode(path);
 219         } catch (RuntimeException re) {
 220             throw new InvalidPathException(getString(path), re.toString());
 221         }
 222         return node != null ? new NodeAndImage(node, image) : null;
 223     }
 224 
 225     private NodeAndImage lookupSymbolic(byte[] path) {
 226         for (int i = 1; i < path.length; i++) {
 227             if (path[i] == (byte) '/') {
 228                 byte[] prefix = Arrays.copyOfRange(path, 0, i);
 229                 NodeAndImage ni = lookup(prefix);
 230                 if (ni == null) {
 231                     break;
 232                 }
 233 
 234                 if (ni.node.isLink()) {
 235                     Node link = ni.node.resolveLink(true);
 236                     // resolved symbolic path concatenated to the rest of the path
 237                     UTF8String resPath = link.getName().concat(new UTF8String(path, i));
 238                     byte[] resPathBytes = resPath.getBytesCopy();
 239                     ni = lookup(resPathBytes);
 240                     return ni != null ? ni : lookupSymbolic(resPathBytes);
 241                 }
 242             }
 243         }
 244 
 245         return null;
 246     }
 247 
 248     private NodeAndImage findNode(byte[] path) throws IOException {
 249         NodeAndImage ni = lookup(path);
 250         if (ni == null) {
 251             ni = lookupSymbolic(path);
 252             if (ni == null) {
 253                 throw new NoSuchFileException(getString(path));
 254             }
 255         }
 256         return ni;
 257     }
 258 
 259     private NodeAndImage checkNode(byte[] path) throws IOException {


 262     }
 263 
 264     private NodeAndImage checkResource(byte[] path) throws IOException {
 265         NodeAndImage ni = checkNode(path);
 266         if (ni.node.isDirectory()) {
 267             throw new FileSystemException(getString(path) + " is a directory");
 268         }
 269 
 270         assert ni.node.isResource() : "resource node expected here";
 271         return ni;
 272     }
 273 
 274     private JrtPath toJrtPath(String path) {
 275         return toJrtPath(getBytes(path));
 276     }
 277 
 278     private JrtPath toJrtPath(byte[] path) {
 279         return new JrtPath(this, path);
 280     }
 281 
 282     private Iterator<Path> nodesToIterator(Path path, String childPrefix, List<Node> childNodes) {
 283         Function<Node, Path> f = childPrefix == null
 284                 ? child -> toJrtPath(child.getNameString())
 285                 : child -> toJrtPath(childPrefix + child.getNameString().substring(1));
 286         return childNodes.stream().map(f).collect(toList()).iterator();



















 287     }
 288 
 289     private List<Node> rootChildren;
 290 
 291     private synchronized void initRootChildren(byte[] path) {
 292         if (rootChildren == null) {
 293             rootChildren = new ArrayList<>();
 294             rootChildren.addAll(bootImage.findNode(path).getChildren());
 295         }
 296     }
 297 
 298     private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException {
 299         initRootChildren(path);
 300         return nodesToIterator(rootPath, childPrefix, rootChildren);
 301     }
 302 
 303     private List<Node> modulesChildren;
 304 
 305     private synchronized void initModulesChildren(byte[] path) {
 306         if (modulesChildren == null) {
 307             modulesChildren = new ArrayList<>();
 308             modulesChildren.addAll(bootImage.findNode(path).getChildren());
 309         }
 310     }
 311 
 312     private Iterator<Path> modulesDirIterator(byte[] path, String childPrefix) throws IOException {
 313         initModulesChildren(path);
 314         return nodesToIterator(new JrtPath(this, path), childPrefix, modulesChildren);
 315     }
 316 
 317     private List<Node> packagesChildren;
 318 
 319     private synchronized void initPackagesChildren(byte[] path) {
 320         if (packagesChildren == null) {
 321             packagesChildren = new ArrayList<>();
 322             packagesChildren.addAll(bootImage.findNode(path).getChildren());
 323         }
 324     }
 325 
 326     private Iterator<Path> packagesDirIterator(byte[] path, String childPrefix) throws IOException {
 327         initPackagesChildren(path);
 328         return nodesToIterator(new JrtPath(this, path), childPrefix, packagesChildren);
 329     }
 330 }


 141         } catch (NoSuchFileException exp) {
 142             return false;
 143         }
 144         return true;
 145     }
 146 
 147     @Override
 148     boolean isDirectory(byte[] path, boolean resolveLinks)
 149             throws IOException {
 150         NodeAndImage ni = checkNode(path);
 151         return resolveLinks && ni.node.isLink()
 152                 ? ni.node.resolveLink(true).isDirectory()
 153                 : ni.node.isDirectory();
 154     }
 155 
 156     @Override
 157     Iterator<Path> iteratorOf(byte[] path, String childPrefix)
 158             throws IOException {
 159         NodeAndImage ni = checkNode(path);
 160         Node node = ni.node.resolveLink(true);

 161         if (!node.isDirectory()) {
 162             throw new NotDirectoryException(getString(path));
 163         }
 164 
 165         if (node.isRootDir()) {
 166             return rootDirIterator(path, childPrefix);
 167         } else if (node.isModulesDir()) {
 168             return modulesDirIterator(path, childPrefix);
 169         } else if (node.isPackagesDir()) {
 170             return packagesDirIterator(path, childPrefix);
 171         }
 172 
 173         return nodesToIterator(toJrtPath(path), ni.symLink, childPrefix, node.getChildren());
 174     }
 175 
 176     @Override
 177     byte[] getFileContent(byte[] path) throws IOException {
 178         final NodeAndImage ni = checkResource(path);
 179         return ni.getResource();
 180     }
 181 
 182     // Implementation details below this point
 183     // clean up this file system - called from finalize and close
 184     private void cleanup() throws IOException {
 185         if (!isOpen) {
 186             return;
 187         }
 188 
 189         synchronized (this) {
 190             isOpen = false;
 191 
 192             // close all image reader and null out
 193             bootImage.close();
 194             bootImage = null;
 195         }
 196     }
 197 
 198     private static class NodeAndImage {
 199 
 200         final Node node;
 201         final ImageReader image;
 202         // was there a symlink somewhere while resolving this Node from name?
 203         final boolean symLink;
 204 
 205         NodeAndImage(Node node, ImageReader image, boolean symLink) {
 206             this.node = node;
 207             this.image = image;
 208             this.symLink = symLink;
 209         }
 210 
 211         byte[] getResource() throws IOException {
 212             return image.getResource(node);
 213         }
 214     }
 215 
 216     private NodeAndImage lookup(byte[] path) {
 217         return lookup(path, false);
 218     }
 219 
 220     private NodeAndImage lookup(byte[] path, boolean symLink) {
 221         ImageReader image = bootImage;
 222         Node node;
 223         try {
 224             node = bootImage.findNode(path);
 225         } catch (RuntimeException re) {
 226             throw new InvalidPathException(getString(path), re.toString());
 227         }
 228         return node != null ? new NodeAndImage(node, image, symLink) : null;
 229     }
 230 
 231     private NodeAndImage lookupSymbolic(byte[] path) {
 232         for (int i = 1; i < path.length; i++) {
 233             if (path[i] == (byte) '/') {
 234                 byte[] prefix = Arrays.copyOfRange(path, 0, i);
 235                 NodeAndImage ni = lookup(prefix, true);
 236                 if (ni == null) {
 237                     break;
 238                 }
 239 
 240                 if (ni.node.isLink()) {
 241                     Node link = ni.node.resolveLink(true);
 242                     // resolved symbolic path concatenated to the rest of the path
 243                     UTF8String resPath = link.getName().concat(new UTF8String(path, i));
 244                     byte[] resPathBytes = resPath.getBytesCopy();
 245                     ni = lookup(resPathBytes, true);
 246                     return ni != null ? ni : lookupSymbolic(resPathBytes);
 247                 }
 248             }
 249         }
 250 
 251         return null;
 252     }
 253 
 254     private NodeAndImage findNode(byte[] path) throws IOException {
 255         NodeAndImage ni = lookup(path);
 256         if (ni == null) {
 257             ni = lookupSymbolic(path);
 258             if (ni == null) {
 259                 throw new NoSuchFileException(getString(path));
 260             }
 261         }
 262         return ni;
 263     }
 264 
 265     private NodeAndImage checkNode(byte[] path) throws IOException {


 268     }
 269 
 270     private NodeAndImage checkResource(byte[] path) throws IOException {
 271         NodeAndImage ni = checkNode(path);
 272         if (ni.node.isDirectory()) {
 273             throw new FileSystemException(getString(path) + " is a directory");
 274         }
 275 
 276         assert ni.node.isResource() : "resource node expected here";
 277         return ni;
 278     }
 279 
 280     private JrtPath toJrtPath(String path) {
 281         return toJrtPath(getBytes(path));
 282     }
 283 
 284     private JrtPath toJrtPath(byte[] path) {
 285         return new JrtPath(this, path);
 286     }
 287 
 288     private static final int MODULES_LEN = "/modules/".length();
 289     private static final int PACKAGES_LEN = "/packages/".length();
 290 
 291     private Iterator<Path> nodesToIterator(Path path, boolean symLink, String childPrefix, List<Node> childNodes) {
 292         // Function that maps name -> Path (adding prefix if needed)
 293         Function<String, Path> prefixHandler = childPrefix == null
 294                 ? childStr -> toJrtPath(childStr)
 295                 : childStr -> toJrtPath(childPrefix + childStr.substring(1));
 296 
 297         // function to map Node->name
 298         Function<Node, String> nodeHandler;
 299         if (symLink) {
 300             // There was a symlink in the parent dir! We need to make sure that the child paths
 301             // use the appropriate parent prefix in the name.
 302             String parentStr = path.toAbsolutePath().toString();
 303             // "/packages/java.lang/java.base/java/" -> "/packages/java.lang/"
 304             String parentPrefix = parentStr.substring(0, 1 + parentStr.indexOf('/', PACKAGES_LEN));
 305 
 306             nodeHandler = node -> parentPrefix + node.getNameString().substring(MODULES_LEN);
 307         } else {
 308             nodeHandler = Node::getNameString;
 309         }
 310 
 311         return childNodes.stream().map(nodeHandler.andThen(prefixHandler)).collect(toList()).iterator();
 312     }
 313 
 314     private List<Node> rootChildren;
 315 
 316     private synchronized void initRootChildren(byte[] path) {
 317         if (rootChildren == null) {
 318             rootChildren = new ArrayList<>();
 319             rootChildren.addAll(bootImage.findNode(path).getChildren());
 320         }
 321     }
 322 
 323     private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException {
 324         initRootChildren(path);
 325         return nodesToIterator(rootPath, false, childPrefix, rootChildren);
 326     }
 327 
 328     private List<Node> modulesChildren;
 329 
 330     private synchronized void initModulesChildren(byte[] path) {
 331         if (modulesChildren == null) {
 332             modulesChildren = new ArrayList<>();
 333             modulesChildren.addAll(bootImage.findNode(path).getChildren());
 334         }
 335     }
 336 
 337     private Iterator<Path> modulesDirIterator(byte[] path, String childPrefix) throws IOException {
 338         initModulesChildren(path);
 339         return nodesToIterator(new JrtPath(this, path), false, childPrefix, modulesChildren);
 340     }
 341 
 342     private List<Node> packagesChildren;
 343 
 344     private synchronized void initPackagesChildren(byte[] path) {
 345         if (packagesChildren == null) {
 346             packagesChildren = new ArrayList<>();
 347             packagesChildren.addAll(bootImage.findNode(path).getChildren());
 348         }
 349     }
 350 
 351     private Iterator<Path> packagesDirIterator(byte[] path, String childPrefix) throws IOException {
 352         initPackagesChildren(path);
 353         return nodesToIterator(new JrtPath(this, path), false, childPrefix, packagesChildren);
 354     }
 355 }
< prev index next >