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 void copy(Path src, Path target, CopyOption... options) 150 throws IOException 151 { 152 toJrtPath(src).copy(toJrtPath(target), options); 153 } 154 155 @Override 156 public void createDirectory(Path path, FileAttribute<?>... attrs) 157 throws IOException 158 { 159 toJrtPath(path).createDirectory(attrs); 160 } 161 162 @Override 163 public final void delete(Path path) throws IOException { 164 toJrtPath(path).delete(); 165 } 166 167 @Override 168 @SuppressWarnings("unchecked") 169 public <V extends FileAttributeView> V 170 getFileAttributeView(Path path, Class<V> type, LinkOption... options) 171 { 172 return JrtFileAttributeView.get(toJrtPath(path), type); 173 } 174 175 @Override 176 public FileStore getFileStore(Path path) throws IOException { 177 return toJrtPath(path).getFileStore(); 178 } 179 180 @Override 181 public boolean isHidden(Path path) { 182 return toJrtPath(path).isHidden(); 183 } 184 185 @Override 186 public boolean isSameFile(Path path, Path other) throws IOException { 187 return toJrtPath(path).isSameFile(other); 188 } 189 190 @Override 191 public void move(Path src, Path target, CopyOption... options) 192 throws IOException 193 { 194 toJrtPath(src).move(toJrtPath(target), options); 195 } 196 197 @Override 198 public AsynchronousFileChannel newAsynchronousFileChannel(Path path, 199 Set<? extends OpenOption> options, 200 ExecutorService exec, 201 FileAttribute<?>... attrs) 202 throws IOException 203 { 204 throw new UnsupportedOperationException(); 205 } 206 207 @Override 208 public SeekableByteChannel newByteChannel(Path path, 209 Set<? extends OpenOption> options, 210 FileAttribute<?>... attrs) 211 throws IOException 212 { 213 return toJrtPath(path).newByteChannel(options, attrs); 214 } 215 216 @Override 217 public DirectoryStream<Path> newDirectoryStream( 218 Path path, Filter<? super Path> filter) throws IOException 219 { 220 return toJrtPath(path).newDirectoryStream(filter); 221 } 222 223 @Override 224 public FileChannel newFileChannel(Path path, 225 Set<? extends OpenOption> options, 226 FileAttribute<?>... attrs) 227 throws IOException 228 { 229 return toJrtPath(path).newFileChannel(options, attrs); 230 } 231 232 @Override 233 public InputStream newInputStream(Path path, OpenOption... options) 234 throws IOException 235 { 236 return toJrtPath(path).newInputStream(options); 237 } 238 239 @Override 240 public OutputStream newOutputStream(Path path, OpenOption... options) 241 throws IOException 242 { 243 return toJrtPath(path).newOutputStream(options); 244 } 245 246 @Override 247 @SuppressWarnings("unchecked") // Cast to A 248 public <A extends BasicFileAttributes> A 249 readAttributes(Path path, Class<A> type, LinkOption... options) 250 throws IOException 251 { 252 if (type == BasicFileAttributes.class || type == JrtFileAttributes.class) 253 return (A)toJrtPath(path).getAttributes(); 254 return null; 255 } 256 257 @Override 258 public Map<String, Object> 259 readAttributes(Path path, String attribute, LinkOption... options) 260 throws IOException 261 { 262 return toJrtPath(path).readAttributes(attribute, options); 263 } 264 265 @Override 266 public void setAttribute(Path path, String attribute, 267 Object value, LinkOption... options) 268 throws IOException 269 { 270 toJrtPath(path).setAttribute(attribute, value, options); 271 } 272 }