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); } }