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