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