FileSystems.java revision 13901:b2a69d66dc65
136285Sbrian/* 236285Sbrian * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. 336285Sbrian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 436285Sbrian * 536285Sbrian * This code is free software; you can redistribute it and/or modify it 636285Sbrian * under the terms of the GNU General Public License version 2 only, as 736285Sbrian * published by the Free Software Foundation. Oracle designates this 836285Sbrian * particular file as subject to the "Classpath" exception as provided 936285Sbrian * by Oracle in the LICENSE file that accompanied this code. 1036285Sbrian * 1136285Sbrian * This code is distributed in the hope that it will be useful, but WITHOUT 1236285Sbrian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1336285Sbrian * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1436285Sbrian * version 2 for more details (a copy is included in the LICENSE file that 1536285Sbrian * accompanied this code). 1636285Sbrian * 1736285Sbrian * You should have received a copy of the GNU General Public License version 1836285Sbrian * 2 along with this work; if not, write to the Free Software Foundation, 1936285Sbrian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2036285Sbrian * 2136285Sbrian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2236285Sbrian * or visit www.oracle.com if you need additional information or have any 2336285Sbrian * questions. 2436285Sbrian */ 2536285Sbrian 2637141Sbrianpackage java.nio.file; 2736285Sbrian 2836285Sbrianimport java.nio.file.spi.FileSystemProvider; 2936285Sbrianimport java.net.URI; 3036285Sbrianimport java.io.IOException; 3136285Sbrianimport java.security.AccessController; 3236285Sbrianimport java.security.PrivilegedAction; 3336285Sbrianimport java.lang.reflect.Constructor; 3436285Sbrianimport java.util.Collections; 3536285Sbrianimport java.util.Map; 3636285Sbrianimport java.util.ServiceConfigurationError; 3736285Sbrianimport java.util.ServiceLoader; 3836285Sbrian 3936285Sbrian/** 4036285Sbrian * Factory methods for file systems. This class defines the {@link #getDefault 4136285Sbrian * getDefault} method to get the default file system and factory methods to 4236285Sbrian * construct other types of file systems. 4336285Sbrian * 4436285Sbrian * <p> The first invocation of any of the methods defined by this class causes 4536285Sbrian * the default {@link FileSystemProvider provider} to be loaded. The default 4636285Sbrian * provider, identified by the URI scheme "file", creates the {@link FileSystem} 4737009Sbrian * that provides access to the file systems accessible to the Java virtual 4836285Sbrian * machine. If the process of loading or initializing the default provider fails 4936285Sbrian * then an unspecified error is thrown. 5036285Sbrian * 5136285Sbrian * <p> The first invocation of the {@link FileSystemProvider#installedProviders 5236285Sbrian * installedProviders} method, by way of invoking any of the {@code 5336285Sbrian * newFileSystem} methods defined by this class, locates and loads all 5436285Sbrian * installed file system providers. Installed providers are loaded using the 5536285Sbrian * service-provider loading facility defined by the {@link ServiceLoader} class. 5636285Sbrian * Installed providers are loaded using the system class loader. If the 5736285Sbrian * system class loader cannot be found then the platform class loader is used. 5836285Sbrian * Providers are typically installed by placing them in a JAR file on the 5936285Sbrian * application class path, the JAR file contains a 6036285Sbrian * provider-configuration file named {@code java.nio.file.spi.FileSystemProvider} 6136285Sbrian * in the resource directory {@code META-INF/services}, and the file lists one or 6236285Sbrian * more fully-qualified names of concrete subclass of {@link FileSystemProvider} 6336285Sbrian * that have a zero argument constructor. 6436285Sbrian * The ordering that installed providers are located is implementation specific. 6536285Sbrian * If a provider is instantiated and its {@link FileSystemProvider#getScheme() 6636285Sbrian * getScheme} returns the same URI scheme of a provider that was previously 6736285Sbrian * instantiated then the most recently instantiated duplicate is discarded. URI 6836285Sbrian * schemes are compared without regard to case. During construction a provider 6936285Sbrian * may safely access files associated with the default provider but care needs 7036285Sbrian * to be taken to avoid circular loading of other installed providers. If 7136285Sbrian * circular loading of installed providers is detected then an unspecified error 7236285Sbrian * is thrown. 7336285Sbrian * 7436285Sbrian * <p> This class also defines factory methods that allow a {@link ClassLoader} 7536285Sbrian * to be specified when locating a provider. As with installed providers, the 7636285Sbrian * provider classes are identified by placing the provider configuration file 7736285Sbrian * in the resource directory {@code META-INF/services}. 7836285Sbrian * 7936285Sbrian * <p> If a thread initiates the loading of the installed file system providers 8036285Sbrian * and another thread invokes a method that also attempts to load the providers 8136285Sbrian * then the method will block until the loading completes. 8236285Sbrian * 8336285Sbrian * @since 1.7 8436285Sbrian */ 8536285Sbrian 8636285Sbrianpublic final class FileSystems { 8736285Sbrian private FileSystems() { } 8836285Sbrian 8936285Sbrian // Built-in file system provider 9036285Sbrian private static final FileSystemProvider builtinFileSystemProvider = 9136285Sbrian sun.nio.fs.DefaultFileSystemProvider.create(); 9236285Sbrian 9336285Sbrian // built-in file system 9436285Sbrian private static class BuiltinFileSystemHolder { 9536285Sbrian static final FileSystem builtinFileSystem = 9636285Sbrian builtinFileSystemProvider.getFileSystem(URI.create("file:///")); 9736285Sbrian } 9836285Sbrian 9936285Sbrian // lazy initialization of default file system 10036285Sbrian private static class DefaultFileSystemHolder { 10136285Sbrian static final FileSystem defaultFileSystem = defaultFileSystem(); 10236285Sbrian 10336285Sbrian // returns default file system 10436285Sbrian private static FileSystem defaultFileSystem() { 10536285Sbrian // load default provider 10636285Sbrian FileSystemProvider provider = AccessController 10736285Sbrian .doPrivileged(new PrivilegedAction<>() { 10836285Sbrian public FileSystemProvider run() { 10936285Sbrian return getDefaultProvider(); 11036285Sbrian } 11136285Sbrian }); 11236285Sbrian 11336285Sbrian // return file system 11436285Sbrian return provider.getFileSystem(URI.create("file:///")); 11536285Sbrian } 11636285Sbrian 11736285Sbrian // returns default provider 11836285Sbrian private static FileSystemProvider getDefaultProvider() { 11936285Sbrian FileSystemProvider provider = builtinFileSystemProvider; 12036285Sbrian 12136285Sbrian // if the property java.nio.file.spi.DefaultFileSystemProvider is 12236285Sbrian // set then its value is the name of the default provider (or a list) 12336285Sbrian String propValue = System 12436285Sbrian .getProperty("java.nio.file.spi.DefaultFileSystemProvider"); 12536285Sbrian if (propValue != null) { 12636285Sbrian for (String cn: propValue.split(",")) { 12736285Sbrian try { 12836285Sbrian Class<?> c = Class 12936285Sbrian .forName(cn, true, ClassLoader.getSystemClassLoader()); 13036285Sbrian Constructor<?> ctor = c 13136285Sbrian .getDeclaredConstructor(FileSystemProvider.class); 13236285Sbrian provider = (FileSystemProvider)ctor.newInstance(provider); 13336285Sbrian 13436285Sbrian // must be "file" 13536285Sbrian if (!provider.getScheme().equals("file")) 13636285Sbrian throw new Error("Default provider must use scheme 'file'"); 13736285Sbrian 13836285Sbrian } catch (Exception x) { 13936285Sbrian throw new Error(x); 14036285Sbrian } 14136285Sbrian } 14236285Sbrian } 14336285Sbrian return provider; 14436285Sbrian } 14536285Sbrian } 14636285Sbrian 14736285Sbrian /** 14836285Sbrian * Returns the default {@code FileSystem}. The default file system creates 14936285Sbrian * objects that provide access to the file systems accessible to the Java 15036285Sbrian * virtual machine. The <em>working directory</em> of the file system is 15136285Sbrian * the current user directory, named by the system property {@code user.dir}. 15236285Sbrian * This allows for interoperability with the {@link java.io.File java.io.File} 15336285Sbrian * class. 15436285Sbrian * 15536285Sbrian * <p> The first invocation of any of the methods defined by this class 15636285Sbrian * locates the default {@link FileSystemProvider provider} object. Where the 15736285Sbrian * system property {@code java.nio.file.spi.DefaultFileSystemProvider} is 15836285Sbrian * not defined then the default provider is a system-default provider that 15936285Sbrian * is invoked to create the default file system. 16036285Sbrian * 16136285Sbrian * <p> If the system property {@code java.nio.file.spi.DefaultFileSystemProvider} 16236285Sbrian * is defined then it is taken to be a list of one or more fully-qualified 16336285Sbrian * names of concrete provider classes identified by the URI scheme 16436285Sbrian * {@code "file"}. Where the property is a list of more than one name then 16536285Sbrian * the names are separated by a comma. Each class is loaded, using the system 16636285Sbrian * class loader, and instantiated by invoking a one argument constructor 16736285Sbrian * whose formal parameter type is {@code FileSystemProvider}. The providers 16836285Sbrian * are loaded and instantiated in the order they are listed in the property. 16936285Sbrian * If this process fails or a provider's scheme is not equal to {@code "file"} 17036285Sbrian * then an unspecified error is thrown. URI schemes are normally compared 17136285Sbrian * without regard to case but for the default provider, the scheme is 17236285Sbrian * required to be {@code "file"}. The first provider class is instantiated 17336285Sbrian * by invoking it with a reference to the system-default provider. 17436285Sbrian * The second provider class is instantiated by invoking it with a reference 17536285Sbrian * to the first provider instance. The third provider class is instantiated 17636285Sbrian * by invoking it with a reference to the second instance, and so on. The 17736285Sbrian * last provider to be instantiated becomes the default provider; its {@code 17836285Sbrian * getFileSystem} method is invoked with the URI {@code "file:///"} to 17936285Sbrian * get a reference to the default file system. 18036285Sbrian * 18136285Sbrian * <p> Subsequent invocations of this method return the file system that was 18236285Sbrian * returned by the first invocation. 18336285Sbrian * 18436285Sbrian * @return the default file system 18536285Sbrian */ 18636285Sbrian public static FileSystem getDefault() { 18736285Sbrian if (jdk.internal.misc.VM.isBooted()) { 18836285Sbrian return DefaultFileSystemHolder.defaultFileSystem; 18936285Sbrian } else { 19036285Sbrian return BuiltinFileSystemHolder.builtinFileSystem; 19136285Sbrian } 19236285Sbrian } 19336285Sbrian 19436285Sbrian /** 19536285Sbrian * Returns a reference to an existing {@code FileSystem}. 19636285Sbrian * 19736285Sbrian * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 19836285Sbrian * installed} providers to locate the provider that is identified by the URI 19936285Sbrian * {@link URI#getScheme scheme} of the given URI. URI schemes are compared 20036285Sbrian * without regard to case. The exact form of the URI is highly provider 20136285Sbrian * dependent. If found, the provider's {@link FileSystemProvider#getFileSystem 20236285Sbrian * getFileSystem} method is invoked to obtain a reference to the {@code 20336285Sbrian * FileSystem}. 20436285Sbrian * 20536285Sbrian * <p> Once a file system created by this provider is {@link FileSystem#close 20636285Sbrian * closed} it is provider-dependent if this method returns a reference to 20736285Sbrian * the closed file system or throws {@link FileSystemNotFoundException}. 20836285Sbrian * If the provider allows a new file system to be created with the same URI 20936285Sbrian * as a file system it previously created then this method throws the 21036285Sbrian * exception if invoked after the file system is closed (and before a new 21136285Sbrian * instance is created by the {@link #newFileSystem newFileSystem} method). 21236285Sbrian * 21336285Sbrian * <p> If a security manager is installed then a provider implementation 21436285Sbrian * may require to check a permission before returning a reference to an 21536285Sbrian * existing file system. In the case of the {@link FileSystems#getDefault 21636285Sbrian * default} file system, no permission check is required. 21736285Sbrian * 21836285Sbrian * @param uri the URI to locate the file system 21936285Sbrian * 22036285Sbrian * @return the reference to the file system 22136285Sbrian * 22236285Sbrian * @throws IllegalArgumentException 22336285Sbrian * if the pre-conditions for the {@code uri} parameter are not met 22436285Sbrian * @throws FileSystemNotFoundException 22536285Sbrian * if the file system, identified by the URI, does not exist 22636285Sbrian * @throws ProviderNotFoundException 22736285Sbrian * if a provider supporting the URI scheme is not installed 22836285Sbrian * @throws SecurityException 22936285Sbrian * if a security manager is installed and it denies an unspecified 23036285Sbrian * permission 23136285Sbrian */ 23236285Sbrian public static FileSystem getFileSystem(URI uri) { 23336285Sbrian String scheme = uri.getScheme(); 23436285Sbrian for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 23536285Sbrian if (scheme.equalsIgnoreCase(provider.getScheme())) { 23636285Sbrian return provider.getFileSystem(uri); 23736285Sbrian } 23836285Sbrian } 23936285Sbrian throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); 24036285Sbrian } 24136285Sbrian 24236285Sbrian /** 24336285Sbrian * Constructs a new file system that is identified by a {@link URI} 24436285Sbrian * 24536285Sbrian * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 24636285Sbrian * installed} providers to locate the provider that is identified by the URI 24736285Sbrian * {@link URI#getScheme scheme} of the given URI. URI schemes are compared 24836285Sbrian * without regard to case. The exact form of the URI is highly provider 24936285Sbrian * dependent. If found, the provider's {@link FileSystemProvider#newFileSystem(URI,Map) 25036285Sbrian * newFileSystem(URI,Map)} method is invoked to construct the new file system. 25136285Sbrian * 25236285Sbrian * <p> Once a file system is {@link FileSystem#close closed} it is 25336285Sbrian * provider-dependent if the provider allows a new file system to be created 25436285Sbrian * with the same URI as a file system it previously created. 25536285Sbrian * 25636285Sbrian * <p> <b>Usage Example:</b> 25736285Sbrian * Suppose there is a provider identified by the scheme {@code "memory"} 25836285Sbrian * installed: 25936285Sbrian * <pre> 26036285Sbrian * Map<String,String> env = new HashMap<>(); 26136285Sbrian * env.put("capacity", "16G"); 26236285Sbrian * env.put("blockSize", "4k"); 26336285Sbrian * FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env); 26436285Sbrian * </pre> 26536285Sbrian * 26636285Sbrian * @param uri 26736285Sbrian * the URI identifying the file system 26836285Sbrian * @param env 26936285Sbrian * a map of provider specific properties to configure the file system; 27036285Sbrian * may be empty 27136285Sbrian * 27236285Sbrian * @return a new file system 27336285Sbrian * 27436285Sbrian * @throws IllegalArgumentException 27536310Sbrian * if the pre-conditions for the {@code uri} parameter are not met, 27636285Sbrian * or the {@code env} parameter does not contain properties required 27736285Sbrian * by the provider, or a property value is invalid 27836285Sbrian * @throws FileSystemAlreadyExistsException 27936285Sbrian * if the file system has already been created 28036285Sbrian * @throws ProviderNotFoundException 28136285Sbrian * if a provider supporting the URI scheme is not installed 28236285Sbrian * @throws IOException 28336285Sbrian * if an I/O error occurs creating the file system 28436285Sbrian * @throws SecurityException 28536285Sbrian * if a security manager is installed and it denies an unspecified 28636285Sbrian * permission required by the file system provider implementation 28736285Sbrian */ 28836285Sbrian public static FileSystem newFileSystem(URI uri, Map<String,?> env) 28936285Sbrian throws IOException 29036285Sbrian { 29136285Sbrian return newFileSystem(uri, env, null); 29236285Sbrian } 29336285Sbrian 29436285Sbrian /** 29536285Sbrian * Constructs a new file system that is identified by a {@link URI} 29636285Sbrian * 29737060Sbrian * <p> This method first attempts to locate an installed provider in exactly 29836285Sbrian * the same manner as the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} 29936285Sbrian * method. If none of the installed providers support the URI scheme then an 30036285Sbrian * attempt is made to locate the provider using the given class loader. If a 30136285Sbrian * provider supporting the URI scheme is located then its {@link 30236285Sbrian * FileSystemProvider#newFileSystem(URI,Map) newFileSystem(URI,Map)} is 30336285Sbrian * invoked to construct the new file system. 30436285Sbrian * 30536285Sbrian * @param uri 30636285Sbrian * the URI identifying the file system 30736285Sbrian * @param env 30836285Sbrian * a map of provider specific properties to configure the file system; 30936285Sbrian * may be empty 31036285Sbrian * @param loader 31136285Sbrian * the class loader to locate the provider or {@code null} to only 31236285Sbrian * attempt to locate an installed provider 31336285Sbrian * 31436285Sbrian * @return a new file system 31536285Sbrian * 31636285Sbrian * @throws IllegalArgumentException 31736285Sbrian * if the pre-conditions for the {@code uri} parameter are not met, 31836285Sbrian * or the {@code env} parameter does not contain properties required 31936285Sbrian * by the provider, or a property value is invalid 32036285Sbrian * @throws FileSystemAlreadyExistsException 32136285Sbrian * if the URI scheme identifies an installed provider and the file 32236285Sbrian * system has already been created 32336285Sbrian * @throws ProviderNotFoundException 32436285Sbrian * if a provider supporting the URI scheme is not found 32536312Sbrian * @throws ServiceConfigurationError 32636312Sbrian * when an error occurs while loading a service provider 32736312Sbrian * @throws IOException 32836312Sbrian * an I/O error occurs creating the file system 32936312Sbrian * @throws SecurityException 33036312Sbrian * if a security manager is installed and it denies an unspecified 33136312Sbrian * permission required by the file system provider implementation 33236285Sbrian */ 33336285Sbrian public static FileSystem newFileSystem(URI uri, Map<String,?> env, ClassLoader loader) 33436285Sbrian throws IOException 33536285Sbrian { 33636312Sbrian String scheme = uri.getScheme(); 33736312Sbrian 33836312Sbrian // check installed providers 33936312Sbrian for (FileSystemProvider provider : FileSystemProvider.installedProviders()) { 34036312Sbrian if (scheme.equalsIgnoreCase(provider.getScheme())) { 34136312Sbrian try { 34236285Sbrian return provider.newFileSystem(uri, env); 34336285Sbrian } catch (UnsupportedOperationException uoe) { 34436285Sbrian } 34536285Sbrian } 34636285Sbrian } 34736285Sbrian 34836285Sbrian // if not found, use service-provider loading facility 34936312Sbrian if (loader != null) { 35036285Sbrian ServiceLoader<FileSystemProvider> sl = ServiceLoader 35136312Sbrian .load(FileSystemProvider.class, loader); 35236312Sbrian for (FileSystemProvider provider : sl) { 35336312Sbrian if (scheme.equalsIgnoreCase(provider.getScheme())) { 35436285Sbrian try { 35536285Sbrian return provider.newFileSystem(uri, env); 35636285Sbrian } catch (UnsupportedOperationException uoe) { 35736285Sbrian } 35836285Sbrian } 35936285Sbrian } 36036285Sbrian } 36136285Sbrian 36236285Sbrian throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); 36336285Sbrian } 36436285Sbrian 36536285Sbrian /** 36636285Sbrian * Constructs a new {@code FileSystem} to access the contents of a file as a 36736285Sbrian * file system. 36836285Sbrian * 36936285Sbrian * <p> This method makes use of specialized providers that create pseudo file 37036285Sbrian * systems where the contents of one or more files is treated as a file 37136285Sbrian * system. 37236285Sbrian * 37336285Sbrian * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 37436285Sbrian * installed} providers. It invokes, in turn, each provider's {@link 37536285Sbrian * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method 37636285Sbrian * with an empty map. If a provider returns a file system then the iteration 37736285Sbrian * terminates and the file system is returned. If none of the installed 37836285Sbrian * providers return a {@code FileSystem} then an attempt is made to locate 37936285Sbrian * the provider using the given class loader. If a provider returns a file 38036285Sbrian * system then the lookup terminates and the file system is returned. 38136285Sbrian * 38236285Sbrian * @param path 38336285Sbrian * the path to the file 38436285Sbrian * @param loader 38536285Sbrian * the class loader to locate the provider or {@code null} to only 38636285Sbrian * attempt to locate an installed provider 38736285Sbrian * 38836285Sbrian * @return a new file system 38936285Sbrian * 39036285Sbrian * @throws ProviderNotFoundException 39136285Sbrian * if a provider supporting this file type cannot be located 39236285Sbrian * @throws ServiceConfigurationError 39336285Sbrian * when an error occurs while loading a service provider 39436285Sbrian * @throws IOException 39536285Sbrian * if an I/O error occurs 39636285Sbrian * @throws SecurityException 39736285Sbrian * if a security manager is installed and it denies an unspecified 39836285Sbrian * permission 39936285Sbrian */ 40036285Sbrian public static FileSystem newFileSystem(Path path, 40136285Sbrian ClassLoader loader) 40236285Sbrian throws IOException 40336285Sbrian { 40436285Sbrian if (path == null) 40536285Sbrian throw new NullPointerException(); 40636285Sbrian Map<String,?> env = Collections.emptyMap(); 40736285Sbrian 40836285Sbrian // check installed providers 40936285Sbrian for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 41036285Sbrian try { 41136285Sbrian return provider.newFileSystem(path, env); 41236285Sbrian } catch (UnsupportedOperationException uoe) { 41336285Sbrian } 41436285Sbrian } 41536285Sbrian 41636285Sbrian // if not found, use service-provider loading facility 41736285Sbrian if (loader != null) { 41836285Sbrian ServiceLoader<FileSystemProvider> sl = ServiceLoader 41936285Sbrian .load(FileSystemProvider.class, loader); 42036285Sbrian for (FileSystemProvider provider: sl) { 42136285Sbrian try { 42236285Sbrian return provider.newFileSystem(path, env); 42336285Sbrian } catch (UnsupportedOperationException uoe) { 42436285Sbrian } 42536285Sbrian } 42636285Sbrian } 42736285Sbrian 42836285Sbrian throw new ProviderNotFoundException("Provider not found"); 42936285Sbrian } 43036285Sbrian} 43136285Sbrian