1 /* 2 * Copyright (c) 2007, 2015, 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; 27 28 import java.nio.file.spi.FileSystemProvider; 29 import java.net.URI; 30 import java.io.IOException; 31 import java.security.AccessController; 32 import java.security.PrivilegedAction; 33 import java.lang.reflect.Constructor; 34 import java.util.Collections; 35 import java.util.Map; 36 import java.util.ServiceConfigurationError; 37 import java.util.ServiceLoader; 38 39 /** 40 * Factory methods for file systems. This class defines the {@link #getDefault 41 * getDefault} method to get the default file system and factory methods to 42 * construct other types of file systems. 43 * 44 * <p> The first invocation of any of the methods defined by this class causes 45 * the default {@link FileSystemProvider provider} to be loaded. The default 46 * provider, identified by the URI scheme "file", creates the {@link FileSystem} 47 * that provides access to the file systems accessible to the Java virtual 48 * machine. If the process of loading or initializing the default provider fails 49 * then an unspecified error is thrown. 50 * 51 * <p> The first invocation of the {@link FileSystemProvider#installedProviders 52 * installedProviders} method, by way of invoking any of the {@code 53 * newFileSystem} methods defined by this class, locates and loads all 54 * installed file system providers. Installed providers are loaded using the 55 * service-provider loading facility defined by the {@link ServiceLoader} class. 56 * Installed providers are loaded using the system class loader. If the 57 * system class loader cannot be found then the platform class loader is used. 58 * Providers are typically installed by placing them in a JAR file on the 59 * application class path, the JAR file contains a 60 * provider-configuration file named {@code java.nio.file.spi.FileSystemProvider} 61 * in the resource directory {@code META-INF/services}, and the file lists one or 62 * more fully-qualified names of concrete subclass of {@link FileSystemProvider} 63 * that have a zero argument constructor. 64 * The ordering that installed providers are located is implementation specific. 65 * If a provider is instantiated and its {@link FileSystemProvider#getScheme() 66 * getScheme} returns the same URI scheme of a provider that was previously 67 * instantiated then the most recently instantiated duplicate is discarded. URI 68 * schemes are compared without regard to case. During construction a provider 69 * may safely access files associated with the default provider but care needs 70 * to be taken to avoid circular loading of other installed providers. If 71 * circular loading of installed providers is detected then an unspecified error 72 * is thrown. 73 * 74 * <p> This class also defines factory methods that allow a {@link ClassLoader} 75 * to be specified when locating a provider. As with installed providers, the 76 * provider classes are identified by placing the provider configuration file 77 * in the resource directory {@code META-INF/services}. 78 * 79 * <p> If a thread initiates the loading of the installed file system providers 80 * and another thread invokes a method that also attempts to load the providers 81 * then the method will block until the loading completes. 82 * 83 * @since 1.7 84 */ 85 86 public final class FileSystems { 87 private FileSystems() { } 88 89 // Built-in file system provider 90 private static final FileSystemProvider builtinFileSystemProvider = 91 sun.nio.fs.DefaultFileSystemProvider.create(); 92 93 // built-in file system 94 private static class BuiltinFileSystemHolder { 95 static final FileSystem builtinFileSystem = 96 builtinFileSystemProvider.getFileSystem(URI.create("file:///")); 97 } 98 99 // lazy initialization of default file system 100 private static class DefaultFileSystemHolder { 101 static final FileSystem defaultFileSystem = defaultFileSystem(); 102 103 // returns default file system 104 private static FileSystem defaultFileSystem() { 105 // load default provider 106 FileSystemProvider provider = AccessController 107 .doPrivileged(new PrivilegedAction<>() { 108 public FileSystemProvider run() { 109 return getDefaultProvider(); 110 } 111 }); 112 113 // return file system 114 return provider.getFileSystem(URI.create("file:///")); 115 } 116 117 // returns default provider 118 private static FileSystemProvider getDefaultProvider() { 119 FileSystemProvider provider = builtinFileSystemProvider; 120 121 // if the property java.nio.file.spi.DefaultFileSystemProvider is 122 // set then its value is the name of the default provider (or a list) 123 String propValue = System 124 .getProperty("java.nio.file.spi.DefaultFileSystemProvider"); 125 if (propValue != null) { 126 for (String cn: propValue.split(",")) { 127 try { 128 Class<?> c = Class 129 .forName(cn, true, ClassLoader.getSystemClassLoader()); 130 Constructor<?> ctor = c 131 .getDeclaredConstructor(FileSystemProvider.class); 132 provider = (FileSystemProvider)ctor.newInstance(provider); 133 134 // must be "file" 135 if (!provider.getScheme().equals("file")) 136 throw new Error("Default provider must use scheme 'file'"); 137 138 } catch (Exception x) { 139 throw new Error(x); 140 } 141 } 142 } 143 return provider; 144 } 145 } 146 147 /** 148 * Returns the builtin {@code FileSystem}. 149 * 150 * @return the builtin file system 151 */ 152 static FileSystem getBuiltin() { 153 return BuiltinFileSystemHolder.builtinFileSystem; 154 } 155 156 /** 157 * Returns the default {@code FileSystem}. The default file system creates 158 * objects that provide access to the file systems accessible to the Java 159 * virtual machine. The <em>working directory</em> of the file system is 160 * the current user directory, named by the system property {@code user.dir}. 161 * This allows for interoperability with the {@link java.io.File java.io.File} 162 * class. 163 * 164 * <p> The first invocation of any of the methods defined by this class 165 * locates the default {@link FileSystemProvider provider} object. Where the 166 * system property {@code java.nio.file.spi.DefaultFileSystemProvider} is 167 * not defined then the default provider is a system-default provider that 168 * is invoked to create the default file system. 169 * 170 * <p> If the system property {@code java.nio.file.spi.DefaultFileSystemProvider} 171 * is defined then it is taken to be a list of one or more fully-qualified 172 * names of concrete provider classes identified by the URI scheme 173 * {@code "file"}. Where the property is a list of more than one name then 174 * the names are separated by a comma. Each class is loaded, using the system 175 * class loader, and instantiated by invoking a one argument constructor 176 * whose formal parameter type is {@code FileSystemProvider}. The providers 177 * are loaded and instantiated in the order they are listed in the property. 178 * If this process fails or a provider's scheme is not equal to {@code "file"} 179 * then an unspecified error is thrown. URI schemes are normally compared 180 * without regard to case but for the default provider, the scheme is 181 * required to be {@code "file"}. The first provider class is instantiated 182 * by invoking it with a reference to the system-default provider. 183 * The second provider class is instantiated by invoking it with a reference 184 * to the first provider instance. The third provider class is instantiated 185 * by invoking it with a reference to the second instance, and so on. The 186 * last provider to be instantiated becomes the default provider; its {@code 187 * getFileSystem} method is invoked with the URI {@code "file:///"} to 188 * get a reference to the default file system. 189 * 190 * <p> Subsequent invocations of this method return the file system that was 191 * returned by the first invocation. 192 * 193 * @return the default file system 194 */ 195 public static FileSystem getDefault() { 196 if (jdk.internal.misc.VM.isBooted()) { 197 return DefaultFileSystemHolder.defaultFileSystem; 198 } else { 199 return BuiltinFileSystemHolder.builtinFileSystem; 200 } 201 } 202 203 /** 204 * Returns a reference to an existing {@code FileSystem}. 205 * 206 * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 207 * installed} providers to locate the provider that is identified by the URI 208 * {@link URI#getScheme scheme} of the given URI. URI schemes are compared 209 * without regard to case. The exact form of the URI is highly provider 210 * dependent. If found, the provider's {@link FileSystemProvider#getFileSystem 211 * getFileSystem} method is invoked to obtain a reference to the {@code 212 * FileSystem}. 213 * 214 * <p> Once a file system created by this provider is {@link FileSystem#close 215 * closed} it is provider-dependent if this method returns a reference to 216 * the closed file system or throws {@link FileSystemNotFoundException}. 217 * If the provider allows a new file system to be created with the same URI 218 * as a file system it previously created then this method throws the 219 * exception if invoked after the file system is closed (and before a new 220 * instance is created by the {@link #newFileSystem newFileSystem} method). 221 * 222 * <p> If a security manager is installed then a provider implementation 223 * may require to check a permission before returning a reference to an 224 * existing file system. In the case of the {@link FileSystems#getDefault 225 * default} file system, no permission check is required. 226 * 227 * @param uri the URI to locate the file system 228 * 229 * @return the reference to the file system 230 * 231 * @throws IllegalArgumentException 232 * if the pre-conditions for the {@code uri} parameter are not met 233 * @throws FileSystemNotFoundException 234 * if the file system, identified by the URI, does not exist 235 * @throws ProviderNotFoundException 236 * if a provider supporting the URI scheme is not installed 237 * @throws SecurityException 238 * if a security manager is installed and it denies an unspecified 239 * permission 240 */ 241 public static FileSystem getFileSystem(URI uri) { 242 String scheme = uri.getScheme(); 243 for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 244 if (scheme.equalsIgnoreCase(provider.getScheme())) { 245 return provider.getFileSystem(uri); 246 } 247 } 248 throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); 249 } 250 251 /** 252 * Constructs a new file system that is identified by a {@link URI} 253 * 254 * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 255 * installed} providers to locate the provider that is identified by the URI 256 * {@link URI#getScheme scheme} of the given URI. URI schemes are compared 257 * without regard to case. The exact form of the URI is highly provider 258 * dependent. If found, the provider's {@link FileSystemProvider#newFileSystem(URI,Map) 259 * newFileSystem(URI,Map)} method is invoked to construct the new file system. 260 * 261 * <p> Once a file system is {@link FileSystem#close closed} it is 262 * provider-dependent if the provider allows a new file system to be created 263 * with the same URI as a file system it previously created. 264 * 265 * <p> <b>Usage Example:</b> 266 * Suppose there is a provider identified by the scheme {@code "memory"} 267 * installed: 268 * <pre> 269 * Map<String,String> env = new HashMap<>(); 270 * env.put("capacity", "16G"); 271 * env.put("blockSize", "4k"); 272 * FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env); 273 * </pre> 274 * 275 * @param uri 276 * the URI identifying the file system 277 * @param env 278 * a map of provider specific properties to configure the file system; 279 * may be empty 280 * 281 * @return a new file system 282 * 283 * @throws IllegalArgumentException 284 * if the pre-conditions for the {@code uri} parameter are not met, 285 * or the {@code env} parameter does not contain properties required 286 * by the provider, or a property value is invalid 287 * @throws FileSystemAlreadyExistsException 288 * if the file system has already been created 289 * @throws ProviderNotFoundException 290 * if a provider supporting the URI scheme is not installed 291 * @throws IOException 292 * if an I/O error occurs creating the file system 293 * @throws SecurityException 294 * if a security manager is installed and it denies an unspecified 295 * permission required by the file system provider implementation 296 */ 297 public static FileSystem newFileSystem(URI uri, Map<String,?> env) 298 throws IOException 299 { 300 return newFileSystem(uri, env, null); 301 } 302 303 /** 304 * Constructs a new file system that is identified by a {@link URI} 305 * 306 * <p> This method first attempts to locate an installed provider in exactly 307 * the same manner as the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} 308 * method. If none of the installed providers support the URI scheme then an 309 * attempt is made to locate the provider using the given class loader. If a 310 * provider supporting the URI scheme is located then its {@link 311 * FileSystemProvider#newFileSystem(URI,Map) newFileSystem(URI,Map)} is 312 * invoked to construct the new file system. 313 * 314 * @param uri 315 * the URI identifying the file system 316 * @param env 317 * a map of provider specific properties to configure the file system; 318 * may be empty 319 * @param loader 320 * the class loader to locate the provider or {@code null} to only 321 * attempt to locate an installed provider 322 * 323 * @return a new file system 324 * 325 * @throws IllegalArgumentException 326 * if the pre-conditions for the {@code uri} parameter are not met, 327 * or the {@code env} parameter does not contain properties required 328 * by the provider, or a property value is invalid 329 * @throws FileSystemAlreadyExistsException 330 * if the URI scheme identifies an installed provider and the file 331 * system has already been created 332 * @throws ProviderNotFoundException 333 * if a provider supporting the URI scheme is not found 334 * @throws ServiceConfigurationError 335 * when an error occurs while loading a service provider 336 * @throws IOException 337 * an I/O error occurs creating the file system 338 * @throws SecurityException 339 * if a security manager is installed and it denies an unspecified 340 * permission required by the file system provider implementation 341 */ 342 public static FileSystem newFileSystem(URI uri, Map<String,?> env, ClassLoader loader) 343 throws IOException 344 { 345 String scheme = uri.getScheme(); 346 347 // check installed providers 348 for (FileSystemProvider provider : FileSystemProvider.installedProviders()) { 349 if (scheme.equalsIgnoreCase(provider.getScheme())) { 350 try { 351 return provider.newFileSystem(uri, env); 352 } catch (UnsupportedOperationException uoe) { 353 } 354 } 355 } 356 357 // if not found, use service-provider loading facility 358 if (loader != null) { 359 ServiceLoader<FileSystemProvider> sl = ServiceLoader 360 .load(FileSystemProvider.class, loader); 361 for (FileSystemProvider provider : sl) { 362 if (scheme.equalsIgnoreCase(provider.getScheme())) { 363 try { 364 return provider.newFileSystem(uri, env); 365 } catch (UnsupportedOperationException uoe) { 366 } 367 } 368 } 369 } 370 371 throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); 372 } 373 374 /** 375 * Constructs a new {@code FileSystem} to access the contents of a file as a 376 * file system. 377 * 378 * <p> This method makes use of specialized providers that create pseudo file 379 * systems where the contents of one or more files is treated as a file 380 * system. 381 * 382 * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 383 * installed} providers. It invokes, in turn, each provider's {@link 384 * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method 385 * with an empty map. If a provider returns a file system then the iteration 386 * terminates and the file system is returned. If none of the installed 387 * providers return a {@code FileSystem} then an attempt is made to locate 388 * the provider using the given class loader. If a provider returns a file 389 * system then the lookup terminates and the file system is returned. 390 * 391 * @param path 392 * the path to the file 393 * @param loader 394 * the class loader to locate the provider or {@code null} to only 395 * attempt to locate an installed provider 396 * 397 * @return a new file system 398 * 399 * @throws ProviderNotFoundException 400 * if a provider supporting this file type cannot be located 401 * @throws ServiceConfigurationError 402 * when an error occurs while loading a service provider 403 * @throws IOException 404 * if an I/O error occurs 405 * @throws SecurityException 406 * if a security manager is installed and it denies an unspecified 407 * permission 408 */ 409 public static FileSystem newFileSystem(Path path, 410 ClassLoader loader) 411 throws IOException 412 { 413 if (path == null) 414 throw new NullPointerException(); 415 Map<String,?> env = Collections.emptyMap(); 416 417 // check installed providers 418 for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 419 try { 420 return provider.newFileSystem(path, env); 421 } catch (UnsupportedOperationException uoe) { 422 } 423 } 424 425 // if not found, use service-provider loading facility 426 if (loader != null) { 427 ServiceLoader<FileSystemProvider> sl = ServiceLoader 428 .load(FileSystemProvider.class, loader); 429 for (FileSystemProvider provider: sl) { 430 try { 431 return provider.newFileSystem(path, env); 432 } catch (UnsupportedOperationException uoe) { 433 } 434 } 435 } 436 437 throw new ProviderNotFoundException("Provider not found"); 438 } 439 }