1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 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 26 package jdk.internal.jrtfs; 27 28 import java.io.*; 29 import java.nio.channels.*; 30 import java.nio.file.*; 31 import java.nio.file.DirectoryStream.Filter; 32 import java.nio.file.attribute.*; 33 import java.nio.file.spi.FileSystemProvider; 34 import java.net.URI; 35 import java.net.URISyntaxException; 36 import java.util.HashMap; 37 import java.util.Map; 38 import java.util.Set; 39 import java.util.concurrent.ExecutorService; 40 41 public final class JrtFileSystemProvider extends FileSystemProvider { 42 private volatile FileSystem theFileSystem; 43 44 public JrtFileSystemProvider() { } 45 46 @Override 47 public String getScheme() { 48 return "jrt"; 49 } 50 51 /** 52 * Need FilePermission ${java.home}/-", "read" to create or get jrt:/ 53 */ 54 private void checkPermission() { 55 SecurityManager sm = System.getSecurityManager(); 56 if (sm != null) { 57 String home = SystemImages.RUNTIME_HOME; 58 FilePermission perm = 59 new FilePermission(home + File.separator + "-", "read"); 60 sm.checkPermission(perm); 61 } 62 } 63 64 private void checkUri(URI uri) { 65 if (!uri.getScheme().equalsIgnoreCase(getScheme())) 66 throw new IllegalArgumentException("URI does not match this provider"); 67 if (uri.getAuthority() != null) 68 throw new IllegalArgumentException("Authority component present"); 69 if (uri.getPath() == null) 70 throw new IllegalArgumentException("Path component is undefined"); 71 if (!uri.getPath().equals("/")) 72 throw new IllegalArgumentException("Path component should be '/'"); 73 if (uri.getQuery() != null) 74 throw new IllegalArgumentException("Query component present"); 75 if (uri.getFragment() != null) 76 throw new IllegalArgumentException("Fragment component present"); 77 } 78 79 @Override 80 public FileSystem newFileSystem(URI uri, Map<String, ?> env) 81 throws IOException 82 { 83 checkPermission(); 84 checkUri(uri); 85 return new JrtFileSystem(this, env); 86 } 87 88 @Override 89 public Path getPath(URI uri) { 90 checkPermission(); 91 if (!uri.getScheme().equalsIgnoreCase(getScheme())) 92 throw new IllegalArgumentException("URI does not match this provider"); 93 if (uri.getAuthority() != null) 94 throw new IllegalArgumentException("Authority component present"); 95 if (uri.getQuery() != null) 96 throw new IllegalArgumentException("Query component present"); 97 if (uri.getFragment() != null) 98 throw new IllegalArgumentException("Fragment component present"); 99 String path = uri.getPath(); 100 if (path == null || path.charAt(0) != '/') 101 throw new IllegalArgumentException("Invalid path component"); 102 return getTheFileSystem().getPath(path); 103 } 104 105 private FileSystem getTheFileSystem() { 106 checkPermission(); 107 FileSystem fs = this.theFileSystem; 108 if (fs == null) { 109 synchronized (this) { 110 fs = this.theFileSystem; 111 if (fs == null) { 112 try { 113 this.theFileSystem = fs = new JrtFileSystem(this, null) { 114 @Override public void close() { 115 throw new UnsupportedOperationException(); 116 } 117 }; 118 } catch (IOException ioe) { 119 throw new InternalError(ioe); 120 } 121 } 122 } 123 } 124 return fs; 125 } 126 127 @Override 128 public FileSystem getFileSystem(URI uri) { 129 checkPermission(); 130 checkUri(uri); 131 return getTheFileSystem(); 132 } 133 134 // Checks that the given file is a JrtPath 135 static final JrtPath toJrtPath(Path path) { 136 if (path == null) 137 throw new NullPointerException(); 138 if (!(path instanceof JrtPath)) 139 throw new ProviderMismatchException(); 140 return (JrtPath)path; 141 } 142 143 @Override 144 public void checkAccess(Path path, AccessMode... modes) throws IOException { 145 toJrtPath(path).checkAccess(modes); 146 } 147 148 @Override 149 public Path readSymbolicLink(Path link) throws IOException { 150 return toJrtPath(link).readSymbolicLink(); 151 } 152 153 @Override 154 public void copy(Path src, Path target, CopyOption... options) 155 throws IOException 156 { 157 toJrtPath(src).copy(toJrtPath(target), options); 158 } 159 160 @Override 161 public void createDirectory(Path path, FileAttribute<?>... attrs) 162 throws IOException 163 { 164 toJrtPath(path).createDirectory(attrs); 165 } 166 167 @Override 168 public final void delete(Path path) throws IOException { 169 toJrtPath(path).delete(); 170 } 171 172 @Override 173 @SuppressWarnings("unchecked") 174 public <V extends FileAttributeView> V 175 getFileAttributeView(Path path, Class<V> type, LinkOption... options) 176 { 177 return JrtFileAttributeView.get(toJrtPath(path), type, options); 178 } 179 180 @Override 181 public FileStore getFileStore(Path path) throws IOException { 182 return toJrtPath(path).getFileStore(); 183 } 184 185 @Override 186 public boolean isHidden(Path path) { 187 return toJrtPath(path).isHidden(); 188 } 189 190 @Override 191 public boolean isSameFile(Path path, Path other) throws IOException { 192 return toJrtPath(path).isSameFile(other); 193 } 194 195 @Override 196 public void move(Path src, Path target, CopyOption... options) 197 throws IOException 198 { 199 toJrtPath(src).move(toJrtPath(target), options); 200 } 201 202 @Override 203 public AsynchronousFileChannel newAsynchronousFileChannel(Path path, 204 Set<? extends OpenOption> options, 205 ExecutorService exec, 206 FileAttribute<?>... attrs) 207 throws IOException 208 { 209 throw new UnsupportedOperationException(); 210 } 211 212 @Override 213 public SeekableByteChannel newByteChannel(Path path, 214 Set<? extends OpenOption> options, 215 FileAttribute<?>... attrs) 216 throws IOException 217 { 218 return toJrtPath(path).newByteChannel(options, attrs); 219 } 220 221 @Override 222 public DirectoryStream<Path> newDirectoryStream( 223 Path path, Filter<? super Path> filter) throws IOException 224 { 225 return toJrtPath(path).newDirectoryStream(filter); 226 } 227 228 @Override 229 public FileChannel newFileChannel(Path path, 230 Set<? extends OpenOption> options, 231 FileAttribute<?>... attrs) 232 throws IOException 233 { 234 return toJrtPath(path).newFileChannel(options, attrs); 235 } 236 237 @Override 238 public InputStream newInputStream(Path path, OpenOption... options) 239 throws IOException 240 { 241 return toJrtPath(path).newInputStream(options); 242 } 243 244 @Override 245 public OutputStream newOutputStream(Path path, OpenOption... options) 246 throws IOException 247 { 248 return toJrtPath(path).newOutputStream(options); 249 } 250 251 @Override 252 @SuppressWarnings("unchecked") // Cast to A 253 public <A extends BasicFileAttributes> A 254 readAttributes(Path path, Class<A> type, LinkOption... options) 255 throws IOException 256 { 257 if (type == BasicFileAttributes.class || type == JrtFileAttributes.class) 258 return (A)toJrtPath(path).getAttributes(options); 259 return null; 260 } 261 262 @Override 263 public Map<String, Object> 264 readAttributes(Path path, String attribute, LinkOption... options) 265 throws IOException 266 { 267 return toJrtPath(path).readAttributes(attribute, options); 268 } 269 270 @Override 271 public void setAttribute(Path path, String attribute, 272 Object value, LinkOption... options) 273 throws IOException 274 { 275 toJrtPath(path).setAttribute(attribute, value, options); 276 } 277 }