This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git


The following commit(s) were added to refs/heads/master by this push:
     new 923a571  Sort methods.
923a571 is described below

commit 923a5715a060c10fb462c4bdfd53fd37fa4531bd
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Mon Apr 5 10:32:21 2021 -0400

    Sort methods.
---
 .../vfs2/impl/DefaultFileSystemManager.java        | 1052 ++++++++++----------
 1 file changed, 526 insertions(+), 526 deletions(-)

diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
index c5fb7b1..dd56a15 100644
--- 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
+++ 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemManager.java
@@ -64,6 +64,22 @@ import org.apache.commons.vfs2.provider.VfsComponent;
 public class DefaultFileSystemManager implements FileSystemManager {
 
     /**
+     * This is an internal class because it needs access to the private member 
providers.
+     */
+    final class VfsStreamHandlerFactory implements URLStreamHandlerFactory {
+        @Override
+        public URLStreamHandler createURLStreamHandler(final String protocol) {
+            final FileProvider provider = providers.get(protocol);
+            if (provider != null) {
+                return new DefaultURLStreamHandler(context);
+            }
+
+            // Route all other calls to the default URLStreamHandlerFactory
+            return new URLStreamHandlerProxy();
+        }
+    }
+
+    /**
      * Mapping from URI scheme to FileProvider.
      */
     private final Map<String, FileProvider> providers = new HashMap<>();
@@ -122,11 +138,11 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
      * The cache strategy
      */
     private CacheStrategy fileCacheStrategy;
-
     /**
      * Class which decorates all returned fileObjects
      */
     private Class<?> fileObjectDecorator;
+
     /**
      * Reflection constructor extracted from {@link #fileObjectDecorator}
      */
@@ -158,12 +174,84 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     private boolean init;
 
     /**
-     * Returns the logger used by this manager.
+     * Closes the given file system.
+     * <p>
+     * If you use VFS as singleton it is VERY dangerous to call this method
+     * </p>
      *
-     * @return the Logger.
+     * @param fileSystem The FileSystem to close.
      */
-    protected Log getLogger() {
-        return log;
+    public void _closeFileSystem(final FileSystem fileSystem) {
+        final FileProvider provider = 
providers.get(fileSystem.getRootName().getScheme());
+        if (provider != null) {
+            ((AbstractFileProvider) provider).closeFileSystem(fileSystem);
+        } else if (fileSystem instanceof VirtualFileSystem) {
+            // vfsProvider does not implement AbstractFileProvider
+            vfsProvider.closeFileSystem(fileSystem);
+        }
+    }
+
+    /**
+     * Adds an file name extension mapping.
+     *
+     * @param extension The file name extension.
+     * @param scheme The scheme to use for files with this extension.
+     */
+    public void addExtensionMap(final String extension, final String scheme) {
+        typeMap.addExtension(extension, scheme);
+    }
+
+    /**
+     * Adds a mime type mapping.
+     *
+     * @param mimeType The mime type.
+     * @param scheme The scheme to use for files with this mime type.
+     */
+    public void addMimeTypeMap(final String mimeType, final String scheme) {
+        typeMap.addMimeType(mimeType, scheme);
+    }
+
+    /**
+     * Adds the specified FileOperationProvider for the specified scheme. 
Several FileOperationProvider's might be
+     * registered for the same scheme. For example, for "file" scheme we can 
register SvnWsOperationProvider and
+     * CvsOperationProvider.
+     *
+     * @param scheme The scheme the provider should be registered for.
+     * @param operationProvider The FileOperationProvider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    @Override
+    public void addOperationProvider(final String scheme, final 
FileOperationProvider operationProvider)
+            throws FileSystemException {
+        addOperationProvider(new String[] { scheme }, operationProvider);
+    }
+
+    /**
+     * @see FileSystemManager#addOperationProvider(String, 
org.apache.commons.vfs2.operations.FileOperationProvider)
+     *
+     * @param schemes The array of schemes the provider should apply to.
+     * @param operationProvider The FileOperationProvider.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public void addOperationProvider(final String[] schemes, final 
FileOperationProvider operationProvider)
+            throws FileSystemException {
+        for (final String scheme : schemes) {
+            if (!operationProviders.containsKey(scheme)) {
+                final List<FileOperationProvider> providers = new 
ArrayList<>();
+                operationProviders.put(scheme, providers);
+            }
+
+            final List<FileOperationProvider> providers = 
operationProviders.get(scheme);
+
+            if (providers.contains(operationProvider)) {
+                throw new 
FileSystemException("vfs.operation/operation-provider-already-added.error", 
scheme);
+            }
+
+            setupComponent(operationProvider);
+
+            providers.add(operationProvider);
+        }
     }
 
     /**
@@ -211,110 +299,212 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
         }
     }
 
+    protected void addVirtualFileSystemScheme(String rootUri) {
+        if (rootUri.indexOf(':') != -1) {
+            rootUri = rootUri.substring(0, rootUri.indexOf(':'));
+        }
+        virtualFileSystemSchemes.add(rootUri);
+    }
+
     /**
-     * Unregisters a file system provider.
+     * Determines if a layered file system can be created for a given file.
      *
-     * @param urlScheme The scheme of the provider.
-     * @since 2.8.0
+     * @param file The file to check for.
+     * @return true if the FileSystem can be created.
+     * @throws FileSystemException if an error occurs.
      */
-    public void removeProvider(final String urlScheme) {
-        final FileProvider provider = providers.remove(urlScheme);
-        // check whether the same instance is not used somewhere else
-        if (provider != null && !providers.containsValue(provider)) {
-            closeComponent(provider);
-        }
+    @Override
+    public boolean canCreateFileSystem(final FileObject file) throws 
FileSystemException {
+        return typeMap.getScheme(file) != null;
     }
 
     /**
-     * Returns true if this manager has a provider for a particular scheme.
-     *
-     * @param scheme The scheme to check.
-     * @return true if a provider is configured for this scheme, false 
otherwise.
+     * Closes the manager.
+     * <p>
+     * This will close all providers (all files), it will also close all 
managed components including temporary files,
+     * replicator, file cache and file operations.
+     * </p>
+     * <p>
+     * The manager is in uninitialized state after this method.
+     * </p>
      */
     @Override
-    public boolean hasProvider(final String scheme) {
-        return providers.containsKey(scheme);
+    public void close() {
+        if (!init) {
+            return;
+        }
+
+        // make sure all discovered components in
+        // 
org.apache.commons.vfs2.impl.StandardFileSystemManager.configure(Element)
+        // are closed here
+
+        // Close the file system providers.
+        providers.values().forEach(this::closeComponent);
+
+        // Close the other components
+        closeComponent(vfsProvider);
+        closeComponent(fileReplicator);
+        closeComponent(tempFileStore);
+        closeComponent(defaultProvider);
+
+        // unregister all providers here, so if any components have local file 
references
+        // they can still resolve against the supported schemes
+        providers.clear();
+
+        // FileOperations are components, too
+        operationProviders.values().forEach(opProviders -> 
opProviders.forEach(this::closeComponent));
+
+        // unregister all
+        operationProviders.clear();
+
+        // collections with add()
+        typeMap.clear();
+
+        // Close cache last.
+        closeComponent(filesCache);
+
+        // should not happen, but make debugging easier:
+        if (!components.isEmpty()) {
+            log.warn("DefaultFilesystemManager.close: not all components are 
closed: " + components.toString());
+        }
+        components.clear();
+
+        // managed components
+        vfsProvider = null;
+
+        // virtual schemas
+        virtualFileSystemSchemes.clear();
+
+        // setters and derived state
+        defaultProvider = null;
+        baseFile = null;
+        fileObjectDecorator = null;
+        fileObjectDecoratorConst = null;
+        localFileProvider = null;
+        fileReplicator = null;
+        tempFileStore = null;
+        // setters with init() defaults
+        filesCache = null;
+        fileCacheStrategy = null;
+        fileContentInfoFactory = null;
+
+        init = false;
     }
 
     /**
-     * Adds an file name extension mapping.
+     * Closes a component, if it has not already been closed.
      *
-     * @param extension The file name extension.
-     * @param scheme The scheme to use for files with this extension.
+     * @param component The component to close.
      */
-    public void addExtensionMap(final String extension, final String scheme) {
-        typeMap.addExtension(extension, scheme);
+    private void closeComponent(final Object component) {
+        if (component != null && components.contains(component)) {
+            if (component instanceof VfsComponent) {
+                ((VfsComponent) component).close();
+            }
+            components.remove(component);
+        }
     }
 
     /**
-     * Adds a mime type mapping.
+     * Closes the given file system.
+     * <p>
+     * If you use VFS as singleton it is VERY dangerous to call this method.
+     * </p>
      *
-     * @param mimeType The mime type.
-     * @param scheme The scheme to use for files with this mime type.
+     * @param fileSystem The FileSystem to close.
      */
-    public void addMimeTypeMap(final String mimeType, final String scheme) {
-        typeMap.addMimeType(mimeType, scheme);
+    @Override
+    public void closeFileSystem(final FileSystem fileSystem) {
+        // inform the cache ...
+        getFilesCache().clear(fileSystem);
+
+        // just in case the cache didnt call _closeFileSystem
+        _closeFileSystem(fileSystem);
     }
 
     /**
-     * Sets the default provider. This is the provider that will handle URI 
with unknown schemes. The manager takes care
-     * of all lifecycle management.
+     * Creates a layered file system.
      *
-     * @param provider The FileProvider.
-     * @throws FileSystemException if an error occurs setting the provider.
+     * @param file The FileObject to use.
+     * @return The layered FileObject.
+     * @throws FileSystemException if an error occurs.
      */
-    public void setDefaultProvider(final FileProvider provider) throws 
FileSystemException {
-        setupComponent(provider);
-        defaultProvider = provider;
+    @Override
+    public FileObject createFileSystem(final FileObject file) throws 
FileSystemException {
+        final String scheme = typeMap.getScheme(file);
+        FileSystemException.requireNonNull(scheme, 
"vfs.impl/no-provider-for-file.error", file);
+        return createFileSystem(scheme, file);
     }
 
     /**
-     * Returns the filesCache implementation used to cache files.
+     * Creates a layered file system.
      *
-     * @return The FilesCache.
+     * @param scheme The scheme to use.
+     * @param file The FileObject.
+     * @return The layered FileObject.
+     * @throws FileSystemException if an error occurs.
      */
     @Override
-    public FilesCache getFilesCache() {
-        return filesCache;
+    public FileObject createFileSystem(final String scheme, final FileObject 
file) throws FileSystemException {
+        final FileProvider provider = providers.get(scheme);
+        FileSystemException.requireNonNull(provider, 
"vfs.impl/unknown-provider.error", scheme, file);
+        return provider.createFileSystem(scheme, file, 
file.getFileSystem().getFileSystemOptions());
     }
 
     /**
-     * Sets the filesCache implementation used to cache files.
-     * <p>
-     * Can only be set before the FileSystemManager is initialized.
-     * </p>
-     * <p>
-     * The manager takes care of the lifecycle. If none is set, a default is 
picked in {@link #init()}.
-     * </p>
+     * Creates a virtual file system.
      *
-     * @param filesCache The FilesCache.
-     * @throws FileSystemException if an error occurs setting the cache..
+     * @param rootFile The FileObject to use.
+     * @return The FileObject in the VirtualFileSystem.
+     * @throws FileSystemException if an error occurs creating the file.
      */
-    public void setFilesCache(final FilesCache filesCache) throws 
FileSystemException {
-        if (init) {
-            throw new FileSystemException("vfs.impl/already-inited.error");
-        }
-        this.filesCache = filesCache;
+    @Override
+    public FileObject createVirtualFileSystem(final FileObject rootFile) 
throws FileSystemException {
+        final FileObject fileObject = vfsProvider.createFileSystem(rootFile);
+        addVirtualFileSystemScheme(rootFile.getName().getScheme());
+        return fileObject;
     }
 
     /**
-     * Set the cache strategy to use when dealing with file object data.
-     * <p>
-     * Can only be set before the FileSystemManager is initialized.
-     * </p>
-     * <p>
-     * The default is {@link CacheStrategy#ON_RESOLVE}.
-     * </p>
+     * Creates an empty virtual file system.
      *
-     * @param fileCacheStrategy The CacheStrategy to use.
-     * @throws FileSystemException if this is not possible. e.g. it is already 
set.
+     * @param rootUri The URI to use as the root of the FileSystem.
+     * @return A FileObject in the virtual FileSystem.
+     * @throws FileSystemException if an error occurs.
      */
-    public void setCacheStrategy(final CacheStrategy fileCacheStrategy) throws 
FileSystemException {
-        if (init) {
-            throw new FileSystemException("vfs.impl/already-inited.error");
+    @Override
+    public FileObject createVirtualFileSystem(final String rootUri) throws 
FileSystemException {
+        final FileObject fileObject = vfsProvider.createFileSystem(rootUri);
+        addVirtualFileSystemScheme(rootUri);
+        return fileObject;
+    }
+
+    /**
+     * Free all resources used by unused file systems created by this manager.
+     */
+    public void freeUnusedResources() {
+        if (!init) {
+            return;
         }
 
-        this.fileCacheStrategy = fileCacheStrategy;
+        // Close the providers.
+        for (final FileProvider fileProvider : providers.values()) {
+            if (fileProvider instanceof AbstractFileProvider) {
+                ((AbstractFileProvider) fileProvider).freeUnusedResources();
+            }
+        }
+        // vfsProvider does not need to free resources
+    }
+
+    /**
+     * Returns the base file used to resolve relative URI.
+     *
+     * @return The FileObject that represents the base file.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public FileObject getBaseFile() throws FileSystemException {
+        return baseFile;
     }
 
     /**
@@ -328,6 +518,16 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
+     * get the fileContentInfoFactory used to determine the infos of a file 
content.
+     *
+     * @return The FileContentInfoFactory.
+     */
+    @Override
+    public FileContentInfoFactory getFileContentInfoFactory() {
+        return fileContentInfoFactory;
+    }
+
+    /**
      * Get the file object decorator used.
      *
      * @return The decorator.
@@ -348,131 +548,82 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
-     * Set a fileObject decorator to be used for ALL returned file objects.
-     * <p>
-     * Can only be set before the FileSystemManager is initialized.
-     * </p>
+     * Returns the filesCache implementation used to cache files.
      *
-     * @param fileObjectDecorator must be inherted from {@link 
DecoratedFileObject} a has to provide a constructor with
-     *            a single {@link FileObject} as argument
-     * @throws FileSystemException if an error occurs setting the decorator.
+     * @return The FilesCache.
      */
-    public void setFileObjectDecorator(final Class<?> fileObjectDecorator) 
throws FileSystemException {
-        if (init) {
-            throw new FileSystemException("vfs.impl/already-inited.error");
-        }
-        if (!DecoratedFileObject.class.isAssignableFrom(fileObjectDecorator)) {
-            throw new FileSystemException("vfs.impl/invalid-decorator.error", 
fileObjectDecorator.getName());
-        }
-
-        try {
-            fileObjectDecoratorConst = 
fileObjectDecorator.getConstructor(FileObject.class);
-        } catch (final NoSuchMethodException e) {
-            throw new FileSystemException("vfs.impl/invalid-decorator.error", 
fileObjectDecorator.getName(), e);
-        }
-
-        this.fileObjectDecorator = fileObjectDecorator;
+    @Override
+    public FilesCache getFilesCache() {
+        return filesCache;
     }
 
     /**
-     * get the fileContentInfoFactory used to determine the infos of a file 
content.
+     * Get the configuration builder for the given scheme.
      *
-     * @return The FileContentInfoFactory.
+     * @param scheme The scheme to locate.
+     * @return The FileSystemConfigBuilder for the scheme.
+     * @throws FileSystemException if the given scheme is not konwn
      */
     @Override
-    public FileContentInfoFactory getFileContentInfoFactory() {
-        return fileContentInfoFactory;
+    public FileSystemConfigBuilder getFileSystemConfigBuilder(final String 
scheme) throws FileSystemException {
+        final FileProvider provider = providers.get(scheme);
+        FileSystemException.requireNonNull(provider, 
"vfs.impl/unknown-scheme.error", scheme);
+        return provider.getConfigBuilder();
     }
 
     /**
-     * set the fileContentInfoFactory used to determine the infos of a file 
content.
+     * Locates the local file provider.
      * <p>
-     * Can only be set before the FileSystemManager is initialized.
+     * The local file provider is the first {@linkplain #addProvider(String[], 
FileProvider) provider added}
+     * implementing {@link LocalFileProvider}.
      * </p>
      *
-     * @param fileContentInfoFactory The FileContentInfoFactory.
-     * @throws FileSystemException if an error occurs setting the 
FileContentInfoFactory.
+     * @return The LocalFileProvider.
+     * @throws FileSystemException if no local file provider was set.
      */
-    public void setFileContentInfoFactory(final FileContentInfoFactory 
fileContentInfoFactory)
-            throws FileSystemException {
-        if (init) {
-            throw new FileSystemException("vfs.impl/already-inited.error");
-        }
-
-        this.fileContentInfoFactory = fileContentInfoFactory;
+    private LocalFileProvider getLocalFileProvider() throws 
FileSystemException {
+        return FileSystemException.requireNonNull(localFileProvider, 
"vfs.impl/no-local-file-provider.error");
     }
 
     /**
-     * Sets the file replicator to use.
-     * <p>
-     * The manager takes care of all lifecycle management.
-     * </p>
+     * Returns the logger used by this manager.
      *
-     * @param replicator The FileReplicator.
-     * @throws FileSystemException if an error occurs setting the replicator.
+     * @return the Logger.
      */
-    public void setReplicator(final FileReplicator replicator) throws 
FileSystemException {
-        setupComponent(replicator);
-        fileReplicator = replicator;
+    protected Log getLogger() {
+        return log;
     }
 
     /**
-     * Sets the temporary file store to use.
-     * <p>
-     * The manager takes care of all lifecycle management.
-     * </p>
+     * @param scheme the scheme for wich we want to get the list af registered 
providers.
      *
-     * @param tempFileStore The temporary FileStore.
-     * @throws FileSystemException if an error occurs adding the file store.
-     */
-    public void setTemporaryFileStore(final TemporaryFileStore tempFileStore) 
throws FileSystemException {
-        setupComponent(tempFileStore);
-        this.tempFileStore = tempFileStore;
-    }
-
-    /**
-     * Sets the logger to use.
-     * <p>
-     * This overwrites the default logger for this manager and is not reset in 
{@link #close()}.
-     * </p>
+     * @return the registered FileOperationProviders for the specified scheme. 
If there were no providers registered for
+     *         the scheme, it returns null.
      *
-     * @param log The Logger to use.
+     * @throws FileSystemException if an error occurs.
      */
     @Override
-    public void setLogger(final Log log) {
-        this.log = log;
-    }
+    public FileOperationProvider[] getOperationProviders(final String scheme) 
throws FileSystemException {
 
-    /**
-     * Initializes a component, if it has not already been initialized.
-     *
-     * @param component The component to setup.
-     * @throws FileSystemException if an error occurs.
-     */
-    private void setupComponent(final Object component) throws 
FileSystemException {
-        if (!components.contains(component)) {
-            if (component instanceof VfsComponent) {
-                final VfsComponent vfsComponent = (VfsComponent) component;
-                vfsComponent.setLogger(getLogger());
-                vfsComponent.setContext(context);
-                vfsComponent.init();
-            }
-            components.add(component);
+        final List<?> providers = operationProviders.get(scheme);
+        if (providers == null || providers.isEmpty()) {
+            return null;
         }
+        return providers.toArray(new FileOperationProvider[] {});
     }
 
     /**
-     * Closes a component, if it has not already been closed.
+     * Get the capabilities for a given scheme.
      *
-     * @param component The component to close.
+     * @param scheme The scheme to located.
+     * @return A Collection of capabilities.
+     * @throws FileSystemException if the given scheme is not konwn
      */
-    private void closeComponent(final Object component) {
-        if (component != null && components.contains(component)) {
-            if (component instanceof VfsComponent) {
-                ((VfsComponent) component).close();
-            }
-            components.remove(component);
-        }
+    @Override
+    public Collection<Capability> getProviderCapabilities(final String scheme) 
throws FileSystemException {
+        final FileProvider provider = providers.get(scheme);
+        FileSystemException.requireNonNull(provider, 
"vfs.impl/unknown-scheme.error", scheme);
+        return provider.getCapabilities();
     }
 
     /**
@@ -486,6 +637,19 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
+     * Get the schemes currently available.
+     *
+     * @return The array of scheme names.
+     */
+    @Override
+    public String[] getSchemes() {
+        final List<String> schemes = new ArrayList<>(providers.size() + 
virtualFileSystemSchemes.size());
+        schemes.addAll(providers.keySet());
+        schemes.addAll(virtualFileSystemSchemes);
+        return schemes.toArray(new String[]{});
+    }
+
+    /**
      * Returns the temporary file store.
      *
      * @return The file store. Never returns null.
@@ -496,6 +660,27 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
+     * Get the URLStreamHandlerFactory.
+     *
+     * @return The URLStreamHandlerFactory.
+     */
+    @Override
+    public URLStreamHandlerFactory getURLStreamHandlerFactory() {
+        return new VfsStreamHandlerFactory();
+    }
+
+    /**
+     * Returns true if this manager has a provider for a particular scheme.
+     *
+     * @param scheme The scheme to check.
+     * @return true if a provider is configured for this scheme, false 
otherwise.
+     */
+    @Override
+    public boolean hasProvider(final String scheme) {
+        return providers.containsKey(scheme);
+    }
+
+    /**
      * Initializes this manager.
      * <p>
      * If no value for the following properties was specified, it will use the 
following defaults:
@@ -528,152 +713,17 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
-     * Closes the manager.
-     * <p>
-     * This will close all providers (all files), it will also close all 
managed components including temporary files,
-     * replicator, file cache and file operations.
-     * </p>
-     * <p>
-     * The manager is in uninitialized state after this method.
-     * </p>
-     */
-    @Override
-    public void close() {
-        if (!init) {
-            return;
-        }
-
-        // make sure all discovered components in
-        // 
org.apache.commons.vfs2.impl.StandardFileSystemManager.configure(Element)
-        // are closed here
-
-        // Close the file system providers.
-        providers.values().forEach(this::closeComponent);
-
-        // Close the other components
-        closeComponent(vfsProvider);
-        closeComponent(fileReplicator);
-        closeComponent(tempFileStore);
-        closeComponent(defaultProvider);
-
-        // unregister all providers here, so if any components have local file 
references
-        // they can still resolve against the supported schemes
-        providers.clear();
-
-        // FileOperations are components, too
-        operationProviders.values().forEach(opProviders -> 
opProviders.forEach(this::closeComponent));
-
-        // unregister all
-        operationProviders.clear();
-
-        // collections with add()
-        typeMap.clear();
-
-        // Close cache last.
-        closeComponent(filesCache);
-
-        // should not happen, but make debugging easier:
-        if (!components.isEmpty()) {
-            log.warn("DefaultFilesystemManager.close: not all components are 
closed: " + components.toString());
-        }
-        components.clear();
-
-        // managed components
-        vfsProvider = null;
-
-        // virtual schemas
-        virtualFileSystemSchemes.clear();
-
-        // setters and derived state
-        defaultProvider = null;
-        baseFile = null;
-        fileObjectDecorator = null;
-        fileObjectDecoratorConst = null;
-        localFileProvider = null;
-        fileReplicator = null;
-        tempFileStore = null;
-        // setters with init() defaults
-        filesCache = null;
-        fileCacheStrategy = null;
-        fileContentInfoFactory = null;
-
-        init = false;
-    }
-
-    /**
-     * Free all resources used by unused file systems created by this manager.
-     */
-    public void freeUnusedResources() {
-        if (!init) {
-            return;
-        }
-
-        // Close the providers.
-        for (final FileProvider fileProvider : providers.values()) {
-            if (fileProvider instanceof AbstractFileProvider) {
-                ((AbstractFileProvider) fileProvider).freeUnusedResources();
-            }
-        }
-        // vfsProvider does not need to free resources
-    }
-
-    /**
-     * Sets the base file to use when resolving relative URI.
-     *
-     * @param baseFile The new base FileObject.
-     * @throws FileSystemException if an error occurs.
-     */
-    public void setBaseFile(final FileObject baseFile) throws 
FileSystemException {
-        this.baseFile = baseFile;
-    }
-
-    /**
-     * Sets the base file to use when resolving relative URI.
-     *
-     * @param baseFile The new base FileObject.
-     * @throws FileSystemException if an error occurs.
-     */
-    public void setBaseFile(final File baseFile) throws FileSystemException {
-        this.baseFile = getLocalFileProvider().findLocalFile(baseFile);
-    }
-
-    /**
-     * Returns the base file used to resolve relative URI.
-     *
-     * @return The FileObject that represents the base file.
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public FileObject getBaseFile() throws FileSystemException {
-        return baseFile;
-    }
-
-    /**
-     * Locates a file by URI.
-     *
-     * @param uri The URI of the file to locate.
-     * @return The FileObject for the located file.
-     * @throws FileSystemException if the file cannot be located or an error 
occurs.
-     */
-    @Override
-    public FileObject resolveFile(final String uri) throws FileSystemException 
{
-        return resolveFile(getBaseFile(), uri);
-    }
-
-    /**
-     * Locate a file by URI, use the FileSystemOptions for file-system 
creation.
+     * Unregisters a file system provider.
      *
-     * @param uri The URI of the file to locate.
-     * @param fileSystemOptions The options for the FileSystem.
-     * @return The FileObject for the located file.
-     * @throws FileSystemException if the file cannot be located or an error 
occurs.
+     * @param urlScheme The scheme of the provider.
+     * @since 2.8.0
      */
-
-    @Override
-    public FileObject resolveFile(final String uri, final FileSystemOptions 
fileSystemOptions)
-            throws FileSystemException {
-        // return resolveFile(baseFile, uri, fileSystemOptions);
-        return resolveFile(getBaseFile(), uri, fileSystemOptions);
+    public void removeProvider(final String urlScheme) {
+        final FileProvider provider = providers.remove(urlScheme);
+        // check whether the same instance is not used somewhere else
+        if (provider != null && !providers.containsValue(provider)) {
+            closeComponent(provider);
+        }
     }
 
     /**
@@ -758,6 +808,65 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
+     * Locates a file by URI.
+     *
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error 
occurs.
+     */
+    @Override
+    public FileObject resolveFile(final String uri) throws FileSystemException 
{
+        return resolveFile(getBaseFile(), uri);
+    }
+
+    /**
+     * Locate a file by URI, use the FileSystemOptions for file-system 
creation.
+     *
+     * @param uri The URI of the file to locate.
+     * @param fileSystemOptions The options for the FileSystem.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error 
occurs.
+     */
+
+    @Override
+    public FileObject resolveFile(final String uri, final FileSystemOptions 
fileSystemOptions)
+            throws FileSystemException {
+        // return resolveFile(baseFile, uri, fileSystemOptions);
+        return resolveFile(getBaseFile(), uri, fileSystemOptions);
+    }
+
+    /**
+     * Converts a URI into a {@link FileObject}.
+     *
+     * @param uri The URI to convert.
+     * @return The {@link FileObject} that represents the URI. Never returns 
null.
+     * @throws FileSystemException On error converting the URI.
+     * @since 2.1
+     */
+    @Override
+    public FileObject resolveFile(final URI uri) throws FileSystemException {
+        // TODO Push the URI deeper into VFS
+        return resolveFile(baseFile, uri.toString(), null);
+    }
+
+    /**
+     * Converts a URL into a {@link FileObject}.
+     *
+     * @param url The URL to convert.
+     * @return The {@link FileObject} that represents the URL. Never returns 
null.
+     * @throws FileSystemException On error converting the URL.
+     * @since 2.1
+     */
+    @Override
+    public FileObject resolveFile(final URL url) throws FileSystemException {
+        try {
+            return this.resolveFile(url.toURI());
+        } catch (final URISyntaxException e) {
+            throw new FileSystemException(e);
+        }
+    }
+
+    /**
      * Resolves a name, relative to the file. If the supplied name is an 
absolute path, then it is resolved relative to
      * the root of the file system that the file belongs to. If a relative 
name is supplied, then it is resolved
      * relative to this file name.
@@ -772,6 +881,7 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
         return resolveName(root, path, NameScope.FILE_SYSTEM);
     }
 
+
     /**
      * Resolves a name, relative to the root.
      *
@@ -891,302 +1001,192 @@ public class DefaultFileSystemManager implements 
FileSystemManager {
     }
 
     /**
-     * Converts a local file into a {@link FileObject}.
+     * Sets the base file to use when resolving relative URI.
      *
-     * @param file The input File.
-     * @return the create FileObject
-     * @throws FileSystemException if an error occurs creating the file.
+     * @param baseFile The new base FileObject.
+     * @throws FileSystemException if an error occurs.
      */
-    @Override
-    public FileObject toFileObject(final File file) throws FileSystemException 
{
-        return getLocalFileProvider().findLocalFile(file);
+    public void setBaseFile(final File baseFile) throws FileSystemException {
+        this.baseFile = getLocalFileProvider().findLocalFile(baseFile);
     }
 
     /**
-     * Creates a layered file system.
+     * Sets the base file to use when resolving relative URI.
      *
-     * @param scheme The scheme to use.
-     * @param file The FileObject.
-     * @return The layered FileObject.
+     * @param baseFile The new base FileObject.
      * @throws FileSystemException if an error occurs.
      */
-    @Override
-    public FileObject createFileSystem(final String scheme, final FileObject 
file) throws FileSystemException {
-        final FileProvider provider = providers.get(scheme);
-        FileSystemException.requireNonNull(provider, 
"vfs.impl/unknown-provider.error", scheme, file);
-        return provider.createFileSystem(scheme, file, 
file.getFileSystem().getFileSystemOptions());
+    public void setBaseFile(final FileObject baseFile) throws 
FileSystemException {
+        this.baseFile = baseFile;
     }
 
     /**
-     * Creates a layered file system.
+     * Set the cache strategy to use when dealing with file object data.
+     * <p>
+     * Can only be set before the FileSystemManager is initialized.
+     * </p>
+     * <p>
+     * The default is {@link CacheStrategy#ON_RESOLVE}.
+     * </p>
      *
-     * @param file The FileObject to use.
-     * @return The layered FileObject.
-     * @throws FileSystemException if an error occurs.
+     * @param fileCacheStrategy The CacheStrategy to use.
+     * @throws FileSystemException if this is not possible. e.g. it is already 
set.
      */
-    @Override
-    public FileObject createFileSystem(final FileObject file) throws 
FileSystemException {
-        final String scheme = typeMap.getScheme(file);
-        FileSystemException.requireNonNull(scheme, 
"vfs.impl/no-provider-for-file.error", file);
-        return createFileSystem(scheme, file);
+    public void setCacheStrategy(final CacheStrategy fileCacheStrategy) throws 
FileSystemException {
+        if (init) {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.fileCacheStrategy = fileCacheStrategy;
     }
 
     /**
-     * Determines if a layered file system can be created for a given file.
+     * Sets the default provider. This is the provider that will handle URI 
with unknown schemes. The manager takes care
+     * of all lifecycle management.
      *
-     * @param file The file to check for.
-     * @return true if the FileSystem can be created.
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public boolean canCreateFileSystem(final FileObject file) throws 
FileSystemException {
-        return typeMap.getScheme(file) != null;
-    }
-
-    /**
-     * Creates a virtual file system.
-     *
-     * @param rootFile The FileObject to use.
-     * @return The FileObject in the VirtualFileSystem.
-     * @throws FileSystemException if an error occurs creating the file.
-     */
-    @Override
-    public FileObject createVirtualFileSystem(final FileObject rootFile) 
throws FileSystemException {
-        final FileObject fileObject = vfsProvider.createFileSystem(rootFile);
-        addVirtualFileSystemScheme(rootFile.getName().getScheme());
-        return fileObject;
-    }
-
-    /**
-     * Creates an empty virtual file system.
-     *
-     * @param rootUri The URI to use as the root of the FileSystem.
-     * @return A FileObject in the virtual FileSystem.
-     * @throws FileSystemException if an error occurs.
+     * @param provider The FileProvider.
+     * @throws FileSystemException if an error occurs setting the provider.
      */
-    @Override
-    public FileObject createVirtualFileSystem(final String rootUri) throws 
FileSystemException {
-        final FileObject fileObject = vfsProvider.createFileSystem(rootUri);
-        addVirtualFileSystemScheme(rootUri);
-        return fileObject;
-    }
-
-
-    protected void addVirtualFileSystemScheme(String rootUri) {
-        if (rootUri.indexOf(':') != -1) {
-            rootUri = rootUri.substring(0, rootUri.indexOf(':'));
-        }
-        virtualFileSystemSchemes.add(rootUri);
+    public void setDefaultProvider(final FileProvider provider) throws 
FileSystemException {
+        setupComponent(provider);
+        defaultProvider = provider;
     }
 
     /**
-     * Locates the local file provider.
+     * set the fileContentInfoFactory used to determine the infos of a file 
content.
      * <p>
-     * The local file provider is the first {@linkplain #addProvider(String[], 
FileProvider) provider added}
-     * implementing {@link LocalFileProvider}.
+     * Can only be set before the FileSystemManager is initialized.
      * </p>
      *
-     * @return The LocalFileProvider.
-     * @throws FileSystemException if no local file provider was set.
+     * @param fileContentInfoFactory The FileContentInfoFactory.
+     * @throws FileSystemException if an error occurs setting the 
FileContentInfoFactory.
      */
-    private LocalFileProvider getLocalFileProvider() throws 
FileSystemException {
-        return FileSystemException.requireNonNull(localFileProvider, 
"vfs.impl/no-local-file-provider.error");
-    }
+    public void setFileContentInfoFactory(final FileContentInfoFactory 
fileContentInfoFactory)
+            throws FileSystemException {
+        if (init) {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
 
-    /**
-     * Get the URLStreamHandlerFactory.
-     *
-     * @return The URLStreamHandlerFactory.
-     */
-    @Override
-    public URLStreamHandlerFactory getURLStreamHandlerFactory() {
-        return new VfsStreamHandlerFactory();
+        this.fileContentInfoFactory = fileContentInfoFactory;
     }
 
     /**
-     * Closes the given file system.
+     * Set a fileObject decorator to be used for ALL returned file objects.
      * <p>
-     * If you use VFS as singleton it is VERY dangerous to call this method.
+     * Can only be set before the FileSystemManager is initialized.
      * </p>
      *
-     * @param fileSystem The FileSystem to close.
+     * @param fileObjectDecorator must be inherted from {@link 
DecoratedFileObject} a has to provide a constructor with
+     *            a single {@link FileObject} as argument
+     * @throws FileSystemException if an error occurs setting the decorator.
      */
-    @Override
-    public void closeFileSystem(final FileSystem fileSystem) {
-        // inform the cache ...
-        getFilesCache().clear(fileSystem);
+    public void setFileObjectDecorator(final Class<?> fileObjectDecorator) 
throws FileSystemException {
+        if (init) {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+        if (!DecoratedFileObject.class.isAssignableFrom(fileObjectDecorator)) {
+            throw new FileSystemException("vfs.impl/invalid-decorator.error", 
fileObjectDecorator.getName());
+        }
 
-        // just in case the cache didnt call _closeFileSystem
-        _closeFileSystem(fileSystem);
+        try {
+            fileObjectDecoratorConst = 
fileObjectDecorator.getConstructor(FileObject.class);
+        } catch (final NoSuchMethodException e) {
+            throw new FileSystemException("vfs.impl/invalid-decorator.error", 
fileObjectDecorator.getName(), e);
+        }
+
+        this.fileObjectDecorator = fileObjectDecorator;
     }
 
     /**
-     * Closes the given file system.
+     * Sets the filesCache implementation used to cache files.
      * <p>
-     * If you use VFS as singleton it is VERY dangerous to call this method
+     * Can only be set before the FileSystemManager is initialized.
+     * </p>
+     * <p>
+     * The manager takes care of the lifecycle. If none is set, a default is 
picked in {@link #init()}.
      * </p>
      *
-     * @param fileSystem The FileSystem to close.
-     */
-    public void _closeFileSystem(final FileSystem fileSystem) {
-        final FileProvider provider = 
providers.get(fileSystem.getRootName().getScheme());
-        if (provider != null) {
-            ((AbstractFileProvider) provider).closeFileSystem(fileSystem);
-        } else if (fileSystem instanceof VirtualFileSystem) {
-            // vfsProvider does not implement AbstractFileProvider
-            vfsProvider.closeFileSystem(fileSystem);
-        }
-    }
-
-    /**
-     * This is an internal class because it needs access to the private member 
providers.
+     * @param filesCache The FilesCache.
+     * @throws FileSystemException if an error occurs setting the cache..
      */
-    final class VfsStreamHandlerFactory implements URLStreamHandlerFactory {
-        @Override
-        public URLStreamHandler createURLStreamHandler(final String protocol) {
-            final FileProvider provider = providers.get(protocol);
-            if (provider != null) {
-                return new DefaultURLStreamHandler(context);
-            }
-
-            // Route all other calls to the default URLStreamHandlerFactory
-            return new URLStreamHandlerProxy();
+    public void setFilesCache(final FilesCache filesCache) throws 
FileSystemException {
+        if (init) {
+            throw new FileSystemException("vfs.impl/already-inited.error");
         }
+        this.filesCache = filesCache;
     }
 
-    /**
-     * Get the schemes currently available.
-     *
-     * @return The array of scheme names.
-     */
-    @Override
-    public String[] getSchemes() {
-        final List<String> schemes = new ArrayList<>(providers.size() + 
virtualFileSystemSchemes.size());
-        schemes.addAll(providers.keySet());
-        schemes.addAll(virtualFileSystemSchemes);
-        return schemes.toArray(new String[]{});
-    }
+    // -- OPERATIONS --
 
     /**
-     * Get the capabilities for a given scheme.
+     * Sets the logger to use.
+     * <p>
+     * This overwrites the default logger for this manager and is not reset in 
{@link #close()}.
+     * </p>
      *
-     * @param scheme The scheme to located.
-     * @return A Collection of capabilities.
-     * @throws FileSystemException if the given scheme is not konwn
+     * @param log The Logger to use.
      */
     @Override
-    public Collection<Capability> getProviderCapabilities(final String scheme) 
throws FileSystemException {
-        final FileProvider provider = providers.get(scheme);
-        FileSystemException.requireNonNull(provider, 
"vfs.impl/unknown-scheme.error", scheme);
-        return provider.getCapabilities();
+    public void setLogger(final Log log) {
+        this.log = log;
     }
 
     /**
-     * Get the configuration builder for the given scheme.
+     * Sets the file replicator to use.
+     * <p>
+     * The manager takes care of all lifecycle management.
+     * </p>
      *
-     * @param scheme The scheme to locate.
-     * @return The FileSystemConfigBuilder for the scheme.
-     * @throws FileSystemException if the given scheme is not konwn
+     * @param replicator The FileReplicator.
+     * @throws FileSystemException if an error occurs setting the replicator.
      */
-    @Override
-    public FileSystemConfigBuilder getFileSystemConfigBuilder(final String 
scheme) throws FileSystemException {
-        final FileProvider provider = providers.get(scheme);
-        FileSystemException.requireNonNull(provider, 
"vfs.impl/unknown-scheme.error", scheme);
-        return provider.getConfigBuilder();
+    public void setReplicator(final FileReplicator replicator) throws 
FileSystemException {
+        setupComponent(replicator);
+        fileReplicator = replicator;
     }
 
-    // -- OPERATIONS --
-
     /**
-     * Adds the specified FileOperationProvider for the specified scheme. 
Several FileOperationProvider's might be
-     * registered for the same scheme. For example, for "file" scheme we can 
register SvnWsOperationProvider and
-     * CvsOperationProvider.
+     * Sets the temporary file store to use.
+     * <p>
+     * The manager takes care of all lifecycle management.
+     * </p>
      *
-     * @param scheme The scheme the provider should be registered for.
-     * @param operationProvider The FileOperationProvider.
-     * @throws FileSystemException if an error occurs adding the provider.
+     * @param tempFileStore The temporary FileStore.
+     * @throws FileSystemException if an error occurs adding the file store.
      */
-    @Override
-    public void addOperationProvider(final String scheme, final 
FileOperationProvider operationProvider)
-            throws FileSystemException {
-        addOperationProvider(new String[] { scheme }, operationProvider);
+    public void setTemporaryFileStore(final TemporaryFileStore tempFileStore) 
throws FileSystemException {
+        setupComponent(tempFileStore);
+        this.tempFileStore = tempFileStore;
     }
 
     /**
-     * @see FileSystemManager#addOperationProvider(String, 
org.apache.commons.vfs2.operations.FileOperationProvider)
+     * Initializes a component, if it has not already been initialized.
      *
-     * @param schemes The array of schemes the provider should apply to.
-     * @param operationProvider The FileOperationProvider.
+     * @param component The component to setup.
      * @throws FileSystemException if an error occurs.
      */
-    @Override
-    public void addOperationProvider(final String[] schemes, final 
FileOperationProvider operationProvider)
-            throws FileSystemException {
-        for (final String scheme : schemes) {
-            if (!operationProviders.containsKey(scheme)) {
-                final List<FileOperationProvider> providers = new 
ArrayList<>();
-                operationProviders.put(scheme, providers);
-            }
-
-            final List<FileOperationProvider> providers = 
operationProviders.get(scheme);
-
-            if (providers.contains(operationProvider)) {
-                throw new 
FileSystemException("vfs.operation/operation-provider-already-added.error", 
scheme);
+    private void setupComponent(final Object component) throws 
FileSystemException {
+        if (!components.contains(component)) {
+            if (component instanceof VfsComponent) {
+                final VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.setLogger(getLogger());
+                vfsComponent.setContext(context);
+                vfsComponent.init();
             }
-
-            setupComponent(operationProvider);
-
-            providers.add(operationProvider);
-        }
-    }
-
-    /**
-     * @param scheme the scheme for wich we want to get the list af registered 
providers.
-     *
-     * @return the registered FileOperationProviders for the specified scheme. 
If there were no providers registered for
-     *         the scheme, it returns null.
-     *
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public FileOperationProvider[] getOperationProviders(final String scheme) 
throws FileSystemException {
-
-        final List<?> providers = operationProviders.get(scheme);
-        if (providers == null || providers.isEmpty()) {
-            return null;
+            components.add(component);
         }
-        return providers.toArray(new FileOperationProvider[] {});
-    }
-
-    /**
-     * Converts a URI into a {@link FileObject}.
-     *
-     * @param uri The URI to convert.
-     * @return The {@link FileObject} that represents the URI. Never returns 
null.
-     * @throws FileSystemException On error converting the URI.
-     * @since 2.1
-     */
-    @Override
-    public FileObject resolveFile(final URI uri) throws FileSystemException {
-        // TODO Push the URI deeper into VFS
-        return resolveFile(baseFile, uri.toString(), null);
     }
 
     /**
-     * Converts a URL into a {@link FileObject}.
+     * Converts a local file into a {@link FileObject}.
      *
-     * @param url The URL to convert.
-     * @return The {@link FileObject} that represents the URL. Never returns 
null.
-     * @throws FileSystemException On error converting the URL.
-     * @since 2.1
+     * @param file The input File.
+     * @return the create FileObject
+     * @throws FileSystemException if an error occurs creating the file.
      */
     @Override
-    public FileObject resolveFile(final URL url) throws FileSystemException {
-        try {
-            return this.resolveFile(url.toURI());
-        } catch (final URISyntaxException e) {
-            throw new FileSystemException(e);
-        }
+    public FileObject toFileObject(final File file) throws FileSystemException 
{
+        return getLocalFileProvider().findLocalFile(file);
     }
 
 }

Reply via email to