0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.commons.vfs.impl;
0018:
0019: import org.apache.commons.logging.Log;
0020: import org.apache.commons.vfs.CacheStrategy;
0021: import org.apache.commons.vfs.FileContentInfoFactory;
0022: import org.apache.commons.vfs.FileName;
0023: import org.apache.commons.vfs.FileObject;
0024: import org.apache.commons.vfs.FileSystem;
0025: import org.apache.commons.vfs.FileSystemConfigBuilder;
0026: import org.apache.commons.vfs.FileSystemException;
0027: import org.apache.commons.vfs.FileSystemManager;
0028: import org.apache.commons.vfs.FileSystemOptions;
0029: import org.apache.commons.vfs.FileType;
0030: import org.apache.commons.vfs.FilesCache;
0031: import org.apache.commons.vfs.NameScope;
0032: import org.apache.commons.vfs.VFS;
0033: import org.apache.commons.vfs.cache.SoftRefFilesCache;
0034: import org.apache.commons.vfs.operations.FileOperationProvider;
0035: import org.apache.commons.vfs.provider.AbstractFileName;
0036: import org.apache.commons.vfs.provider.AbstractFileProvider;
0037: import org.apache.commons.vfs.provider.DefaultURLStreamHandler;
0038: import org.apache.commons.vfs.provider.FileProvider;
0039: import org.apache.commons.vfs.provider.FileReplicator;
0040: import org.apache.commons.vfs.provider.LocalFileProvider;
0041: import org.apache.commons.vfs.provider.TemporaryFileStore;
0042: import org.apache.commons.vfs.provider.UriParser;
0043: import org.apache.commons.vfs.provider.VfsComponent;
0044:
0045: import java.io.File;
0046: import java.lang.reflect.Constructor;
0047: import java.net.URLStreamHandler;
0048: import java.net.URLStreamHandlerFactory;
0049: import java.util.ArrayList;
0050: import java.util.Collection;
0051: import java.util.HashMap;
0052: import java.util.Iterator;
0053: import java.util.List;
0054: import java.util.Map;
0055:
0056: /**
0057: * A default file system manager implementation.
0058: *
0059: * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
0060: * @version $Revision: 537931 $ $Date: 2006-03-30 21:16:24 +0200 (Do, 30 Mrz
0061: * 2006) $
0062: */
0063: public class DefaultFileSystemManager implements FileSystemManager {
0064: /**
0065: * The provider for local files.
0066: */
0067: private LocalFileProvider localFileProvider;
0068:
0069: /**
0070: * The default provider.
0071: */
0072: private FileProvider defaultProvider;
0073:
0074: /**
0075: * The file replicator to use.
0076: */
0077: private FileReplicator fileReplicator;
0078:
0079: /**
0080: * Mapping from URI scheme to FileProvider.
0081: */
0082: private final Map providers = new HashMap();
0083:
0084: /**
0085: * All components used by this manager.
0086: */
0087: private final ArrayList components = new ArrayList();
0088:
0089: /**
0090: * The base file to use for relative URI.
0091: */
0092: private FileObject baseFile;
0093:
0094: /**
0095: * The files cache
0096: */
0097: private FilesCache filesCache;
0098:
0099: /**
0100: * The cache strategy
0101: */
0102: private CacheStrategy fileCacheStrategy;
0103:
0104: /**
0105: * Class which decorates all returned fileObjects
0106: */
0107: private Class fileObjectDecorator;
0108: private Constructor fileObjectDecoratorConst;
0109:
0110: /**
0111: * The class to use to determine the content-type (mime-type)
0112: */
0113: private FileContentInfoFactory fileContentInfoFactory;
0114:
0115: /**
0116: * The logger to use.
0117: */
0118: private Log log;
0119:
0120: /**
0121: * The context to pass to providers.
0122: */
0123: private final DefaultVfsComponentContext context = new DefaultVfsComponentContext(
0124: this );
0125:
0126: private TemporaryFileStore tempFileStore;
0127: private final FileTypeMap map = new FileTypeMap();
0128: private final VirtualFileProvider vfsProvider = new VirtualFileProvider();
0129: private boolean init;
0130:
0131: /**
0132: * Returns the logger used by this manager.
0133: */
0134: protected Log getLogger() {
0135: return log;
0136: }
0137:
0138: /**
0139: * Registers a file system provider. The manager takes care of all lifecycle
0140: * management. A provider may be registered multiple times.
0141: *
0142: * @param urlScheme
0143: * The scheme the provider will handle.
0144: * @param provider
0145: * The provider.
0146: */
0147: public void addProvider(final String urlScheme,
0148: final FileProvider provider) throws FileSystemException {
0149: addProvider(new String[] { urlScheme }, provider);
0150: }
0151:
0152: /**
0153: * Registers a file system provider. The manager takes care of all lifecycle
0154: * management. A provider may be registered multiple times.
0155: *
0156: * @param urlSchemes
0157: * The schemes the provider will handle.
0158: * @param provider
0159: * The provider.
0160: */
0161: public void addProvider(final String[] urlSchemes,
0162: final FileProvider provider) throws FileSystemException {
0163: // Warn about duplicate providers
0164: for (int i = 0; i < urlSchemes.length; i++) {
0165: final String scheme = urlSchemes[i];
0166: if (providers.containsKey(scheme)) {
0167: throw new FileSystemException(
0168: "vfs.impl/multiple-providers-for-scheme.error",
0169: scheme);
0170: }
0171: }
0172:
0173: // Contextualise the component (if not already)
0174: setupComponent(provider);
0175:
0176: // Add to map
0177: for (int i = 0; i < urlSchemes.length; i++) {
0178: final String scheme = urlSchemes[i];
0179: providers.put(scheme, provider);
0180: }
0181:
0182: if (provider instanceof LocalFileProvider
0183: && localFileProvider == null) {
0184: localFileProvider = (LocalFileProvider) provider;
0185: }
0186: }
0187:
0188: /**
0189: * Returns true if this manager has a provider for a particular scheme.
0190: */
0191: public boolean hasProvider(final String scheme) {
0192: return providers.containsKey(scheme);
0193: }
0194:
0195: /**
0196: * Adds an filename extension mapping.
0197: *
0198: * @param extension
0199: * The file name extension.
0200: * @param scheme
0201: * The scheme to use for files with this extension.
0202: */
0203: public void addExtensionMap(final String extension,
0204: final String scheme) {
0205: map.addExtension(extension, scheme);
0206: }
0207:
0208: /**
0209: * Adds a mime type mapping.
0210: *
0211: * @param mimeType
0212: * The mime type.
0213: * @param scheme
0214: * The scheme to use for files with this mime type.
0215: */
0216: public void addMimeTypeMap(final String mimeType,
0217: final String scheme) {
0218: map.addMimeType(mimeType, scheme);
0219: }
0220:
0221: /**
0222: * Sets the default provider. This is the provider that will handle URI with
0223: * unknown schemes. The manager takes care of all lifecycle management.
0224: */
0225: public void setDefaultProvider(final FileProvider provider)
0226: throws FileSystemException {
0227: setupComponent(provider);
0228: defaultProvider = provider;
0229: }
0230:
0231: /**
0232: * Returns the filesCache implementation used to cache files
0233: */
0234: public FilesCache getFilesCache() {
0235: return filesCache;
0236: }
0237:
0238: /**
0239: * Sets the filesCache implementation used to cache files
0240: */
0241: public void setFilesCache(final FilesCache filesCache)
0242: throws FileSystemException {
0243: if (init) {
0244: throw new FileSystemException(
0245: "vfs.impl/already-inited.error");
0246: }
0247:
0248: this .filesCache = filesCache;
0249: }
0250:
0251: /**
0252: * <p>
0253: * Set the cache strategy to use when dealing with file object data. You can
0254: * set it only once before the FileSystemManager is initialized.
0255: * <p />
0256: * <p>
0257: * The default is {@link CacheStrategy#ON_RESOLVE}
0258: * </p>
0259: *
0260: * @throws FileSystemException
0261: * if this is not possible. e.g. it is already set.
0262: */
0263: public void setCacheStrategy(final CacheStrategy fileCacheStrategy)
0264: throws FileSystemException {
0265: if (init) {
0266: throw new FileSystemException(
0267: "vfs.impl/already-inited.error");
0268: }
0269:
0270: this .fileCacheStrategy = fileCacheStrategy;
0271: }
0272:
0273: /**
0274: * Get the cache strategy used
0275: */
0276: public CacheStrategy getCacheStrategy() {
0277: return fileCacheStrategy;
0278: }
0279:
0280: /**
0281: * Get the file object decorator used
0282: */
0283: public Class getFileObjectDecorator() {
0284: return fileObjectDecorator;
0285: }
0286:
0287: /**
0288: * The constructor associated to the fileObjectDecorator.
0289: * We cache it here for performance reasons.
0290: */
0291: public Constructor getFileObjectDecoratorConst() {
0292: return fileObjectDecoratorConst;
0293: }
0294:
0295: /**
0296: * set a fileObject decorator to be used for ALL returned file objects
0297: *
0298: * @param fileObjectDecorator must be inherted from {@link DecoratedFileObject} a has to provide a
0299: * constructor with a single {@link FileObject} as argument
0300: */
0301: public void setFileObjectDecorator(Class fileObjectDecorator)
0302: throws FileSystemException {
0303: if (init) {
0304: throw new FileSystemException(
0305: "vfs.impl/already-inited.error");
0306: }
0307: if (!DecoratedFileObject.class
0308: .isAssignableFrom(fileObjectDecorator)) {
0309: throw new FileSystemException(
0310: "vfs.impl/invalid-decorator.error",
0311: fileObjectDecorator.getName());
0312: }
0313:
0314: try {
0315: fileObjectDecoratorConst = fileObjectDecorator
0316: .getConstructor(new Class[] { FileObject.class });
0317: } catch (NoSuchMethodException e) {
0318: throw new FileSystemException(
0319: "vfs.impl/invalid-decorator.error",
0320: fileObjectDecorator.getName(), e);
0321: }
0322:
0323: this .fileObjectDecorator = fileObjectDecorator;
0324: }
0325:
0326: /**
0327: * get the fileContentInfoFactory used to determine the infos of a file
0328: * content.
0329: */
0330: public FileContentInfoFactory getFileContentInfoFactory() {
0331: return fileContentInfoFactory;
0332: }
0333:
0334: /**
0335: * set the fileContentInfoFactory used to determine the infos of a file
0336: * content.
0337: */
0338: public void setFileContentInfoFactory(
0339: FileContentInfoFactory fileContentInfoFactory)
0340: throws FileSystemException {
0341: if (init) {
0342: throw new FileSystemException(
0343: "vfs.impl/already-inited.error");
0344: }
0345:
0346: this .fileContentInfoFactory = fileContentInfoFactory;
0347: }
0348:
0349: /**
0350: * Sets the file replicator to use. The manager takes care of all lifecycle
0351: * management.
0352: */
0353: public void setReplicator(final FileReplicator replicator)
0354: throws FileSystemException {
0355: setupComponent(replicator);
0356: fileReplicator = replicator;
0357: }
0358:
0359: /**
0360: * Sets the temporary file store to use. The manager takes care of all
0361: * lifecycle management.
0362: */
0363: public void setTemporaryFileStore(
0364: final TemporaryFileStore tempFileStore)
0365: throws FileSystemException {
0366: setupComponent(tempFileStore);
0367: this .tempFileStore = tempFileStore;
0368: }
0369:
0370: /**
0371: * Sets the logger to use.
0372: */
0373: public void setLogger(final Log log) {
0374: this .log = log;
0375: }
0376:
0377: /**
0378: * Initialises a component, if it has not already been initialised.
0379: */
0380: private void setupComponent(final Object component)
0381: throws FileSystemException {
0382: if (!components.contains(component)) {
0383: if (component instanceof VfsComponent) {
0384: final VfsComponent vfsComponent = (VfsComponent) component;
0385: vfsComponent.setLogger(getLogger());
0386: vfsComponent.setContext(context);
0387: vfsComponent.init();
0388: }
0389: components.add(component);
0390: }
0391: }
0392:
0393: /**
0394: * Closes a component, if it has not already been closed.
0395: */
0396: private void closeComponent(final Object component) {
0397: if (component != null && components.contains(component)) {
0398: if (component instanceof VfsComponent) {
0399: final VfsComponent vfsComponent = (VfsComponent) component;
0400: vfsComponent.close();
0401: }
0402: components.remove(component);
0403: }
0404: }
0405:
0406: /**
0407: * Returns the file replicator.
0408: *
0409: * @return The file replicator. Never returns null.
0410: */
0411: public FileReplicator getReplicator() throws FileSystemException {
0412: if (fileReplicator == null) {
0413: throw new FileSystemException(
0414: "vfs.impl/no-replicator.error");
0415: }
0416: return fileReplicator;
0417: }
0418:
0419: /**
0420: * Returns the temporary file store.
0421: *
0422: * @return The file store. Never returns null.
0423: */
0424: public TemporaryFileStore getTemporaryFileStore()
0425: throws FileSystemException {
0426: if (tempFileStore == null) {
0427: throw new FileSystemException(
0428: "vfs.impl/no-temp-file-store.error");
0429: }
0430: return tempFileStore;
0431: }
0432:
0433: /**
0434: * Initialises this manager.
0435: */
0436: public void init() throws FileSystemException {
0437: if (filesCache == null) {
0438: // filesCache = new DefaultFilesCache();
0439: filesCache = new SoftRefFilesCache();
0440: }
0441: if (fileContentInfoFactory == null) {
0442: fileContentInfoFactory = new FileContentInfoFilenameFactory();
0443: }
0444:
0445: if (fileCacheStrategy == null) {
0446: fileCacheStrategy = CacheStrategy.ON_RESOLVE;
0447: }
0448:
0449: setupComponent(filesCache);
0450: setupComponent(vfsProvider);
0451:
0452: init = true;
0453: }
0454:
0455: /**
0456: * Closes all files created by this manager, and cleans up any temporary
0457: * files. Also closes all providers and the replicator.
0458: */
0459: public void close() {
0460: if (!init) {
0461: return;
0462: }
0463:
0464: // Close the providers.
0465: for (Iterator iterator = providers.values().iterator(); iterator
0466: .hasNext();) {
0467: final Object provider = iterator.next();
0468: closeComponent(provider);
0469: }
0470:
0471: // Close the other components
0472: closeComponent(defaultProvider);
0473: closeComponent(fileReplicator);
0474: closeComponent(tempFileStore);
0475:
0476: components.clear();
0477: providers.clear();
0478: filesCache.close();
0479: localFileProvider = null;
0480: defaultProvider = null;
0481: fileReplicator = null;
0482: tempFileStore = null;
0483: init = false;
0484: }
0485:
0486: /**
0487: * Free all resources used by unused filesystems created by this manager.
0488: */
0489: public void freeUnusedResources() {
0490: if (!init) {
0491: return;
0492: }
0493:
0494: // Close the providers.
0495: for (Iterator iterator = providers.values().iterator(); iterator
0496: .hasNext();) {
0497: final AbstractFileProvider provider = (AbstractFileProvider) iterator
0498: .next();
0499: provider.freeUnusedResources();
0500: }
0501: }
0502:
0503: /**
0504: * Sets the base file to use when resolving relative URI.
0505: */
0506: // public void setBaseFile(final FileObject baseFile)
0507: public void setBaseFile(final FileObject baseFile)
0508: throws FileSystemException {
0509: this .baseFile = baseFile;
0510: }
0511:
0512: /**
0513: * Sets the base file to use when resolving relative URI.
0514: */
0515: public void setBaseFile(final File baseFile)
0516: throws FileSystemException {
0517: this .baseFile = getLocalFileProvider().findLocalFile(baseFile);
0518: }
0519:
0520: /**
0521: * Returns the base file used to resolve relative URI.
0522: */
0523: public FileObject getBaseFile() throws FileSystemException {
0524: return baseFile;
0525: }
0526:
0527: /**
0528: * Locates a file by URI.
0529: */
0530: public FileObject resolveFile(final String uri)
0531: throws FileSystemException {
0532: // return resolveFile(baseFile, uri);
0533: return resolveFile(getBaseFile(), uri);
0534: }
0535:
0536: /**
0537: * Locate a file by URI, use the FileSystemOptions for file-system creation
0538: */
0539:
0540: public FileObject resolveFile(final String uri,
0541: final FileSystemOptions fileSystemOptions)
0542: throws FileSystemException {
0543: // return resolveFile(baseFile, uri, fileSystemOptions);
0544: return resolveFile(getBaseFile(), uri, fileSystemOptions);
0545: }
0546:
0547: /**
0548: * Locates a file by URI.
0549: */
0550: public FileObject resolveFile(final File baseFile, final String uri)
0551: throws FileSystemException {
0552: final FileObject baseFileObj = getLocalFileProvider()
0553: .findLocalFile(baseFile);
0554: return resolveFile(baseFileObj, uri);
0555: }
0556:
0557: /**
0558: * Resolves a URI, relative to a base file.
0559: */
0560: public FileObject resolveFile(final FileObject baseFile,
0561: final String uri) throws FileSystemException {
0562: return resolveFile(baseFile, uri, baseFile == null ? null
0563: : baseFile.getFileSystem().getFileSystemOptions());
0564: }
0565:
0566: /**
0567: * Resolves a URI, realtive to a base file with specified FileSystem
0568: * configuration
0569: */
0570: public FileObject resolveFile(final FileObject baseFile,
0571: final String uri, final FileSystemOptions fileSystemOptions)
0572: throws FileSystemException {
0573: final FileObject realBaseFile;
0574: if (baseFile != null && VFS.isUriStyle()
0575: && baseFile.getName().getType() == FileType.FILE) {
0576: realBaseFile = baseFile.getParent();
0577: } else {
0578: realBaseFile = baseFile;
0579: }
0580: // TODO: use resolveName and use this name to resolve the fileObject
0581:
0582: UriParser.checkUriEncoding(uri);
0583:
0584: if (uri == null) {
0585: throw new IllegalArgumentException();
0586: }
0587:
0588: // Extract the scheme
0589: final String scheme = UriParser.extractScheme(uri);
0590: if (scheme != null) {
0591: // An absolute URI - locate the provider
0592: final FileProvider provider = (FileProvider) providers
0593: .get(scheme);
0594: if (provider != null) {
0595: return provider.findFile(realBaseFile, uri,
0596: fileSystemOptions);
0597: }
0598: // Otherwise, assume a local file
0599: }
0600:
0601: // Handle absolute file names
0602: if (localFileProvider != null
0603: && localFileProvider.isAbsoluteLocalName(uri)) {
0604: return localFileProvider.findLocalFile(uri);
0605: }
0606:
0607: if (scheme != null) {
0608: // An unknown scheme - hand it to the default provider
0609: if (defaultProvider == null) {
0610: throw new FileSystemException(
0611: "vfs.impl/unknown-scheme.error", new Object[] {
0612: scheme, uri });
0613: }
0614: return defaultProvider.findFile(realBaseFile, uri,
0615: fileSystemOptions);
0616: }
0617:
0618: // Assume a relative name - use the supplied base file
0619: if (realBaseFile == null) {
0620: throw new FileSystemException(
0621: "vfs.impl/find-rel-file.error", uri);
0622: }
0623:
0624: return realBaseFile.resolveFile(uri);
0625: }
0626:
0627: /**
0628: * Resolves a name, relative to the file. If the supplied name is an
0629: * absolute path, then it is resolved relative to the root of the file
0630: * system that the file belongs to. If a relative name is supplied, then it
0631: * is resolved relative to this file name.
0632: */
0633: public FileName resolveName(final FileName root, final String path)
0634: throws FileSystemException {
0635: return resolveName(root, path, NameScope.FILE_SYSTEM);
0636: }
0637:
0638: /**
0639: * Resolves a name, relative to the root.
0640: *
0641: * @param base
0642: * the base filename
0643: * @param name
0644: * the name
0645: * @param scope
0646: * the {@link NameScope}
0647: * @throws FileSystemException
0648: */
0649: public FileName resolveName(final FileName base, final String name,
0650: final NameScope scope) throws FileSystemException {
0651: final FileName realBase;
0652: if (base != null && VFS.isUriStyle()
0653: && base.getType() == FileType.FILE) {
0654: realBase = base.getParent();
0655: } else {
0656: realBase = base;
0657: }
0658:
0659: final StringBuffer buffer = new StringBuffer(name);
0660:
0661: // Adjust separators
0662: UriParser.fixSeparators(buffer);
0663:
0664: // Determine whether to prepend the base path
0665: if (name.length() == 0
0666: || name.charAt(0) != FileName.SEPARATOR_CHAR) {
0667: // Supplied path is not absolute
0668: if (!VFS.isUriStyle()) {
0669: // when using uris the parent already do have the trailing "/"
0670: buffer.insert(0, FileName.SEPARATOR_CHAR);
0671: }
0672: buffer.insert(0, realBase.getPath());
0673: }
0674:
0675: // // UriParser.canonicalizePath(buffer, 0, name.length());
0676:
0677: // Normalise the path
0678: FileType fileType = UriParser.normalisePath(buffer);
0679:
0680: // Check the name is ok
0681: final String resolvedPath = buffer.toString();
0682: if (!AbstractFileName.checkName(realBase.getPath(),
0683: resolvedPath, scope)) {
0684: throw new FileSystemException(
0685: "vfs.provider/invalid-descendent-name.error", name);
0686: }
0687:
0688: String scheme = realBase.getScheme();
0689: String fullPath = realBase.getRootURI() + resolvedPath;
0690: final FileProvider provider = (FileProvider) providers
0691: .get(scheme);
0692: if (provider != null) {
0693: // todo: extend the filename parser to be able to parse
0694: // only a pathname and take the missing informations from
0695: // the base. Then we can get rid of the string operation.
0696: // // String fullPath = base.getRootURI() +
0697: // resolvedPath.substring(1);
0698:
0699: return provider.parseUri(realBase, fullPath);
0700: }
0701:
0702: if (scheme != null) {
0703: // An unknown scheme - hand it to the default provider - if possible
0704: if (defaultProvider != null) {
0705: return defaultProvider.parseUri(realBase, fullPath);
0706: }
0707: }
0708:
0709: // todo: avoid fallback to this point
0710: // this happens if we have a virtual filesystem (no provider for scheme)
0711: return ((AbstractFileName) realBase).createName(resolvedPath,
0712: fileType);
0713: }
0714:
0715: /**
0716: * resolve the uri to a filename
0717: *
0718: * @throws FileSystemException
0719: */
0720: public FileName resolveURI(String uri) throws FileSystemException {
0721: UriParser.checkUriEncoding(uri);
0722:
0723: if (uri == null) {
0724: throw new IllegalArgumentException();
0725: }
0726:
0727: // Extract the scheme
0728: final String scheme = UriParser.extractScheme(uri);
0729: if (scheme != null) {
0730: // An absolute URI - locate the provider
0731: final FileProvider provider = (FileProvider) providers
0732: .get(scheme);
0733: if (provider != null) {
0734: return provider.parseUri(null, uri);
0735: }
0736:
0737: // Otherwise, assume a local file
0738: }
0739:
0740: // Handle absolute file names
0741: if (localFileProvider != null
0742: && localFileProvider.isAbsoluteLocalName(uri)) {
0743: return localFileProvider.parseUri(null, uri);
0744: }
0745:
0746: if (scheme != null) {
0747: // An unknown scheme - hand it to the default provider
0748: if (defaultProvider == null) {
0749: throw new FileSystemException(
0750: "vfs.impl/unknown-scheme.error", new Object[] {
0751: scheme, uri });
0752: }
0753: return defaultProvider.parseUri(null, uri);
0754: }
0755:
0756: // Assume a relative name - use the supplied base file
0757: if (baseFile == null) {
0758: throw new FileSystemException(
0759: "vfs.impl/find-rel-file.error", uri);
0760: }
0761:
0762: return resolveName(baseFile.getName(), uri,
0763: NameScope.FILE_SYSTEM);
0764: }
0765:
0766: /**
0767: * Converts a local file into a {@link FileObject}.
0768: */
0769: public FileObject toFileObject(final File file)
0770: throws FileSystemException {
0771: return getLocalFileProvider().findLocalFile(file);
0772: }
0773:
0774: /**
0775: * Creates a layered file system.
0776: */
0777: public FileObject createFileSystem(final String scheme,
0778: final FileObject file) throws FileSystemException {
0779: final FileProvider provider = (FileProvider) providers
0780: .get(scheme);
0781: if (provider == null) {
0782: throw new FileSystemException(
0783: "vfs.impl/unknown-provider.error", new Object[] {
0784: scheme, file });
0785: }
0786: return provider.createFileSystem(scheme, file, file
0787: .getFileSystem().getFileSystemOptions());
0788: }
0789:
0790: /**
0791: * Creates a layered file system.
0792: */
0793: public FileObject createFileSystem(final FileObject file)
0794: throws FileSystemException {
0795: final String scheme = map.getScheme(file);
0796: if (scheme == null) {
0797: throw new FileSystemException(
0798: "vfs.impl/no-provider-for-file.error", file);
0799: }
0800:
0801: return createFileSystem(scheme, file);
0802: }
0803:
0804: /**
0805: * Determines if a layered file system can be created for a given file.
0806: *
0807: * @param file
0808: * The file to check for.
0809: */
0810: public boolean canCreateFileSystem(final FileObject file)
0811: throws FileSystemException {
0812: return (map.getScheme(file) != null);
0813: }
0814:
0815: /**
0816: * Creates a virtual file system.
0817: */
0818: public FileObject createVirtualFileSystem(final FileObject rootFile)
0819: throws FileSystemException {
0820: return vfsProvider.createFileSystem(rootFile);
0821: }
0822:
0823: /**
0824: * Creates an empty virtual file system.
0825: */
0826: public FileObject createVirtualFileSystem(final String rootUri)
0827: throws FileSystemException {
0828: return vfsProvider.createFileSystem(rootUri);
0829: }
0830:
0831: /**
0832: * Locates the local file provider.
0833: */
0834: private LocalFileProvider getLocalFileProvider()
0835: throws FileSystemException {
0836: if (localFileProvider == null) {
0837: throw new FileSystemException(
0838: "vfs.impl/no-local-file-provider.error");
0839: }
0840: return localFileProvider;
0841: }
0842:
0843: /**
0844: * Get the URLStreamHandlerFactory.
0845: */
0846: public URLStreamHandlerFactory getURLStreamHandlerFactory() {
0847: return new VfsStreamHandlerFactory();
0848: }
0849:
0850: /**
0851: * Closes the given filesystem.<br />
0852: * If you use VFS as singleton it is VERY dangerous to call this method
0853: */
0854: public void closeFileSystem(FileSystem filesystem) {
0855: // inform the cache ...
0856: getFilesCache().clear(filesystem);
0857:
0858: // just in case the cache didnt call _closeFileSystem
0859: _closeFileSystem(filesystem);
0860: }
0861:
0862: /**
0863: * Closes the given filesystem.<br />
0864: * If you use VFS as singleton it is VERY dangerous to call this method
0865: */
0866: public void _closeFileSystem(FileSystem filesystem) {
0867: FileProvider provider = (FileProvider) providers.get(filesystem
0868: .getRootName().getScheme());
0869: if (provider != null) {
0870: ((AbstractFileProvider) provider)
0871: .closeFileSystem(filesystem);
0872: }
0873: }
0874:
0875: /**
0876: * This is an internal class because it needs access to the private member
0877: * providers.
0878: */
0879: final class VfsStreamHandlerFactory implements
0880: URLStreamHandlerFactory {
0881: public URLStreamHandler createURLStreamHandler(
0882: final String protocol) {
0883: FileProvider provider = (FileProvider) providers
0884: .get(protocol);
0885: if (provider != null) {
0886: return new DefaultURLStreamHandler(context);
0887: }
0888:
0889: // Route all other calls to the default URLStreamHandlerFactory
0890: return new URLStreamHandlerProxy();
0891: }
0892: }
0893:
0894: /**
0895: * Get the schemes currently available.
0896: */
0897: public String[] getSchemes() {
0898: String[] schemes = new String[providers.size()];
0899: providers.keySet().toArray(schemes);
0900: return schemes;
0901: }
0902:
0903: /**
0904: * Get the capabilities for a given scheme.
0905: *
0906: * @throws FileSystemException
0907: * if the given scheme is not konwn
0908: */
0909: public Collection getProviderCapabilities(final String scheme)
0910: throws FileSystemException {
0911: FileProvider provider = (FileProvider) providers.get(scheme);
0912: if (provider == null) {
0913: throw new FileSystemException(
0914: "vfs.impl/unknown-scheme.error",
0915: new Object[] { scheme });
0916: }
0917:
0918: return provider.getCapabilities();
0919: }
0920:
0921: /**
0922: * Get the configuration builder for the given scheme
0923: *
0924: * @throws FileSystemException
0925: * if the given scheme is not konwn
0926: */
0927: public FileSystemConfigBuilder getFileSystemConfigBuilder(
0928: final String scheme) throws FileSystemException {
0929: FileProvider provider = (FileProvider) providers.get(scheme);
0930: if (provider == null) {
0931: throw new FileSystemException(
0932: "vfs.impl/unknown-scheme.error",
0933: new Object[] { scheme });
0934: }
0935:
0936: return provider.getConfigBuilder();
0937: }
0938:
0939: // -- OPERATIONS --
0940:
0941: private final Map operationProviders = new HashMap();
0942:
0943: /**
0944: * Adds the specified FileOperationProvider for the specified scheme.
0945: * Several FileOperationProvider's might be registered for the same scheme.
0946: * For example, for "file" scheme we can register SvnWsOperationProvider and
0947: * CvsOperationProvider.
0948: *
0949: * @param scheme
0950: * @param operationProvider
0951: * @throws FileSystemException
0952: */
0953: public void addOperationProvider(final String scheme,
0954: final FileOperationProvider operationProvider)
0955: throws FileSystemException {
0956: addOperationProvider(new String[] { scheme }, operationProvider);
0957: }
0958:
0959: /**
0960: * @see FileSystemManager#addOperationProvider(String,
0961: * org.apache.commons.vfs.operations.FileOperationProvider)
0962: *
0963: * @param schemes
0964: * @param operationProvider
0965: * @throws FileSystemException
0966: */
0967: public void addOperationProvider(final String[] schemes,
0968: final FileOperationProvider operationProvider)
0969: throws FileSystemException {
0970: for (int i = 0; i < schemes.length; i++) {
0971: final String scheme = schemes[i];
0972:
0973: if (!operationProviders.containsKey(scheme)) {
0974: final List providers = new ArrayList();
0975: operationProviders.put(scheme, providers);
0976: }
0977:
0978: final List providers = (List) operationProviders
0979: .get(scheme);
0980:
0981: if (providers.contains(operationProvider)) {
0982: throw new FileSystemException(
0983: "vfs.operation/operation-provider-already-added.error",
0984: scheme);
0985: }
0986:
0987: setupComponent(operationProvider);
0988:
0989: providers.add(operationProvider);
0990: }
0991: }
0992:
0993: /**
0994: * @param scheme
0995: * the scheme for wich we want to get the list af registered
0996: * providers.
0997: *
0998: * @return the registered FileOperationProviders for the specified scheme.
0999: * If there were no providers registered for the scheme, it returns
1000: * null.
1001: *
1002: * @throws FileSystemException
1003: */
1004: public FileOperationProvider[] getOperationProviders(
1005: final String scheme) throws FileSystemException {
1006:
1007: List providers = (List) operationProviders.get(scheme);
1008: if (providers == null || providers.size() == 0) {
1009: return null;
1010: }
1011: return (FileOperationProvider[]) providers
1012: .toArray(new FileOperationProvider[] {});
1013: }
1014: }
|