jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java
changeset 2057 3acf8e5e2ca0
child 3065 452aaa2899fc
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2007-2009 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package java.nio.file.spi;
       
    27 
       
    28 import java.nio.file.*;
       
    29 import java.nio.file.attribute.FileAttribute;
       
    30 import java.nio.channels.*;
       
    31 import java.net.URI;
       
    32 import java.util.*;
       
    33 import java.util.concurrent.ExecutorService;
       
    34 import java.security.AccessController;
       
    35 import java.security.PrivilegedAction;
       
    36 import java.io.IOException;
       
    37 
       
    38 /**
       
    39  * Service-provider class for file systems.
       
    40  *
       
    41  * <p> A file system provider is a concrete implementation of this class that
       
    42  * implements the abstract methods defined by this class. A provider is
       
    43  * identified by a {@code URI} {@link #getScheme() scheme}. The default provider
       
    44  * is identified by the URI scheme "file". It creates the {@link FileSystem} that
       
    45  * provides access to the file systems accessible to the Java virtual machine.
       
    46  * The {@link FileSystems} class defines how file system providers are located
       
    47  * and loaded. The default provider is typically a system-default provider but
       
    48  * may be overridden if the system property {@code
       
    49  * java.nio.file.spi.DefaultFileSystemProvider} is set. In that case, the
       
    50  * provider has a one argument constructor whose formal parameter type is {@code
       
    51  * FileSystemProvider}. All other providers have a zero argument constructor
       
    52  * that initializes the provider.
       
    53  *
       
    54  * <p> A provider is a factory for one or more {@link FileSystem} instances. Each
       
    55  * file system is identified by a {@code URI} where the URI's scheme matches
       
    56  * the provider's {@link #getScheme scheme}. The default file system, for example,
       
    57  * is identified by the URI {@code "file:///"}. A memory-based file system,
       
    58  * for example, may be identified by a URI such as {@code "memory:///?name=logfs"}.
       
    59  * The {@link #newFileSystem newFileSystem} method may be used to create a file
       
    60  * system, and the {@link #getFileSystem getFileSystem} method may be used to
       
    61  * obtain a reference to an existing file system created by the provider. Where
       
    62  * a provider is the factory for a single file system then it is provider dependent
       
    63  * if the file system is created when the provider is initialized, or later when
       
    64  * the {@code newFileSystem} method is invoked. In the case of the default
       
    65  * provider, the {@code FileSystem} is created when the provider is initialized.
       
    66  *
       
    67  * <p> In addition to file systems, a provider is also a factory for {@link
       
    68  * FileChannel} and {@link AsynchronousFileChannel} channels. The {@link
       
    69  * #newFileChannel newFileChannel} and {@link #newAsynchronousFileChannel
       
    70  * AsynchronousFileChannel} methods are defined to open or create files, returning
       
    71  * a channel to access the file. These methods are invoked by static factory
       
    72  * methods defined in the {@link java.nio.channels} package.
       
    73  *
       
    74  * <p> All of the methods in this class are safe for use by multiple concurrent
       
    75  * threads.
       
    76  *
       
    77  * @since 1.7
       
    78  */
       
    79 
       
    80 public abstract class FileSystemProvider {
       
    81     // lock using when loading providers
       
    82     private static final Object lock = new Object();
       
    83 
       
    84     // installed providers
       
    85     private static volatile List<FileSystemProvider> installedProviders;
       
    86 
       
    87     // used to avoid recursive loading of instaled providers
       
    88     private static boolean loadingProviders  = false;
       
    89 
       
    90     private static Void checkPermission() {
       
    91         SecurityManager sm = System.getSecurityManager();
       
    92         if (sm != null)
       
    93             sm.checkPermission(new RuntimePermission("fileSystemProvider"));
       
    94         return null;
       
    95     }
       
    96     private FileSystemProvider(Void ignore) { }
       
    97 
       
    98     /**
       
    99      * Initializes a new instance of this class.
       
   100      *
       
   101      * <p> During construction a provider may safely access files associated
       
   102      * with the default provider but care needs to be taken to avoid circular
       
   103      * loading of other installed providers. If circular loading of installed
       
   104      * providers is detected then an unspecified error is thrown.
       
   105      *
       
   106      * @throws  SecurityException
       
   107      *          If a security manager has been installed and it denies
       
   108      *          {@link RuntimePermission}<tt>("fileSystemProvider")</tt>
       
   109      */
       
   110     protected FileSystemProvider() {
       
   111         this(checkPermission());
       
   112     }
       
   113 
       
   114     // loads all installed providers
       
   115     private static List<FileSystemProvider> loadInstalledProviders() {
       
   116         List<FileSystemProvider> list = new ArrayList<FileSystemProvider>();
       
   117 
       
   118         ServiceLoader<FileSystemProvider> sl = ServiceLoader
       
   119             .load(FileSystemProvider.class, ClassLoader.getSystemClassLoader());
       
   120 
       
   121         // ServiceConfigurationError may be throw here
       
   122         for (FileSystemProvider provider: sl) {
       
   123             String scheme = provider.getScheme();
       
   124 
       
   125             // add to list if the provider is not "file" and isn't a duplicate
       
   126             if (!scheme.equalsIgnoreCase("file")) {
       
   127                 boolean found = false;
       
   128                 for (FileSystemProvider p: list) {
       
   129                     if (p.getScheme().equalsIgnoreCase(scheme)) {
       
   130                         found = true;
       
   131                         break;
       
   132                     }
       
   133                 }
       
   134                 if (!found) {
       
   135                     list.add(provider);
       
   136                 }
       
   137             }
       
   138         }
       
   139         return list;
       
   140     }
       
   141 
       
   142     /**
       
   143      * Returns a list of the installed file system providers.
       
   144      *
       
   145      * <p> The first invocation of this method causes the default provider to be
       
   146      * initialized (if not already initialized) and loads any other installed
       
   147      * providers as described by the {@link FileSystems} class.
       
   148      *
       
   149      * @return  An unmodifiable list of the installed file system providers. The
       
   150      *          list contains at least one element, that is the default file
       
   151      *          system provider
       
   152      *
       
   153      * @throws  ServiceConfigurationError
       
   154      *          When an error occurs while loading a service provider
       
   155      */
       
   156     public static List<FileSystemProvider> installedProviders() {
       
   157         if (installedProviders == null) {
       
   158             // ensure default provider is initialized
       
   159             FileSystemProvider defaultProvider = FileSystems.getDefault().provider();
       
   160 
       
   161             synchronized (lock) {
       
   162                 if (installedProviders == null) {
       
   163                     if (loadingProviders) {
       
   164                         throw new Error("Circular loading of installed providers detected");
       
   165                     }
       
   166                     loadingProviders = true;
       
   167 
       
   168                     List<FileSystemProvider> list = AccessController
       
   169                         .doPrivileged(new PrivilegedAction<List<FileSystemProvider>>() {
       
   170                             @Override
       
   171                             public List<FileSystemProvider> run() {
       
   172                                 return loadInstalledProviders();
       
   173                         }});
       
   174 
       
   175                     // insert the default provider at the start of the list
       
   176                     list.add(0, defaultProvider);
       
   177 
       
   178                     installedProviders = Collections.unmodifiableList(list);
       
   179                 }
       
   180             }
       
   181         }
       
   182         return installedProviders;
       
   183     }
       
   184 
       
   185     /**
       
   186      * Returns the URI scheme that identifies this provider.
       
   187      *
       
   188      * @return  The URI scheme
       
   189      */
       
   190     public abstract String getScheme();
       
   191 
       
   192     /**
       
   193      * Constructs a new {@code FileSystem} object identified by a URI. This
       
   194      * method is invoked by the {@link FileSystems#newFileSystem(URI,Map)}
       
   195      * method to open a new file system identified by a URI.
       
   196      *
       
   197      * <p> The {@code uri} parameter is an absolute, hierarchical URI, with a
       
   198      * scheme equal (without regard to case) to the scheme supported by this
       
   199      * provider. The exact form of the URI is highly provider dependent. The
       
   200      * {@code env} parameter is a map of provider specific properties to configure
       
   201      * the file system.
       
   202      *
       
   203      * <p> This method throws {@link FileSystemAlreadyExistsException} if the
       
   204      * file system already exists because it was previously created by an
       
   205      * invocation of this method. Once a file system is {@link FileSystem#close
       
   206      * closed} it is provider-dependent if the provider allows a new file system
       
   207      * to be created with the same URI as a file system it previously created.
       
   208      *
       
   209      * @param   uri
       
   210      *          URI reference
       
   211      * @param   env
       
   212      *          A map of provider specific properties to configure the file system;
       
   213      *          may be empty
       
   214      *
       
   215      * @return  A new file system
       
   216      *
       
   217      * @throws  IllegalArgumentException
       
   218      *          If the pre-conditions for the {@code uri} parameter aren't met,
       
   219      *          or the {@code env} parameter does not contain properties required
       
   220      *          by the provider, or a property value is invalid
       
   221      * @throws  IOException
       
   222      *          An I/O error occurs creating the file system
       
   223      * @throws  SecurityException
       
   224      *          If a security manager is installed and it denies an unspecified
       
   225      *          permission required by the file system provider implementation
       
   226      * @throws  FileSystemAlreadyExistsException
       
   227      *          If the file system has already been created
       
   228      */
       
   229     public abstract FileSystem newFileSystem(URI uri, Map<String,?> env)
       
   230         throws IOException;
       
   231 
       
   232     /**
       
   233      * Returns an existing {@code FileSystem} created by this provider.
       
   234      *
       
   235      * <p> This method returns a reference to a {@code FileSystem} that was
       
   236      * created by invoking the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)}
       
   237      * method. File systems created the {@link #newFileSystem(FileRef,Map)
       
   238      * newFileSystem(FileRef,Map)} method are not returned by this method.
       
   239      * The file system is identified by its {@code URI}. Its exact form
       
   240      * is highly provider dependent. In the case of the default provider the URI's
       
   241      * path component is {@code "/"} and the authority, query and fragment components
       
   242      * are undefined (Undefined components are represented by {@code null}).
       
   243      *
       
   244      * <p> Once a file system created by this provider is {@link FileSystem#close
       
   245      * closed} it is provider-dependent if this method returns a reference to
       
   246      * the closed file system or throws {@link FileSystemNotFoundException}.
       
   247      * If the provider allows a new file system to be created with the same URI
       
   248      * as a file system it previously created then this method throws the
       
   249      * exception if invoked after the file system is closed (and before a new
       
   250      * instance is created by the {@link #newFileSystem newFileSystem} method).
       
   251      *
       
   252      * <p> If a security manager is installed then a provider implementation
       
   253      * may require to check a permission before returning a reference to an
       
   254      * existing file system. In the case of the {@link FileSystems#getDefault
       
   255      * default} file system, no permission check is required.
       
   256      *
       
   257      * @param   uri
       
   258      *          URI reference
       
   259      *
       
   260      * @return  The file system
       
   261      *
       
   262      * @throws  IllegalArgumentException
       
   263      *          If the pre-conditions for the {@code uri} parameter aren't met
       
   264      * @throws  FileSystemNotFoundException
       
   265      *          If the file system does not exist
       
   266      * @throws  SecurityException
       
   267      *          If a security manager is installed and it denies an unspecified
       
   268      *          permission.
       
   269      */
       
   270     public abstract FileSystem getFileSystem(URI uri);
       
   271 
       
   272     /**
       
   273      * Return a {@code Path} object by converting the given {@link URI}.
       
   274      *
       
   275      * <p> The exact form of the URI is file system provider dependent. In the
       
   276      * case of the default provider, the URI scheme is {@code "file"} and the
       
   277      * given URI has a non-empty path component, and undefined query, and
       
   278      * fragment components. The resulting {@code Path} is associated with the
       
   279      * default {@link FileSystems#getDefault default} {@code FileSystem}.
       
   280      *
       
   281      * <p> If a security manager is installed then a provider implementation
       
   282      * may require to check a permission. In the case of the {@link
       
   283      * FileSystems#getDefault default} file system, no permission check is
       
   284      * required.
       
   285      *
       
   286      * @param   uri
       
   287      *          The URI to convert
       
   288      *
       
   289      * @throws  IllegalArgumentException
       
   290      *          If the URI scheme does not identify this provider or other
       
   291      *          preconditions on the uri parameter do not hold
       
   292      * @throws  FileSystemNotFoundException
       
   293      *          The file system, identified by the URI, does not exist
       
   294      * @throws  SecurityException
       
   295      *          If a security manager is installed and it denies an unspecified
       
   296      *          permission.
       
   297      */
       
   298     public abstract Path getPath(URI uri);
       
   299 
       
   300     /**
       
   301      * Constructs a new {@code FileSystem} to access the contents of a file as a
       
   302      * file system.
       
   303      *
       
   304      * <p> This method is intended for specialized providers of pseudo file
       
   305      * systems where the contents of one or more files is treated as a file
       
   306      * system. The {@code file} parameter is a reference to an existing file
       
   307      * and the {@code env} parameter is a map of provider specific properties to
       
   308      * configure the file system.
       
   309      *
       
   310      * <p> If this provider does not support the creation of such file systems
       
   311      * or if the provider does not recognize the file type of the given file then
       
   312      * it throws {@code UnsupportedOperationException}. The default implementation
       
   313      * of this method throws {@code UnsupportedOperationException}.
       
   314      *
       
   315      * @param   file
       
   316      *          The file
       
   317      * @param   env
       
   318      *          A map of provider specific properties to configure the file system;
       
   319      *          may be empty
       
   320      *
       
   321      * @return  A new file system
       
   322      *
       
   323      * @throws  UnsupportedOperationException
       
   324      *          If this provider does not support access to the contents as a
       
   325      *          file system or it does not recognize the file type of the
       
   326      *          given file
       
   327      * @throws  IllegalArgumentException
       
   328      *          If the {@code env} parameter does not contain properties required
       
   329      *          by the provider, or a property value is invalid
       
   330      * @throws  IOException
       
   331      *          If an I/O error occurs
       
   332      * @throws  SecurityException
       
   333      *          If a security manager is installed and it denies an unspecified
       
   334      *          permission.
       
   335      */
       
   336     public FileSystem newFileSystem(FileRef file, Map<String,?> env)
       
   337         throws IOException
       
   338     {
       
   339         throw new UnsupportedOperationException();
       
   340     }
       
   341 
       
   342     /**
       
   343      * Opens or creates a file for reading and/or writing, returning a file
       
   344      * channel to access the file.
       
   345      *
       
   346      * <p> This method is invoked by the {@link FileChannel#open(Path,Set,FileAttribute[])
       
   347      * FileChannel.open} method to open a file channel. A provider that does not
       
   348      * support all the features required to construct a file channel throws
       
   349      * {@code UnsupportedOperationException}. The default provider is required
       
   350      * to support the creation of file channels. When not overridden, the
       
   351      * default implementation throws {@code UnsupportedOperationException}.
       
   352      *
       
   353      * @param   path
       
   354      *          The path of the file to open or create
       
   355      * @param   options
       
   356      *          Options specifying how the file is opened
       
   357      * @param   attrs
       
   358      *          An optional list of file attributes to set atomically when
       
   359      *          creating the file
       
   360      *
       
   361      * @return  A new file channel
       
   362      *
       
   363      * @throws  IllegalArgumentException
       
   364      *          If the set contains an invalid combination of options
       
   365      * @throws  UnsupportedOperationException
       
   366      *          If this provider that does not support creating file channels,
       
   367      *          or an unsupported open option or file attribute is specified
       
   368      * @throws  IOException
       
   369      *          If an I/O error occurs
       
   370      * @throws  SecurityException
       
   371      *          In the case of the default file system, the {@link
       
   372      *          SecurityManager#checkRead(String)} method is invoked to check
       
   373      *          read access if the file is opened for reading. The {@link
       
   374      *          SecurityManager#checkWrite(String)} method is invoked to check
       
   375      *          write access if the file is opened for writing
       
   376      */
       
   377     public FileChannel newFileChannel(Path path,
       
   378                                       Set<? extends OpenOption> options,
       
   379                                       FileAttribute<?>... attrs)
       
   380         throws IOException
       
   381     {
       
   382         throw new UnsupportedOperationException();
       
   383     }
       
   384 
       
   385     /**
       
   386      * Opens or creates a file for reading and/or writing, returning an
       
   387      * asynchronous file channel to access the file.
       
   388      *
       
   389      * <p> This method is invoked by the {@link
       
   390      * AsynchronousFileChannel#open(Path,Set,ExecutorService,FileAttribute[])
       
   391      * AsynchronousFileChannel.open} method to open an asynchronous file channel.
       
   392      * A provider that does not support all the features required to construct
       
   393      * an asynchronous file channel throws {@code UnsupportedOperationException}.
       
   394      * The default provider is required to support the creation of asynchronous
       
   395      * file channels. When not overridden, the default implementation of this
       
   396      * method throws {@code UnsupportedOperationException}.
       
   397      *
       
   398      * @param   path
       
   399      *          The path of the file to open or create
       
   400      * @param   options
       
   401      *          Options specifying how the file is opened
       
   402      * @param   executor
       
   403      *          The thread pool or {@code null} to associate the channel with
       
   404      *          the default thread pool
       
   405      * @param   attrs
       
   406      *          An optional list of file attributes to set atomically when
       
   407      *          creating the file
       
   408      *
       
   409      * @return  A new asynchronous file channel
       
   410      *
       
   411      * @throws  IllegalArgumentException
       
   412      *          If the set contains an invalid combination of options
       
   413      * @throws  UnsupportedOperationException
       
   414      *          If this provider that does not support creating asynchronous file
       
   415      *          channels, or an unsupported open option or file attribute is
       
   416      *          specified
       
   417      * @throws  IOException
       
   418      *          If an I/O error occurs
       
   419      * @throws  SecurityException
       
   420      *          In the case of the default file system, the {@link
       
   421      *          SecurityManager#checkRead(String)} method is invoked to check
       
   422      *          read access if the file is opened for reading. The {@link
       
   423      *          SecurityManager#checkWrite(String)} method is invoked to check
       
   424      *          write access if the file is opened for writing
       
   425      */
       
   426     public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
       
   427                                                               Set<? extends OpenOption> options,
       
   428                                                               ExecutorService executor,
       
   429                                                               FileAttribute<?>... attrs)
       
   430         throws IOException
       
   431     {
       
   432         throw new UnsupportedOperationException();
       
   433     }
       
   434 }