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