< prev index next >

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

Print this page




  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.IOException;
  28 import java.nio.file.LinkOption;
  29 import java.nio.file.FileSystemException;
  30 import java.nio.file.InvalidPathException;
  31 import java.nio.file.NoSuchFileException;
  32 import java.nio.file.NotDirectoryException;
  33 import java.nio.file.Path;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.Iterator;
  37 import java.util.List;
  38 import java.util.Map;

  39 import java.util.function.Function;
  40 import static java.util.stream.Collectors.toList;
  41 import jdk.internal.jimage.ImageReader;
  42 import jdk.internal.jimage.ImageReader.Node;
  43 import jdk.internal.jimage.UTF8String;
  44 
  45 /**
  46  * jrt file system implementation built on System jimage files.
  47  */
  48 class JrtFileSystem extends AbstractJrtFileSystem {
  49 
  50     // System image reader
  51     private ImageReader bootImage;
  52     // root path
  53     private final JrtPath rootPath;
  54     private volatile boolean isOpen;
  55 
  56     // open a .jimage and build directory structure
  57     private static ImageReader openImage(Path path) throws IOException {
  58         ImageReader image = ImageReader.open(path.toString());


  86     }
  87 
  88     @Override
  89     protected void finalize() throws Throwable {
  90         try {
  91             cleanup();
  92         } catch (IOException ignored) {
  93         }
  94         super.finalize();
  95     }
  96 
  97     // AbstractJrtFileSystem method implementations
  98     @Override
  99     JrtPath getRootPath() {
 100         return rootPath;
 101     }
 102 
 103     @Override
 104     boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException {
 105         ensureOpen();
 106         NodeAndImage n1 = findNode(p1.getName());
 107         NodeAndImage n2 = findNode(p2.getName());
 108         return n1.node.equals(n2.node);
 109     }
 110 
 111     @Override
 112     boolean isLink(AbstractJrtPath jrtPath) throws IOException {
 113         return checkNode(jrtPath.getName()).node.isLink();
 114     }
 115 
 116     @Override
 117     AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException {
 118         NodeAndImage ni = checkNode(jrtPath.getName());
 119         if (ni.node.isLink()) {
 120             Node node = ni.node.resolveLink();
 121             return toJrtPath(node.getName().getBytesCopy());
 122         }
 123 
 124         return jrtPath;
 125     }
 126 
 127     @Override
 128     JrtFileAttributes getFileAttributes(byte[] path, LinkOption... options)
 129             throws IOException {
 130         NodeAndImage ni = checkNode(path);
 131         if (ni.node.isLink() && followLinks(options)) {
 132             return new JrtFileAttributes(ni.node.resolveLink(true));
 133         }
 134         return new JrtFileAttributes(ni.node);
 135     }
 136 
 137     @Override
 138     boolean exists(byte[] path) throws IOException {
 139         try {
 140             checkNode(path);
 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 {




 260         ensureOpen();
 261         return findNode(path);
 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 }


  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.IOException;
  28 import java.nio.file.LinkOption;
  29 import java.nio.file.FileSystemException;
  30 import java.nio.file.InvalidPathException;
  31 import java.nio.file.NoSuchFileException;
  32 import java.nio.file.NotDirectoryException;
  33 import java.nio.file.Path;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.Iterator;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Objects;
  40 import java.util.function.Function;
  41 import static java.util.stream.Collectors.toList;
  42 import jdk.internal.jimage.ImageReader;
  43 import jdk.internal.jimage.ImageReader.Node;
  44 import jdk.internal.jimage.UTF8String;
  45 
  46 /**
  47  * jrt file system implementation built on System jimage files.
  48  */
  49 class JrtFileSystem extends AbstractJrtFileSystem {
  50 
  51     // System image reader
  52     private ImageReader bootImage;
  53     // root path
  54     private final JrtPath rootPath;
  55     private volatile boolean isOpen;
  56 
  57     // open a .jimage and build directory structure
  58     private static ImageReader openImage(Path path) throws IOException {
  59         ImageReader image = ImageReader.open(path.toString());


  87     }
  88 
  89     @Override
  90     protected void finalize() throws Throwable {
  91         try {
  92             cleanup();
  93         } catch (IOException ignored) {
  94         }
  95         super.finalize();
  96     }
  97 
  98     // AbstractJrtFileSystem method implementations
  99     @Override
 100     JrtPath getRootPath() {
 101         return rootPath;
 102     }
 103 
 104     @Override
 105     boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException {
 106         ensureOpen();
 107         Node node1 = findNode(p1);
 108         Node node2 = findNode(p2);
 109         return node1.equals(node2);
 110     }
 111 
 112     @Override
 113     boolean isLink(AbstractJrtPath jrtPath) throws IOException {
 114         return checkNode(jrtPath).isLink();
 115     }
 116 
 117     @Override
 118     AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException {
 119         Node node = checkNode(jrtPath);
 120         if (node.isLink()) {
 121             node = node.resolveLink();
 122             return toJrtPath(node.getName().getBytesCopy());
 123         }
 124 
 125         return jrtPath;
 126     }
 127 
 128     @Override
 129     JrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options)
 130             throws IOException {
 131         Node node = checkNode(jrtPath);
 132         if (node.isLink() && followLinks(options)) {
 133             return new JrtFileAttributes(node.resolveLink(true));
 134         }
 135         return new JrtFileAttributes(node);
 136     }
 137 
 138     @Override
 139     boolean exists(AbstractJrtPath jrtPath) throws IOException {
 140         try {
 141             checkNode(jrtPath);
 142         } catch (NoSuchFileException exp) {
 143             return false;
 144         }
 145         return true;
 146     }
 147 
 148     @Override
 149     boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks)
 150             throws IOException {
 151         Node node = checkNode(jrtPath);
 152         return resolveLinks && node.isLink()
 153                 ? node.resolveLink(true).isDirectory()
 154                 : node.isDirectory();
 155     }
 156 
 157     @Override
 158     Iterator<Path> iteratorOf(AbstractJrtPath jrtPath) throws IOException {
 159         Node node = checkNode(jrtPath).resolveLink(true);



 160         if (!node.isDirectory()) {
 161             throw new NotDirectoryException(getString(jrtPath.getName()));
 162         }
 163 
 164         if (node.isRootDir()) {
 165             return rootDirIterator(jrtPath);
 166         } else if (node.isModulesDir()) {
 167             return modulesDirIterator(jrtPath);
 168         } else if (node.isPackagesDir()) {
 169             return packagesDirIterator(jrtPath);
 170         }
 171 
 172         return nodesToIterator(jrtPath, node.getChildren());
 173     }
 174 
 175     @Override
 176     byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException {
 177         final Node node = checkResource(jrtPath);
 178         return bootImage.getResource(node);
 179     }
 180 
 181     // Implementation details below this point
 182     // clean up this file system - called from finalize and close
 183     private void cleanup() throws IOException {
 184         if (!isOpen) {
 185             return;
 186         }
 187 
 188         synchronized (this) {
 189             isOpen = false;
 190 
 191             // close all image reader and null out
 192             bootImage.close();
 193             bootImage = null;
 194         }
 195     }
 196 
 197     private Node lookup(byte[] path) {
 198         Node node = null;
















 199         try {
 200             node = bootImage.findNode(path);
 201         } catch (RuntimeException re) {
 202             throw new InvalidPathException(getString(path), re.toString());
 203         }
 204         return node;
 205     }
 206 
 207     private Node lookupSymbolic(byte[] path) {
 208         for (int i = 1; i < path.length; i++) {
 209             if (path[i] == (byte) '/') {
 210                 byte[] prefix = Arrays.copyOfRange(path, 0, i);
 211                 Node node = lookup(prefix);
 212                 if (node == null) {
 213                     break;
 214                 }
 215 
 216                 if (node.isLink()) {
 217                     Node link = node.resolveLink(true);
 218                     // resolved symbolic path concatenated to the rest of the path
 219                     UTF8String resPath = link.getName().concat(new UTF8String(path, i));
 220                     byte[] resPathBytes = resPath.getBytesCopy();
 221                     node = lookup(resPathBytes);
 222                     return node != null ? node : lookupSymbolic(resPathBytes);
 223                 }
 224             }
 225         }
 226 
 227         return null;
 228     }
 229 
 230     private Node findNode(AbstractJrtPath jrtPath) throws IOException {
 231         return findNode(jrtPath.getResolvedPath());
 232     }
 233 
 234     private Node findNode(byte[] path) throws IOException {
 235         Node node = lookup(path);
 236         if (node == null) {
 237             node = lookupSymbolic(path);
 238             if (node == null) {
 239                 throw new NoSuchFileException(getString(path));
 240             }
 241         }
 242         return node;
 243     }
 244 
 245     private Node checkNode(AbstractJrtPath jrtPath) throws IOException {
 246         return checkNode(jrtPath.getResolvedPath());
 247     }
 248 
 249     private Node checkNode(byte[] path) throws IOException {
 250         ensureOpen();
 251         return findNode(path);
 252     }
 253 
 254     private Node checkResource(AbstractJrtPath jrtPath) throws IOException {
 255         return checkResource(jrtPath.getResolvedPath());
 256     }
 257 
 258     private Node checkResource(byte[] path) throws IOException {
 259         Node node = checkNode(path);
 260         if (node.isDirectory()) {
 261             throw new FileSystemException(getString(path) + " is a directory");
 262         }
 263 
 264         assert node.isResource() : "resource node expected here";
 265         return node;
 266     }
 267 
 268     private JrtPath toJrtPath(String path) {
 269         return toJrtPath(getBytes(path));
 270     }
 271 
 272     private JrtPath toJrtPath(byte[] path) {
 273         return new JrtPath(this, path);
 274     }
 275 
 276     private Iterator<Path> nodesToIterator(AbstractJrtPath dir, List<Node> childNodes) {
 277         Function<Node, Path> nodeToPath =
 278             child -> dir.resolve(
 279                 toJrtPath(child.getNameString()).getFileName());
 280         return childNodes.stream().
 281                 map(nodeToPath).collect(toList()).
 282                 iterator();
 283     }
 284 
 285     private List<Node> rootChildren;
 286 
 287     private synchronized void initRootChildren(AbstractJrtPath jrtPath) throws IOException {
 288         if (rootChildren == null) {
 289             rootChildren = new ArrayList<>();
 290             rootChildren.addAll(findNode(jrtPath).getChildren());
 291         }
 292     }
 293 
 294     private Iterator<Path> rootDirIterator(AbstractJrtPath jrtPath) throws IOException {
 295         initRootChildren(jrtPath);
 296         return nodesToIterator(jrtPath, rootChildren);
 297     }
 298 
 299     private List<Node> modulesChildren;
 300 
 301     private synchronized void initModulesChildren(AbstractJrtPath jrtPath) throws IOException {
 302         if (modulesChildren == null) {
 303             modulesChildren = new ArrayList<>();
 304             modulesChildren.addAll(findNode(jrtPath).getChildren());
 305         }
 306     }
 307 
 308     private Iterator<Path> modulesDirIterator(AbstractJrtPath jrtPath) throws IOException {
 309         initModulesChildren(jrtPath);
 310         return nodesToIterator(jrtPath, modulesChildren);
 311     }
 312 
 313     private List<Node> packagesChildren;
 314 
 315     private synchronized void initPackagesChildren(AbstractJrtPath jrtPath) throws IOException {
 316         if (packagesChildren == null) {
 317             packagesChildren = new ArrayList<>();
 318             packagesChildren.addAll(findNode(jrtPath).getChildren());
 319         }
 320     }
 321 
 322     private Iterator<Path> packagesDirIterator(AbstractJrtPath jrtPath) throws IOException {
 323         initPackagesChildren(jrtPath);
 324         return nodesToIterator(jrtPath, packagesChildren);
 325     }
 326 }
< prev index next >