FileSystems.java revision 11805:98ce6490ceff
1217739Sadrian/* 2217739Sadrian * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. 3217739Sadrian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4217739Sadrian * 5217739Sadrian * This code is free software; you can redistribute it and/or modify it 6217739Sadrian * under the terms of the GNU General Public License version 2 only, as 7217739Sadrian * published by the Free Software Foundation. Oracle designates this 8217739Sadrian * particular file as subject to the "Classpath" exception as provided 9217739Sadrian * by Oracle in the LICENSE file that accompanied this code. 10217739Sadrian * 11217739Sadrian * This code is distributed in the hope that it will be useful, but WITHOUT 12217739Sadrian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13217739Sadrian * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14217739Sadrian * version 2 for more details (a copy is included in the LICENSE file that 15217739Sadrian * accompanied this code). 16217739Sadrian * 17217739Sadrian * You should have received a copy of the GNU General Public License version 18217739Sadrian * 2 along with this work; if not, write to the Free Software Foundation, 19217739Sadrian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20217739Sadrian * 21217739Sadrian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22217739Sadrian * or visit www.oracle.com if you need additional information or have any 23217739Sadrian * questions. 24217739Sadrian */ 25217739Sadrian 26217739Sadrianpackage java.nio.file; 27217739Sadrian 28217739Sadrianimport java.nio.file.spi.FileSystemProvider; 29217739Sadrianimport java.net.URI; 30217739Sadrianimport java.io.IOException; 31217739Sadrianimport java.security.AccessController; 32217739Sadrianimport java.security.PrivilegedAction; 33217739Sadrianimport java.util.*; 34217739Sadrianimport java.lang.reflect.Constructor; 35217739Sadrian 36217739Sadrian/** 37217739Sadrian * Factory methods for file systems. This class defines the {@link #getDefault 38217739Sadrian * getDefault} method to get the default file system and factory methods to 39217739Sadrian * construct other types of file systems. 40217739Sadrian * 41217739Sadrian * <p> The first invocation of any of the methods defined by this class causes 42217739Sadrian * the default {@link FileSystemProvider provider} to be loaded. The default 43217739Sadrian * provider, identified by the URI scheme "file", creates the {@link FileSystem} 44217739Sadrian * that provides access to the file systems accessible to the Java virtual 45217739Sadrian * machine. If the process of loading or initializing the default provider fails 46217739Sadrian * then an unspecified error is thrown. 47217739Sadrian * 48217739Sadrian * <p> The first invocation of the {@link FileSystemProvider#installedProviders 49217739Sadrian * installedProviders} method, by way of invoking any of the {@code 50217739Sadrian * newFileSystem} methods defined by this class, locates and loads all 51217739Sadrian * installed file system providers. Installed providers are loaded using the 52217739Sadrian * service-provider loading facility defined by the {@link ServiceLoader} class. 53217739Sadrian * Installed providers are loaded using the system class loader. If the 54217739Sadrian * system class loader cannot be found then the extension class loader is used; 55217739Sadrian * if there is no extension class loader then the bootstrap class loader is used. 56217739Sadrian * Providers are typically installed by placing them in a JAR file on the 57217739Sadrian * application class path, the JAR file contains a 58217739Sadrian * provider-configuration file named {@code java.nio.file.spi.FileSystemProvider} 59217739Sadrian * in the resource directory {@code META-INF/services}, and the file lists one or 60217739Sadrian * more fully-qualified names of concrete subclass of {@link FileSystemProvider} 61217739Sadrian * that have a zero argument constructor. 62217739Sadrian * The ordering that installed providers are located is implementation specific. 63217739Sadrian * If a provider is instantiated and its {@link FileSystemProvider#getScheme() 64217739Sadrian * getScheme} returns the same URI scheme of a provider that was previously 65217739Sadrian * instantiated then the most recently instantiated duplicate is discarded. URI 66217739Sadrian * schemes are compared without regard to case. During construction a provider 67217739Sadrian * may safely access files associated with the default provider but care needs 68217739Sadrian * to be taken to avoid circular loading of other installed providers. If 69217739Sadrian * circular loading of installed providers is detected then an unspecified error 70217739Sadrian * is thrown. 71217739Sadrian * 72217739Sadrian * <p> This class also defines factory methods that allow a {@link ClassLoader} 73217739Sadrian * to be specified when locating a provider. As with installed providers, the 74217739Sadrian * provider classes are identified by placing the provider configuration file 75217739Sadrian * in the resource directory {@code META-INF/services}. 76217739Sadrian * 77217739Sadrian * <p> If a thread initiates the loading of the installed file system providers 78217739Sadrian * and another thread invokes a method that also attempts to load the providers 79217739Sadrian * then the method will block until the loading completes. 80217739Sadrian * 81217739Sadrian * @since 1.7 82217739Sadrian */ 83217739Sadrian 84217739Sadrianpublic final class FileSystems { 85217739Sadrian private FileSystems() { 86217739Sadrian } 87217739Sadrian 88217739Sadrian // lazy initialization of default file system 89217739Sadrian private static class DefaultFileSystemHolder { 90217739Sadrian static final FileSystem defaultFileSystem = defaultFileSystem(); 91217739Sadrian 92217739Sadrian // returns default file system 93217739Sadrian private static FileSystem defaultFileSystem() { 94217739Sadrian // load default provider 95217739Sadrian FileSystemProvider provider = AccessController 96217739Sadrian .doPrivileged(new PrivilegedAction<>() { 97217739Sadrian public FileSystemProvider run() { 98217739Sadrian return getDefaultProvider(); 99217739Sadrian } 100217739Sadrian }); 101217739Sadrian 102217739Sadrian // return file system 103217739Sadrian return provider.getFileSystem(URI.create("file:///")); 104217739Sadrian } 105217739Sadrian 106217739Sadrian // returns default provider 107217739Sadrian private static FileSystemProvider getDefaultProvider() { 108217739Sadrian FileSystemProvider provider = sun.nio.fs.DefaultFileSystemProvider.create(); 109217739Sadrian 110217739Sadrian // if the property java.nio.file.spi.DefaultFileSystemProvider is 111217739Sadrian // set then its value is the name of the default provider (or a list) 112217739Sadrian String propValue = System 113217739Sadrian .getProperty("java.nio.file.spi.DefaultFileSystemProvider"); 114217739Sadrian if (propValue != null) { 115217739Sadrian for (String cn: propValue.split(",")) { 116217739Sadrian try { 117217739Sadrian Class<?> c = Class 118217739Sadrian .forName(cn, true, ClassLoader.getSystemClassLoader()); 119217739Sadrian Constructor<?> ctor = c 120217739Sadrian .getDeclaredConstructor(FileSystemProvider.class); 121217739Sadrian provider = (FileSystemProvider)ctor.newInstance(provider); 122217739Sadrian 123217739Sadrian // must be "file" 124217739Sadrian if (!provider.getScheme().equals("file")) 125217739Sadrian throw new Error("Default provider must use scheme 'file'"); 126244969Sadrian 127217739Sadrian } catch (Exception x) { 128217739Sadrian throw new Error(x); 129217739Sadrian } 130217739Sadrian } 131217739Sadrian } 132217739Sadrian return provider; 133217739Sadrian } 134217739Sadrian } 135 136 /** 137 * Returns the default {@code FileSystem}. The default file system creates 138 * objects that provide access to the file systems accessible to the Java 139 * virtual machine. The <em>working directory</em> of the file system is 140 * the current user directory, named by the system property {@code user.dir}. 141 * This allows for interoperability with the {@link java.io.File java.io.File} 142 * class. 143 * 144 * <p> The first invocation of any of the methods defined by this class 145 * locates the default {@link FileSystemProvider provider} object. Where the 146 * system property {@code java.nio.file.spi.DefaultFileSystemProvider} is 147 * not defined then the default provider is a system-default provider that 148 * is invoked to create the default file system. 149 * 150 * <p> If the system property {@code java.nio.file.spi.DefaultFileSystemProvider} 151 * is defined then it is taken to be a list of one or more fully-qualified 152 * names of concrete provider classes identified by the URI scheme 153 * {@code "file"}. Where the property is a list of more than one name then 154 * the names are separated by a comma. Each class is loaded, using the system 155 * class loader, and instantiated by invoking a one argument constructor 156 * whose formal parameter type is {@code FileSystemProvider}. The providers 157 * are loaded and instantiated in the order they are listed in the property. 158 * If this process fails or a provider's scheme is not equal to {@code "file"} 159 * then an unspecified error is thrown. URI schemes are normally compared 160 * without regard to case but for the default provider, the scheme is 161 * required to be {@code "file"}. The first provider class is instantiated 162 * by invoking it with a reference to the system-default provider. 163 * The second provider class is instantiated by invoking it with a reference 164 * to the first provider instance. The third provider class is instantiated 165 * by invoking it with a reference to the second instance, and so on. The 166 * last provider to be instantiated becomes the default provider; its {@code 167 * getFileSystem} method is invoked with the URI {@code "file:///"} to 168 * get a reference to the default file system. 169 * 170 * <p> Subsequent invocations of this method return the file system that was 171 * returned by the first invocation. 172 * 173 * @return the default file system 174 */ 175 public static FileSystem getDefault() { 176 return DefaultFileSystemHolder.defaultFileSystem; 177 } 178 179 /** 180 * Returns a reference to an existing {@code FileSystem}. 181 * 182 * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 183 * installed} providers to locate the provider that is identified by the URI 184 * {@link URI#getScheme scheme} of the given URI. URI schemes are compared 185 * without regard to case. The exact form of the URI is highly provider 186 * dependent. If found, the provider's {@link FileSystemProvider#getFileSystem 187 * getFileSystem} method is invoked to obtain a reference to the {@code 188 * FileSystem}. 189 * 190 * <p> Once a file system created by this provider is {@link FileSystem#close 191 * closed} it is provider-dependent if this method returns a reference to 192 * the closed file system or throws {@link FileSystemNotFoundException}. 193 * If the provider allows a new file system to be created with the same URI 194 * as a file system it previously created then this method throws the 195 * exception if invoked after the file system is closed (and before a new 196 * instance is created by the {@link #newFileSystem newFileSystem} method). 197 * 198 * <p> If a security manager is installed then a provider implementation 199 * may require to check a permission before returning a reference to an 200 * existing file system. In the case of the {@link FileSystems#getDefault 201 * default} file system, no permission check is required. 202 * 203 * @param uri the URI to locate the file system 204 * 205 * @return the reference to the file system 206 * 207 * @throws IllegalArgumentException 208 * if the pre-conditions for the {@code uri} parameter are not met 209 * @throws FileSystemNotFoundException 210 * if the file system, identified by the URI, does not exist 211 * @throws ProviderNotFoundException 212 * if a provider supporting the URI scheme is not installed 213 * @throws SecurityException 214 * if a security manager is installed and it denies an unspecified 215 * permission 216 */ 217 public static FileSystem getFileSystem(URI uri) { 218 String scheme = uri.getScheme(); 219 for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 220 if (scheme.equalsIgnoreCase(provider.getScheme())) { 221 return provider.getFileSystem(uri); 222 } 223 } 224 throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); 225 } 226 227 /** 228 * Constructs a new file system that is identified by a {@link URI} 229 * 230 * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 231 * installed} providers to locate the provider that is identified by the URI 232 * {@link URI#getScheme scheme} of the given URI. URI schemes are compared 233 * without regard to case. The exact form of the URI is highly provider 234 * dependent. If found, the provider's {@link FileSystemProvider#newFileSystem(URI,Map) 235 * newFileSystem(URI,Map)} method is invoked to construct the new file system. 236 * 237 * <p> Once a file system is {@link FileSystem#close closed} it is 238 * provider-dependent if the provider allows a new file system to be created 239 * with the same URI as a file system it previously created. 240 * 241 * <p> <b>Usage Example:</b> 242 * Suppose there is a provider identified by the scheme {@code "memory"} 243 * installed: 244 * <pre> 245 * Map<String,String> env = new HashMap<>(); 246 * env.put("capacity", "16G"); 247 * env.put("blockSize", "4k"); 248 * FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env); 249 * </pre> 250 * 251 * @param uri 252 * the URI identifying the file system 253 * @param env 254 * a map of provider specific properties to configure the file system; 255 * may be empty 256 * 257 * @return a new file system 258 * 259 * @throws IllegalArgumentException 260 * if the pre-conditions for the {@code uri} parameter are not met, 261 * or the {@code env} parameter does not contain properties required 262 * by the provider, or a property value is invalid 263 * @throws FileSystemAlreadyExistsException 264 * if the file system has already been created 265 * @throws ProviderNotFoundException 266 * if a provider supporting the URI scheme is not installed 267 * @throws IOException 268 * if an I/O error occurs creating the file system 269 * @throws SecurityException 270 * if a security manager is installed and it denies an unspecified 271 * permission required by the file system provider implementation 272 */ 273 public static FileSystem newFileSystem(URI uri, Map<String,?> env) 274 throws IOException 275 { 276 return newFileSystem(uri, env, null); 277 } 278 279 /** 280 * Constructs a new file system that is identified by a {@link URI} 281 * 282 * <p> This method first attempts to locate an installed provider in exactly 283 * the same manner as the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} 284 * method. If none of the installed providers support the URI scheme then an 285 * attempt is made to locate the provider using the given class loader. If a 286 * provider supporting the URI scheme is located then its {@link 287 * FileSystemProvider#newFileSystem(URI,Map) newFileSystem(URI,Map)} is 288 * invoked to construct the new file system. 289 * 290 * @param uri 291 * the URI identifying the file system 292 * @param env 293 * a map of provider specific properties to configure the file system; 294 * may be empty 295 * @param loader 296 * the class loader to locate the provider or {@code null} to only 297 * attempt to locate an installed provider 298 * 299 * @return a new file system 300 * 301 * @throws IllegalArgumentException 302 * if the pre-conditions for the {@code uri} parameter are not met, 303 * or the {@code env} parameter does not contain properties required 304 * by the provider, or a property value is invalid 305 * @throws FileSystemAlreadyExistsException 306 * if the URI scheme identifies an installed provider and the file 307 * system has already been created 308 * @throws ProviderNotFoundException 309 * if a provider supporting the URI scheme is not found 310 * @throws ServiceConfigurationError 311 * when an error occurs while loading a service provider 312 * @throws IOException 313 * an I/O error occurs creating the file system 314 * @throws SecurityException 315 * if a security manager is installed and it denies an unspecified 316 * permission required by the file system provider implementation 317 */ 318 public static FileSystem newFileSystem(URI uri, Map<String,?> env, ClassLoader loader) 319 throws IOException 320 { 321 String scheme = uri.getScheme(); 322 323 // check installed providers 324 for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 325 if (scheme.equalsIgnoreCase(provider.getScheme())) { 326 return provider.newFileSystem(uri, env); 327 } 328 } 329 330 // if not found, use service-provider loading facility 331 if (loader != null) { 332 ServiceLoader<FileSystemProvider> sl = ServiceLoader 333 .load(FileSystemProvider.class, loader); 334 for (FileSystemProvider provider: sl) { 335 if (scheme.equalsIgnoreCase(provider.getScheme())) { 336 return provider.newFileSystem(uri, env); 337 } 338 } 339 } 340 341 throw new ProviderNotFoundException("Provider \"" + scheme + "\" not found"); 342 } 343 344 /** 345 * Constructs a new {@code FileSystem} to access the contents of a file as a 346 * file system. 347 * 348 * <p> This method makes use of specialized providers that create pseudo file 349 * systems where the contents of one or more files is treated as a file 350 * system. 351 * 352 * <p> This method iterates over the {@link FileSystemProvider#installedProviders() 353 * installed} providers. It invokes, in turn, each provider's {@link 354 * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method 355 * with an empty map. If a provider returns a file system then the iteration 356 * terminates and the file system is returned. If none of the installed 357 * providers return a {@code FileSystem} then an attempt is made to locate 358 * the provider using the given class loader. If a provider returns a file 359 * system then the lookup terminates and the file system is returned. 360 * 361 * @param path 362 * the path to the file 363 * @param loader 364 * the class loader to locate the provider or {@code null} to only 365 * attempt to locate an installed provider 366 * 367 * @return a new file system 368 * 369 * @throws ProviderNotFoundException 370 * if a provider supporting this file type cannot be located 371 * @throws ServiceConfigurationError 372 * when an error occurs while loading a service provider 373 * @throws IOException 374 * if an I/O error occurs 375 * @throws SecurityException 376 * if a security manager is installed and it denies an unspecified 377 * permission 378 */ 379 public static FileSystem newFileSystem(Path path, 380 ClassLoader loader) 381 throws IOException 382 { 383 if (path == null) 384 throw new NullPointerException(); 385 Map<String,?> env = Collections.emptyMap(); 386 387 // check installed providers 388 for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { 389 try { 390 return provider.newFileSystem(path, env); 391 } catch (UnsupportedOperationException uoe) { 392 } 393 } 394 395 // if not found, use service-provider loading facility 396 if (loader != null) { 397 ServiceLoader<FileSystemProvider> sl = ServiceLoader 398 .load(FileSystemProvider.class, loader); 399 for (FileSystemProvider provider: sl) { 400 try { 401 return provider.newFileSystem(path, env); 402 } catch (UnsupportedOperationException uoe) { 403 } 404 } 405 } 406 407 throw new ProviderNotFoundException("Provider not found"); 408 } 409} 410