1 /* 2 * Copyright (c) 2007, 2009, 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 java.nio.file.spi; 27 28 import java.nio.file.*; 29 import java.nio.file.attribute.FileAttribute; 30 import java.nio.channels.*; 31 import java.net.URI; 32 import java.util.*; 33 import java.util.concurrent.ExecutorService; 34 import java.security.AccessController; 35 import java.security.PrivilegedAction; 36 import java.io.IOException; 37 38 /** 39 * Service-provider class for file systems. 40 * 41 * <p> A file system provider is a concrete implementation of this class that 42 * implements the abstract methods defined by this class. A provider is 43 * identified by a {@code URI} {@link #getScheme() scheme}. The default provider 44 * is identified by the URI scheme "file". It creates the {@link FileSystem} that 45 * provides access to the file systems accessible to the Java virtual machine. 46 * The {@link FileSystems} class defines how file system providers are located 47 * and loaded. The default provider is typically a system-default provider but 48 * may be overridden if the system property {@code 49 * java.nio.file.spi.DefaultFileSystemProvider} is set. In that case, the 50 * provider has a one argument constructor whose formal parameter type is {@code 51 * FileSystemProvider}. All other providers have a zero argument constructor 52 * that initializes the provider. 53 * 54 * <p> A provider is a factory for one or more {@link FileSystem} instances. Each 55 * file system is identified by a {@code URI} where the URI's scheme matches 56 * the provider's {@link #getScheme scheme}. The default file system, for example, 57 * is identified by the URI {@code "file:///"}. A memory-based file system, 58 * for example, may be identified by a URI such as {@code "memory:///?name=logfs"}. 59 * The {@link #newFileSystem newFileSystem} method may be used to create a file 60 * system, and the {@link #getFileSystem getFileSystem} method may be used to 61 * obtain a reference to an existing file system created by the provider. Where 62 * a provider is the factory for a single file system then it is provider dependent 63 * if the file system is created when the provider is initialized, or later when 64 * the {@code newFileSystem} method is invoked. In the case of the default 65 * provider, the {@code FileSystem} is created when the provider is initialized. 66 * 67 * <p> In addition to file systems, a provider is also a factory for {@link 68 * FileChannel} and {@link AsynchronousFileChannel} channels. The {@link 69 * #newFileChannel newFileChannel} and {@link #newAsynchronousFileChannel 70 * AsynchronousFileChannel} methods are defined to open or create files, returning 71 * a channel to access the file. These methods are invoked by static factory 72 * methods defined in the {@link java.nio.channels} package. 73 * 74 * <p> All of the methods in this class are safe for use by multiple concurrent 75 * threads. 76 * 77 * @since 1.7 78 */ 79 80 public abstract class FileSystemProvider { 81 // lock using when loading providers 82 private static final Object lock = new Object(); 83 84 // installed providers 85 private static volatile List<FileSystemProvider> installedProviders; 86 87 // used to avoid recursive loading of instaled providers 88 private static boolean loadingProviders = false; 89 90 private static Void checkPermission() { 91 SecurityManager sm = System.getSecurityManager(); 92 if (sm != null) 93 sm.checkPermission(new RuntimePermission("fileSystemProvider")); 94 return null; 95 } 96 private FileSystemProvider(Void ignore) { } 97 98 /** 99 * Initializes a new instance of this class. 100 * 101 * <p> During construction a provider may safely access files associated 102 * with the default provider but care needs to be taken to avoid circular 103 * loading of other installed providers. If circular loading of installed 104 * providers is detected then an unspecified error is thrown. 105 * 106 * @throws SecurityException 107 * If a security manager has been installed and it denies 108 * {@link RuntimePermission}<tt>("fileSystemProvider")</tt> 109 */ 110 protected FileSystemProvider() { 111 this(checkPermission()); 112 } 113 114 // loads all installed providers 115 private static List<FileSystemProvider> loadInstalledProviders() { 116 List<FileSystemProvider> list = new ArrayList<FileSystemProvider>(); 117 118 ServiceLoader<FileSystemProvider> sl = ServiceLoader 119 .load(FileSystemProvider.class, ClassLoader.getSystemClassLoader()); 120 121 // ServiceConfigurationError may be throw here 122 for (FileSystemProvider provider: sl) { 123 String scheme = provider.getScheme(); 124 125 // add to list if the provider is not "file" and isn't a duplicate 126 if (!scheme.equalsIgnoreCase("file")) { 127 boolean found = false; 128 for (FileSystemProvider p: list) { 129 if (p.getScheme().equalsIgnoreCase(scheme)) { 130 found = true; 131 break; 132 } 133 } 134 if (!found) { 135 list.add(provider); 136 } 137 } 138 } 139 return list; 140 } 141 142 /** 143 * Returns a list of the installed file system providers. 144 * 145 * <p> The first invocation of this method causes the default provider to be 146 * initialized (if not already initialized) and loads any other installed 147 * providers as described by the {@link FileSystems} class. 148 * 149 * @return An unmodifiable list of the installed file system providers. The 150 * list contains at least one element, that is the default file 151 * system provider 152 * 153 * @throws ServiceConfigurationError 154 * When an error occurs while loading a service provider 155 */ 156 public static List<FileSystemProvider> installedProviders() { 157 if (installedProviders == null) { 158 // ensure default provider is initialized 159 FileSystemProvider defaultProvider = FileSystems.getDefault().provider(); 160 161 synchronized (lock) { 162 if (installedProviders == null) { 163 if (loadingProviders) { 164 throw new Error("Circular loading of installed providers detected"); 165 } 166 loadingProviders = true; 167 168 List<FileSystemProvider> list = AccessController 169 .doPrivileged(new PrivilegedAction<List<FileSystemProvider>>() { 170 @Override 171 public List<FileSystemProvider> run() { 172 return loadInstalledProviders(); 173 }}); 174 175 // insert the default provider at the start of the list 176 list.add(0, defaultProvider); 177 178 installedProviders = Collections.unmodifiableList(list); 179 } 180 } 181 } 182 return installedProviders; 183 } 184 185 /** 186 * Returns the URI scheme that identifies this provider. 187 * 188 * @return The URI scheme 189 */ 190 public abstract String getScheme(); 191 192 /** 193 * Constructs a new {@code FileSystem} object identified by a URI. This 194 * method is invoked by the {@link FileSystems#newFileSystem(URI,Map)} 195 * method to open a new file system identified by a URI. 196 * 197 * <p> The {@code uri} parameter is an absolute, hierarchical URI, with a 198 * scheme equal (without regard to case) to the scheme supported by this 199 * provider. The exact form of the URI is highly provider dependent. The 200 * {@code env} parameter is a map of provider specific properties to configure 201 * the file system. 202 * 203 * <p> This method throws {@link FileSystemAlreadyExistsException} if the 204 * file system already exists because it was previously created by an 205 * invocation of this method. Once a file system is {@link FileSystem#close 206 * closed} it is provider-dependent if the provider allows a new file system 207 * to be created with the same URI as a file system it previously created. 208 * 209 * @param uri 210 * URI reference 211 * @param env 212 * A map of provider specific properties to configure the file system; 213 * may be empty 214 * 215 * @return A new file system 216 * 217 * @throws IllegalArgumentException 218 * If the pre-conditions for the {@code uri} parameter aren't met, 219 * or the {@code env} parameter does not contain properties required 220 * by the provider, or a property value is invalid 221 * @throws IOException 222 * An I/O error occurs creating the file system 223 * @throws SecurityException 224 * If a security manager is installed and it denies an unspecified 225 * permission required by the file system provider implementation 226 * @throws FileSystemAlreadyExistsException 227 * If the file system has already been created 228 */ 229 public abstract FileSystem newFileSystem(URI uri, Map<String,?> env) 230 throws IOException; 231 232 /** 233 * Returns an existing {@code FileSystem} created by this provider. 234 * 235 * <p> This method returns a reference to a {@code FileSystem} that was 236 * created by invoking the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} 237 * method. File systems created the {@link #newFileSystem(FileRef,Map) 238 * newFileSystem(FileRef,Map)} method are not returned by this method. 239 * The file system is identified by its {@code URI}. Its exact form 240 * is highly provider dependent. In the case of the default provider the URI's 241 * path component is {@code "/"} and the authority, query and fragment components 242 * are undefined (Undefined components are represented by {@code null}). 243 * 244 * <p> Once a file system created by this provider is {@link FileSystem#close 245 * closed} it is provider-dependent if this method returns a reference to 246 * the closed file system or throws {@link FileSystemNotFoundException}. 247 * If the provider allows a new file system to be created with the same URI 248 * as a file system it previously created then this method throws the 249 * exception if invoked after the file system is closed (and before a new 250 * instance is created by the {@link #newFileSystem newFileSystem} method). 251 * 252 * <p> If a security manager is installed then a provider implementation 253 * may require to check a permission before returning a reference to an 254 * existing file system. In the case of the {@link FileSystems#getDefault 255 * default} file system, no permission check is required. 256 * 257 * @param uri 258 * URI reference 259 * 260 * @return The file system 261 * 262 * @throws IllegalArgumentException 263 * If the pre-conditions for the {@code uri} parameter aren't met 264 * @throws FileSystemNotFoundException 265 * If the file system does not exist 266 * @throws SecurityException 267 * If a security manager is installed and it denies an unspecified 268 * permission. 269 */ 270 public abstract FileSystem getFileSystem(URI uri); 271 272 /** 273 * Return a {@code Path} object by converting the given {@link URI}. The 274 * resulting {@code Path} is associated with a {@link FileSystem} that 275 * already exists or is constructed automatically. 276 * 277 * <p> The exact form of the URI is file system provider dependent. In the 278 * case of the default provider, the URI scheme is {@code "file"} and the 279 * given URI has a non-empty path component, and undefined query, and 280 * fragment components. The resulting {@code Path} is associated with the 281 * default {@link FileSystems#getDefault default} {@code FileSystem}. 282 * 283 * <p> If a security manager is installed then a provider implementation 284 * may require to check a permission. In the case of the {@link 285 * FileSystems#getDefault default} file system, no permission check is 286 * required. 287 * 288 * @param uri 289 * The URI to convert 290 * 291 * @throws IllegalArgumentException 292 * If the URI scheme does not identify this provider or other 293 * preconditions on the uri parameter do not hold 294 * @throws FileSystemNotFoundException 295 * The file system, identified by the URI, does not exist and 296 * cannot be created automatically 297 * @throws SecurityException 298 * If a security manager is installed and it denies an unspecified 299 * permission. 300 */ 301 public abstract Path getPath(URI uri); 302 303 /** 304 * Constructs a new {@code FileSystem} to access the contents of a file as a 305 * file system. 306 * 307 * <p> This method is intended for specialized providers of pseudo file 308 * systems where the contents of one or more files is treated as a file 309 * system. The {@code file} parameter is a reference to an existing file 310 * and the {@code env} parameter is a map of provider specific properties to 311 * configure the file system. 312 * 313 * <p> If this provider does not support the creation of such file systems 314 * or if the provider does not recognize the file type of the given file then 315 * it throws {@code UnsupportedOperationException}. The default implementation 316 * of this method throws {@code UnsupportedOperationException}. 317 * 318 * @param file 319 * The file 320 * @param env 321 * A map of provider specific properties to configure the file system; 322 * may be empty 323 * 324 * @return A new file system 325 * 326 * @throws UnsupportedOperationException 327 * If this provider does not support access to the contents as a 328 * file system or it does not recognize the file type of the 329 * given file 330 * @throws IllegalArgumentException 331 * If the {@code env} parameter does not contain properties required 332 * by the provider, or a property value is invalid 333 * @throws IOException 334 * If an I/O error occurs 335 * @throws SecurityException 336 * If a security manager is installed and it denies an unspecified 337 * permission. 338 */ 339 public FileSystem newFileSystem(FileRef file, Map<String,?> env) 340 throws IOException 341 { 342 throw new UnsupportedOperationException(); 343 } 344 345 /** 346 * Opens or creates a file for reading and/or writing, returning a file 347 * channel to access the file. 348 * 349 * <p> This method is invoked by the {@link FileChannel#open(Path,Set,FileAttribute[]) 350 * FileChannel.open} method to open a file channel. A provider that does not 351 * support all the features required to construct a file channel throws 352 * {@code UnsupportedOperationException}. The default provider is required 353 * to support the creation of file channels. When not overridden, the 354 * default implementation throws {@code UnsupportedOperationException}. 355 * 356 * @param path 357 * The path of the file to open or create 358 * @param options 359 * Options specifying how the file is opened 360 * @param attrs 361 * An optional list of file attributes to set atomically when 362 * creating the file 363 * 364 * @return A new file channel 365 * 366 * @throws IllegalArgumentException 367 * If the set contains an invalid combination of options 368 * @throws UnsupportedOperationException 369 * If this provider that does not support creating file channels, 370 * or an unsupported open option or file attribute is specified 371 * @throws IOException 372 * If an I/O error occurs 373 * @throws SecurityException 374 * In the case of the default file system, the {@link 375 * SecurityManager#checkRead(String)} method is invoked to check 376 * read access if the file is opened for reading. The {@link 377 * SecurityManager#checkWrite(String)} method is invoked to check 378 * write access if the file is opened for writing 379 */ 380 public FileChannel newFileChannel(Path path, 381 Set<? extends OpenOption> options, 382 FileAttribute<?>... attrs) 383 throws IOException 384 { 385 throw new UnsupportedOperationException(); 386 } 387 388 /** 389 * Opens or creates a file for reading and/or writing, returning an 390 * asynchronous file channel to access the file. 391 * 392 * <p> This method is invoked by the {@link 393 * AsynchronousFileChannel#open(Path,Set,ExecutorService,FileAttribute[]) 394 * AsynchronousFileChannel.open} method to open an asynchronous file channel. 395 * A provider that does not support all the features required to construct 396 * an asynchronous file channel throws {@code UnsupportedOperationException}. 397 * The default provider is required to support the creation of asynchronous 398 * file channels. When not overridden, the default implementation of this 399 * method throws {@code UnsupportedOperationException}. 400 * 401 * @param path 402 * The path of the file to open or create 403 * @param options 404 * Options specifying how the file is opened 405 * @param executor 406 * The thread pool or {@code null} to associate the channel with 407 * the default thread pool 408 * @param attrs 409 * An optional list of file attributes to set atomically when 410 * creating the file 411 * 412 * @return A new asynchronous file channel 413 * 414 * @throws IllegalArgumentException 415 * If the set contains an invalid combination of options 416 * @throws UnsupportedOperationException 417 * If this provider that does not support creating asynchronous file 418 * channels, or an unsupported open option or file attribute is 419 * specified 420 * @throws IOException 421 * If an I/O error occurs 422 * @throws SecurityException 423 * In the case of the default file system, the {@link 424 * SecurityManager#checkRead(String)} method is invoked to check 425 * read access if the file is opened for reading. The {@link 426 * SecurityManager#checkWrite(String)} method is invoked to check 427 * write access if the file is opened for writing 428 */ 429 public AsynchronousFileChannel newAsynchronousFileChannel(Path path, 430 Set<? extends OpenOption> options, 431 ExecutorService executor, 432 FileAttribute<?>... attrs) 433 throws IOException 434 { 435 throw new UnsupportedOperationException(); 436 } 437 }