/* * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.nio.file; import java.nio.file.spi.FileSystemProvider; import java.net.URI; import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import java.lang.reflect.Constructor; /** * Factory methods for file systems. This class defines the {@link #getDefault * getDefault} method to get the default file system and factory methods to * construct other types of file systems. * *

The first invocation of any of the methods defined by this class causes * the default {@link FileSystemProvider provider} to be loaded. The default * provider, identified by the URI scheme "file", creates the {@link FileSystem} * that provides access to the file systems accessible to the Java virtual * machine. If the process of loading or initializing the default provider fails * then an unspecified error is thrown. * *

The first invocation of the {@link FileSystemProvider#installedProviders * installedProviders} method, by way of invoking any of the {@code * newFileSystem} methods defined by this class, locates and loads all * installed file system providers. Installed providers are loaded using the * service-provider loading facility defined by the {@link ServiceLoader} class. * Installed providers are loaded using the system class loader. If the * system class loader cannot be found then the extension class loader is used; * if there is no extension class loader then the bootstrap class loader is used. * Providers are typically installed by placing them in a JAR file on the * application class path, the JAR file contains a * provider-configuration file named {@code java.nio.file.spi.FileSystemProvider} * in the resource directory {@code META-INF/services}, and the file lists one or * more fully-qualified names of concrete subclass of {@link FileSystemProvider} * that have a zero argument constructor. * The ordering that installed providers are located is implementation specific. * If a provider is instantiated and its {@link FileSystemProvider#getScheme() * getScheme} returns the same URI scheme of a provider that was previously * instantiated then the most recently instantiated duplicate is discarded. URI * schemes are compared without regard to case. During construction a provider * may safely access files associated with the default provider but care needs * to be taken to avoid circular loading of other installed providers. If * circular loading of installed providers is detected then an unspecified error * is thrown. * *

This class also defines factory methods that allow a {@link ClassLoader} * to be specified when locating a provider. As with installed providers, the * provider classes are identified by placing the provider configuration file * in the resource directory {@code META-INF/services}. * *

If a thread initiates the loading of the installed file system providers * and another thread invokes a method that also attempts to load the providers * then the method will block until the loading completes. * * @since 1.7 */ public final class FileSystems { private FileSystems() { } // lazy initialization of default file system private static class DefaultFileSystemHolder { static final FileSystem defaultFileSystem = defaultFileSystem(); // returns default file system private static FileSystem defaultFileSystem() { // load default provider FileSystemProvider provider = AccessController .doPrivileged(new PrivilegedAction() { public FileSystemProvider run() { return getDefaultProvider(); } }); // return file system return provider.getFileSystem(URI.create("file:///")); } // returns default provider private static FileSystemProvider getDefaultProvider() { FileSystemProvider provider = sun.nio.fs.DefaultFileSystemProvider.create(); // if the property java.nio.file.spi.DefaultFileSystemProvider is // set then its value is the name of the default provider (or a list) String propValue = System .getProperty("java.nio.file.spi.DefaultFileSystemProvider"); if (propValue != null) { for (String cn: propValue.split(",")) { try { Class c = Class .forName(cn, true, ClassLoader.getSystemClassLoader()); Constructor ctor = c .getDeclaredConstructor(FileSystemProvider.class); provider = (FileSystemProvider)ctor.newInstance(provider); // must be "file" if (!provider.getScheme().equals("file")) throw new Error("Default provider must use scheme 'file'"); } catch (Exception x) { throw new Error(x); } } } return provider; } } /** * Returns the default {@code FileSystem}. The default file system creates * objects that provide access to the file systems accessible to the Java * virtual machine. The working directory of the file system is * the current user directory, named by the system property {@code user.dir}. * This allows for interoperability with the {@link java.io.File java.io.File} * class. * *

The first invocation of any of the methods defined by this class * locates the default {@link FileSystemProvider provider} object. Where the * system property {@code java.nio.file.spi.DefaultFileSystemProvider} is * not defined then the default provider is a system-default provider that * is invoked to create the default file system. * *

If the system property {@code java.nio.file.spi.DefaultFileSystemProvider} * is defined then it is taken to be a list of one or more fully-qualified * names of concrete provider classes identified by the URI scheme * {@code "file"}. Where the property is a list of more than one name then * the names are separated by a comma. Each class is loaded, using the system * class loader, and instantiated by invoking a one argument constructor * whose formal parameter type is {@code FileSystemProvider}. The providers * are loaded and instantiated in the order they are listed in the property. * If this process fails or a provider's scheme is not equal to {@code "file"} * then an unspecified error is thrown. URI schemes are normally compared * without regard to case but for the default provider, the scheme is * required to be {@code "file"}. The first provider class is instantiated * by invoking it with a reference to the system-default provider. * The second provider class is instantiated by invoking it with a reference * to the first provider instance. The third provider class is instantiated * by invoking it with a reference to the second instance, and so on. The * last provider to be instantiated becomes the default provider; its {@code * getFileSystem} method is invoked with the URI {@code "file:///"} to * get a reference to the default file system. * *

Subsequent invocations of this method return the file system that was * returned by the first invocation. * * @return the default file system */ public static FileSystem getDefault() { return DefaultFileSystemHolder.defaultFileSystem; } /** * Returns a reference to an existing {@code FileSystem}. * *

This method iterates over the {@link FileSystemProvider#installedProviders() * installed} providers to locate the provider that is identified by the URI * {@link URI#getScheme scheme} of the given URI. URI schemes are compared * without regard to case. The exact form of the URI is highly provider * dependent. If found, the provider's {@link FileSystemProvider#getFileSystem * getFileSystem} method is invoked to obtain a reference to the {@code * FileSystem}. * *

Once a file system created by this provider is {@link FileSystem#close * closed} it is provider-dependent if this method returns a reference to * the closed file system or throws {@link FileSystemNotFoundException}. * If the provider allows a new file system to be created with the same URI * as a file system it previously created then this method throws the * exception if invoked after the file system is closed (and before a new * instance is created by the {@link #newFileSystem newFileSystem} method). * *

If a security manager is installed then a provider implementation * may require to check a permission before returning a reference to an * existing file system. In the case of the {@link FileSystems#getDefault * default} file system, no permission check is required. * * @param uri the URI to locate the file system * * @return the reference to the file system * * @throws IllegalArgumentException * if the pre-conditions for the {@code uri} parameter are not met * @throws FileSystemNotFoundException * if the file system, identified by the URI, does not exist * @throws ProviderNotFoundException * if a provider supporting the URI scheme is not installed * @throws SecurityException * if a security manager is installed and it denies an unspecified * permission */ public static FileSystem getFileSystem(URI uri) { String scheme = uri.getScheme(); for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { if (scheme.equalsIgnoreCase(provider.getScheme())) { return provider.getFileSystem(uri); } } throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); } /** * Constructs a new file system that is identified by a {@link URI} * *

This method iterates over the {@link FileSystemProvider#installedProviders() * installed} providers to locate the provider that is identified by the URI * {@link URI#getScheme scheme} of the given URI. URI schemes are compared * without regard to case. The exact form of the URI is highly provider * dependent. If found, the provider's {@link FileSystemProvider#newFileSystem(URI,Map) * newFileSystem(URI,Map)} method is invoked to construct the new file system. * *

Once a file system is {@link FileSystem#close closed} it is * provider-dependent if the provider allows a new file system to be created * with the same URI as a file system it previously created. * *

Usage Example: * Suppose there is a provider identified by the scheme {@code "memory"} * installed: *

     *   Map<String,String> env = new HashMap<>();
     *   env.put("capacity", "16G");
     *   env.put("blockSize", "4k");
     *   FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env);
     * 
* * @param uri * the URI identifying the file system * @param env * a map of provider specific properties to configure the file system; * may be empty * * @return a new file system * * @throws IllegalArgumentException * if the pre-conditions for the {@code uri} parameter are not met, * or the {@code env} parameter does not contain properties required * by the provider, or a property value is invalid * @throws FileSystemAlreadyExistsException * if the file system has already been created * @throws ProviderNotFoundException * if a provider supporting the URI scheme is not installed * @throws IOException * if an I/O error occurs creating the file system * @throws SecurityException * if a security manager is installed and it denies an unspecified * permission required by the file system provider implementation */ public static FileSystem newFileSystem(URI uri, Map env) throws IOException { return newFileSystem(uri, env, null); } /** * Constructs a new file system that is identified by a {@link URI} * *

This method first attempts to locate an installed provider in exactly * the same manner as the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} * method. If none of the installed providers support the URI scheme then an * attempt is made to locate the provider using the given class loader. If a * provider supporting the URI scheme is located then its {@link * FileSystemProvider#newFileSystem(URI,Map) newFileSystem(URI,Map)} is * invoked to construct the new file system. * * @param uri * the URI identifying the file system * @param env * a map of provider specific properties to configure the file system; * may be empty * @param loader * the class loader to locate the provider or {@code null} to only * attempt to locate an installed provider * * @return a new file system * * @throws IllegalArgumentException * if the pre-conditions for the {@code uri} parameter are not met, * or the {@code env} parameter does not contain properties required * by the provider, or a property value is invalid * @throws FileSystemAlreadyExistsException * if the URI scheme identifies an installed provider and the file * system has already been created * @throws ProviderNotFoundException * if a provider supporting the URI scheme is not found * @throws ServiceConfigurationError * when an error occurs while loading a service provider * @throws IOException * an I/O error occurs creating the file system * @throws SecurityException * if a security manager is installed and it denies an unspecified * permission required by the file system provider implementation */ public static FileSystem newFileSystem(URI uri, Map env, ClassLoader loader) throws IOException { String scheme = uri.getScheme(); // check installed providers for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { if (scheme.equalsIgnoreCase(provider.getScheme())) { return provider.newFileSystem(uri, env); } } // if not found, use service-provider loading facility if (loader != null) { ServiceLoader sl = ServiceLoader .load(FileSystemProvider.class, loader); for (FileSystemProvider provider: sl) { if (scheme.equalsIgnoreCase(provider.getScheme())) { return provider.newFileSystem(uri, env); } } } throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); } /** * Constructs a new {@code FileSystem} to access the contents of a file as a * file system. * *

This method makes use of specialized providers that create pseudo file * systems where the contents of one or more files is treated as a file * system. * *

This method iterates over the {@link FileSystemProvider#installedProviders() * installed} providers. It invokes, in turn, each provider's {@link * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method * with an empty map. If a provider returns a file system then the iteration * terminates and the file system is returned. If none of the installed * providers return a {@code FileSystem} then an attempt is made to locate * the provider using the given class loader. If a provider returns a file * system then the lookup terminates and the file system is returned. * * @param path * the path to the file * @param loader * the class loader to locate the provider or {@code null} to only * attempt to locate an installed provider * * @return a new file system * * @throws ProviderNotFoundException * if a provider supporting this file type cannot be located * @throws ServiceConfigurationError * when an error occurs while loading a service provider * @throws IOException * if an I/O error occurs * @throws SecurityException * if a security manager is installed and it denies an unspecified * permission */ public static FileSystem newFileSystem(Path path, ClassLoader loader) throws IOException { if (path == null) throw new NullPointerException(); Map env = Collections.emptyMap(); // check installed providers for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { try { return provider.newFileSystem(path, env); } catch (UnsupportedOperationException uoe) { } } // if not found, use service-provider loading facility if (loader != null) { ServiceLoader sl = ServiceLoader .load(FileSystemProvider.class, loader); for (FileSystemProvider provider: sl) { try { return provider.newFileSystem(path, env); } catch (UnsupportedOperationException uoe) { } } } throw new ProviderNotFoundException("Provider not found"); } }