1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.impl;
18
19 import java.io.File;
20 import java.net.URLStreamHandler;
21 import java.net.URLStreamHandlerFactory;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.lang.reflect.Constructor;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.vfs.CacheStrategy;
32 import org.apache.commons.vfs.FileContentInfoFactory;
33 import org.apache.commons.vfs.FileName;
34 import org.apache.commons.vfs.FileObject;
35 import org.apache.commons.vfs.FileSystem;
36 import org.apache.commons.vfs.FileSystemConfigBuilder;
37 import org.apache.commons.vfs.FileSystemException;
38 import org.apache.commons.vfs.FileSystemManager;
39 import org.apache.commons.vfs.FileSystemOptions;
40 import org.apache.commons.vfs.FileType;
41 import org.apache.commons.vfs.FilesCache;
42 import org.apache.commons.vfs.NameScope;
43 import org.apache.commons.vfs.VFS;
44 import org.apache.commons.vfs.cache.SoftRefFilesCache;
45 import org.apache.commons.vfs.operations.FileOperationProvider;
46 import org.apache.commons.vfs.provider.AbstractFileName;
47 import org.apache.commons.vfs.provider.AbstractFileProvider;
48 import org.apache.commons.vfs.provider.DefaultURLStreamHandler;
49 import org.apache.commons.vfs.provider.FileProvider;
50 import org.apache.commons.vfs.provider.FileReplicator;
51 import org.apache.commons.vfs.provider.LocalFileProvider;
52 import org.apache.commons.vfs.provider.TemporaryFileStore;
53 import org.apache.commons.vfs.provider.UriParser;
54 import org.apache.commons.vfs.provider.VfsComponent;
55
56 /***
57 * A default file system manager implementation.
58 *
59 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
60 * @version $Revision: 484648 $ $Date: 2006-03-30 21:16:24 +0200 (Do, 30 Mrz
61 * 2006) $
62 */
63 public class DefaultFileSystemManager implements FileSystemManager
64 {
65 /***
66 * The provider for local files.
67 */
68 private LocalFileProvider localFileProvider;
69
70 /***
71 * The default provider.
72 */
73 private FileProvider defaultProvider;
74
75 /***
76 * The file replicator to use.
77 */
78 private FileReplicator fileReplicator;
79
80 /***
81 * Mapping from URI scheme to FileProvider.
82 */
83 private final Map providers = new HashMap();
84
85 /***
86 * All components used by this manager.
87 */
88 private final ArrayList components = new ArrayList();
89
90 /***
91 * The base file to use for relative URI.
92 */
93 private FileObject baseFile;
94
95 /***
96 * The files cache
97 */
98 private FilesCache filesCache;
99
100 /***
101 * The cache strategy
102 */
103 private CacheStrategy fileCacheStrategy;
104
105 /***
106 * Class which decorates all returned fileObjects
107 */
108 private Class fileObjectDecorator;
109 private Constructor fileObjectDecoratorConst;
110
111 /***
112 * The class to use to determine the content-type (mime-type)
113 */
114 private FileContentInfoFactory fileContentInfoFactory;
115
116 /***
117 * The logger to use.
118 */
119 private Log log;
120
121 /***
122 * The context to pass to providers.
123 */
124 private final DefaultVfsComponentContext context = new DefaultVfsComponentContext(
125 this);
126
127 private TemporaryFileStore tempFileStore;
128 private final FileTypeMap map = new FileTypeMap();
129 private final VirtualFileProvider vfsProvider = new VirtualFileProvider();
130 private boolean init;
131
132 /***
133 * Returns the logger used by this manager.
134 */
135 protected Log getLogger()
136 {
137 return log;
138 }
139
140 /***
141 * Registers a file system provider. The manager takes care of all lifecycle
142 * management. A provider may be registered multiple times.
143 *
144 * @param urlScheme
145 * The scheme the provider will handle.
146 * @param provider
147 * The provider.
148 */
149 public void addProvider(final String urlScheme, final FileProvider provider)
150 throws FileSystemException
151 {
152 addProvider(new String[]
153 { urlScheme }, provider);
154 }
155
156 /***
157 * Registers a file system provider. The manager takes care of all lifecycle
158 * management. A provider may be registered multiple times.
159 *
160 * @param urlSchemes
161 * The schemes the provider will handle.
162 * @param provider
163 * The provider.
164 */
165 public void addProvider(final String[] urlSchemes,
166 final FileProvider provider) throws FileSystemException
167 {
168
169 for (int i = 0; i < urlSchemes.length; i++)
170 {
171 final String scheme = urlSchemes[i];
172 if (providers.containsKey(scheme))
173 {
174 throw new FileSystemException(
175 "vfs.impl/multiple-providers-for-scheme.error", scheme);
176 }
177 }
178
179
180 setupComponent(provider);
181
182
183 for (int i = 0; i < urlSchemes.length; i++)
184 {
185 final String scheme = urlSchemes[i];
186 providers.put(scheme, provider);
187 }
188
189 if (provider instanceof LocalFileProvider)
190 {
191 localFileProvider = (LocalFileProvider) provider;
192 }
193 }
194
195 /***
196 * Returns true if this manager has a provider for a particular scheme.
197 */
198 public boolean hasProvider(final String scheme)
199 {
200 return providers.containsKey(scheme);
201 }
202
203 /***
204 * Adds an filename extension mapping.
205 *
206 * @param extension
207 * The file name extension.
208 * @param scheme
209 * The scheme to use for files with this extension.
210 */
211 public void addExtensionMap(final String extension, final String scheme)
212 {
213 map.addExtension(extension, scheme);
214 }
215
216 /***
217 * Adds a mime type mapping.
218 *
219 * @param mimeType
220 * The mime type.
221 * @param scheme
222 * The scheme to use for files with this mime type.
223 */
224 public void addMimeTypeMap(final String mimeType, final String scheme)
225 {
226 map.addMimeType(mimeType, scheme);
227 }
228
229 /***
230 * Sets the default provider. This is the provider that will handle URI with
231 * unknown schemes. The manager takes care of all lifecycle management.
232 */
233 public void setDefaultProvider(final FileProvider provider)
234 throws FileSystemException
235 {
236 setupComponent(provider);
237 defaultProvider = provider;
238 }
239
240 /***
241 * Returns the filesCache implementation used to cache files
242 */
243 public FilesCache getFilesCache()
244 {
245 return filesCache;
246 }
247
248 /***
249 * Sets the filesCache implementation used to cache files
250 */
251 public void setFilesCache(final FilesCache filesCache)
252 throws FileSystemException
253 {
254 if (init)
255 {
256 throw new FileSystemException("vfs.impl/already-inited.error");
257 }
258
259 this.filesCache = filesCache;
260 }
261
262 /***
263 * <p>
264 * Set the cache strategy to use when dealing with file object data. You can
265 * set it only once before the FileSystemManager is initialized.
266 * <p />
267 * <p>
268 * The default is {@link CacheStrategy#ON_RESOLVE}
269 * </p>
270 *
271 * @throws FileSystemException
272 * if this is not possible. e.g. it is already set.
273 */
274 public void setCacheStrategy(final CacheStrategy fileCacheStrategy)
275 throws FileSystemException
276 {
277 if (init)
278 {
279 throw new FileSystemException("vfs.impl/already-inited.error");
280 }
281
282 this.fileCacheStrategy = fileCacheStrategy;
283 }
284
285 /***
286 * Get the cache strategy used
287 */
288 public CacheStrategy getCacheStrategy()
289 {
290 return fileCacheStrategy;
291 }
292
293 /***
294 * Get the file object decorator used
295 */
296 public Class getFileObjectDecorator()
297 {
298 return fileObjectDecorator;
299 }
300
301 /***
302 * The constructor associated to the fileObjectDecorator.
303 * We cache it here for performance reasons.
304 */
305 public Constructor getFileObjectDecoratorConst()
306 {
307 return fileObjectDecoratorConst;
308 }
309
310 /***
311 * set a fileObject decorator to be used for ALL returned file objects
312 *
313 * @param fileObjectDecorator must be inherted from {@link DecoratedFileObject} a has to provide a
314 * constructor with a single {@link FileObject} as argument
315 */
316 public void setFileObjectDecorator(Class fileObjectDecorator) throws FileSystemException
317 {
318 if (init)
319 {
320 throw new FileSystemException("vfs.impl/already-inited.error");
321 }
322 if (!DecoratedFileObject.class.isAssignableFrom(fileObjectDecorator))
323 {
324 throw new FileSystemException("vfs.impl/invalid-decorator.error", fileObjectDecorator.getName());
325 }
326
327 try
328 {
329 fileObjectDecoratorConst = fileObjectDecorator.getConstructor(new Class[]{FileObject.class});
330 }
331 catch (NoSuchMethodException e)
332 {
333 throw new FileSystemException("vfs.impl/invalid-decorator.error", fileObjectDecorator.getName(), e);
334 }
335
336 this.fileObjectDecorator = fileObjectDecorator;
337 }
338
339 /***
340 * get the fileContentInfoFactory used to determine the infos of a file
341 * content.
342 */
343 public FileContentInfoFactory getFileContentInfoFactory()
344 {
345 return fileContentInfoFactory;
346 }
347
348 /***
349 * set the fileContentInfoFactory used to determine the infos of a file
350 * content.
351 */
352 public void setFileContentInfoFactory(
353 FileContentInfoFactory fileContentInfoFactory)
354 throws FileSystemException
355 {
356 if (init)
357 {
358 throw new FileSystemException("vfs.impl/already-inited.error");
359 }
360
361 this.fileContentInfoFactory = fileContentInfoFactory;
362 }
363
364 /***
365 * Sets the file replicator to use. The manager takes care of all lifecycle
366 * management.
367 */
368 public void setReplicator(final FileReplicator replicator)
369 throws FileSystemException
370 {
371 setupComponent(replicator);
372 fileReplicator = replicator;
373 }
374
375 /***
376 * Sets the temporary file store to use. The manager takes care of all
377 * lifecycle management.
378 */
379 public void setTemporaryFileStore(final TemporaryFileStore tempFileStore)
380 throws FileSystemException
381 {
382 setupComponent(tempFileStore);
383 this.tempFileStore = tempFileStore;
384 }
385
386 /***
387 * Sets the logger to use.
388 */
389 public void setLogger(final Log log)
390 {
391 this.log = log;
392 }
393
394 /***
395 * Initialises a component, if it has not already been initialised.
396 */
397 private void setupComponent(final Object component)
398 throws FileSystemException
399 {
400 if (!components.contains(component))
401 {
402 if (component instanceof VfsComponent)
403 {
404 final VfsComponent vfsComponent = (VfsComponent) component;
405 vfsComponent.setLogger(getLogger());
406 vfsComponent.setContext(context);
407 vfsComponent.init();
408 }
409 components.add(component);
410 }
411 }
412
413 /***
414 * Closes a component, if it has not already been closed.
415 */
416 private void closeComponent(final Object component)
417 {
418 if (component != null && components.contains(component))
419 {
420 if (component instanceof VfsComponent)
421 {
422 final VfsComponent vfsComponent = (VfsComponent) component;
423 vfsComponent.close();
424 }
425 components.remove(component);
426 }
427 }
428
429 /***
430 * Returns the file replicator.
431 *
432 * @return The file replicator. Never returns null.
433 */
434 public FileReplicator getReplicator() throws FileSystemException
435 {
436 if (fileReplicator == null)
437 {
438 throw new FileSystemException("vfs.impl/no-replicator.error");
439 }
440 return fileReplicator;
441 }
442
443 /***
444 * Returns the temporary file store.
445 *
446 * @return The file store. Never returns null.
447 */
448 public TemporaryFileStore getTemporaryFileStore()
449 throws FileSystemException
450 {
451 if (tempFileStore == null)
452 {
453 throw new FileSystemException("vfs.impl/no-temp-file-store.error");
454 }
455 return tempFileStore;
456 }
457
458 /***
459 * Initialises this manager.
460 */
461 public void init() throws FileSystemException
462 {
463 if (filesCache == null)
464 {
465
466 filesCache = new SoftRefFilesCache();
467 }
468 if (fileContentInfoFactory == null)
469 {
470 fileContentInfoFactory = new FileContentInfoFilenameFactory();
471 }
472
473 if (fileCacheStrategy == null)
474 {
475 fileCacheStrategy = CacheStrategy.ON_RESOLVE;
476 }
477
478 setupComponent(filesCache);
479 setupComponent(vfsProvider);
480
481 init = true;
482 }
483
484 /***
485 * Closes all files created by this manager, and cleans up any temporary
486 * files. Also closes all providers and the replicator.
487 */
488 public void close()
489 {
490 if (!init)
491 {
492 return;
493 }
494
495
496 for (Iterator iterator = providers.values().iterator(); iterator
497 .hasNext();)
498 {
499 final Object provider = iterator.next();
500 closeComponent(provider);
501 }
502
503
504 closeComponent(defaultProvider);
505 closeComponent(fileReplicator);
506 closeComponent(tempFileStore);
507
508 components.clear();
509 providers.clear();
510 filesCache.close();
511 localFileProvider = null;
512 defaultProvider = null;
513 fileReplicator = null;
514 tempFileStore = null;
515 init = false;
516 }
517
518 /***
519 * Free all resources used by unused filesystems created by this manager.
520 */
521 public void freeUnusedResources()
522 {
523 if (!init)
524 {
525 return;
526 }
527
528
529 for (Iterator iterator = providers.values().iterator(); iterator
530 .hasNext();)
531 {
532 final AbstractFileProvider provider = (AbstractFileProvider) iterator
533 .next();
534 provider.freeUnusedResources();
535 }
536 }
537
538 /***
539 * Sets the base file to use when resolving relative URI.
540 */
541
542 public void setBaseFile(final FileObject baseFile)
543 throws FileSystemException
544 {
545 this.baseFile = baseFile;
546 }
547
548 /***
549 * Sets the base file to use when resolving relative URI.
550 */
551 public void setBaseFile(final File baseFile) throws FileSystemException
552 {
553 this.baseFile = getLocalFileProvider().findLocalFile(baseFile);
554 }
555
556 /***
557 * Returns the base file used to resolve relative URI.
558 */
559 public FileObject getBaseFile() throws FileSystemException
560 {
561 return baseFile;
562 }
563
564 /***
565 * Locates a file by URI.
566 */
567 public FileObject resolveFile(final String uri) throws FileSystemException
568 {
569
570 return resolveFile(getBaseFile(), uri);
571 }
572
573 /***
574 * Locate a file by URI, use the FileSystemOptions for file-system creation
575 */
576
577 public FileObject resolveFile(final String uri,
578 final FileSystemOptions fileSystemOptions)
579 throws FileSystemException
580 {
581
582 return resolveFile(getBaseFile(), uri, fileSystemOptions);
583 }
584
585 /***
586 * Locates a file by URI.
587 */
588 public FileObject resolveFile(final File baseFile, final String uri)
589 throws FileSystemException
590 {
591 final FileObject baseFileObj = getLocalFileProvider().findLocalFile(
592 baseFile);
593 return resolveFile(baseFileObj, uri);
594 }
595
596 /***
597 * Resolves a URI, relative to a base file.
598 */
599 public FileObject resolveFile(final FileObject baseFile, final String uri)
600 throws FileSystemException
601 {
602 return resolveFile(baseFile, uri, baseFile == null ? null : baseFile
603 .getFileSystem().getFileSystemOptions());
604 }
605
606 /***
607 * Resolves a URI, realtive to a base file with specified FileSystem
608 * configuration
609 */
610 public FileObject resolveFile(final FileObject baseFile, final String uri,
611 final FileSystemOptions fileSystemOptions)
612 throws FileSystemException
613 {
614 final FileObject realBaseFile;
615 if (baseFile != null && VFS.isUriStyle()
616 && baseFile.getName().getType() == FileType.FILE)
617 {
618 realBaseFile = baseFile.getParent();
619 }
620 else
621 {
622 realBaseFile = baseFile;
623 }
624
625
626 UriParser.checkUriEncoding(uri);
627
628 if (uri == null)
629 {
630 throw new IllegalArgumentException();
631 }
632
633
634 final String scheme = UriParser.extractScheme(uri);
635 if (scheme != null)
636 {
637
638 final FileProvider provider = (FileProvider) providers.get(scheme);
639 if (provider != null)
640 {
641 return provider.findFile(realBaseFile, uri, fileSystemOptions);
642 }
643
644 }
645
646
647 if (localFileProvider != null
648 && localFileProvider.isAbsoluteLocalName(uri))
649 {
650 return localFileProvider.findLocalFile(uri);
651 }
652
653 if (scheme != null)
654 {
655
656 if (defaultProvider == null)
657 {
658 throw new FileSystemException("vfs.impl/unknown-scheme.error",
659 new Object[]
660 { scheme, uri });
661 }
662 return defaultProvider.findFile(realBaseFile, uri,
663 fileSystemOptions);
664 }
665
666
667 if (realBaseFile == null)
668 {
669 throw new FileSystemException("vfs.impl/find-rel-file.error", uri);
670 }
671
672 return realBaseFile.resolveFile(uri);
673 }
674
675 /***
676 * Resolves a name, relative to the file. If the supplied name is an
677 * absolute path, then it is resolved relative to the root of the file
678 * system that the file belongs to. If a relative name is supplied, then it
679 * is resolved relative to this file name.
680 */
681 public FileName resolveName(final FileName root, final String path)
682 throws FileSystemException
683 {
684 return resolveName(root, path, NameScope.FILE_SYSTEM);
685 }
686
687 /***
688 * Resolves a name, relative to the root.
689 *
690 * @param base
691 * the base filename
692 * @param name
693 * the name
694 * @param scope
695 * the {@link NameScope}
696 * @throws FileSystemException
697 */
698 public FileName resolveName(final FileName base, final String name,
699 final NameScope scope) throws FileSystemException
700 {
701 final FileName realBase;
702 if (base != null && VFS.isUriStyle() && base.getType() == FileType.FILE)
703 {
704 realBase = base.getParent();
705 }
706 else
707 {
708 realBase = base;
709 }
710
711 final StringBuffer buffer = new StringBuffer(name);
712
713
714 UriParser.fixSeparators(buffer);
715
716
717 if (name.length() == 0 || name.charAt(0) != FileName.SEPARATOR_CHAR)
718 {
719
720 if (!VFS.isUriStyle())
721 {
722
723 buffer.insert(0, FileName.SEPARATOR_CHAR);
724 }
725 buffer.insert(0, realBase.getPath());
726 }
727
728
729
730
731 FileType fileType = UriParser.normalisePath(buffer);
732
733
734 final String resolvedPath = buffer.toString();
735 if (!AbstractFileName
736 .checkName(realBase.getPath(), resolvedPath, scope))
737 {
738 throw new FileSystemException(
739 "vfs.provider/invalid-descendent-name.error", name);
740 }
741
742 String scheme = realBase.getScheme();
743 String fullPath = realBase.getRootURI() + resolvedPath;
744 final FileProvider provider = (FileProvider) providers.get(scheme);
745 if (provider != null)
746 {
747
748
749
750
751
752
753 return provider.parseUri(realBase, fullPath);
754 }
755
756 if (scheme != null)
757 {
758
759 if (defaultProvider != null)
760 {
761 return defaultProvider.parseUri(realBase, fullPath);
762 }
763 }
764
765
766
767 return ((AbstractFileName) realBase).createName(resolvedPath, fileType);
768 }
769
770 /***
771 * resolve the uri to a filename
772 *
773 * @throws FileSystemException
774 */
775 public FileName resolveURI(String uri) throws FileSystemException
776 {
777 UriParser.checkUriEncoding(uri);
778
779 if (uri == null)
780 {
781 throw new IllegalArgumentException();
782 }
783
784
785 final String scheme = UriParser.extractScheme(uri);
786 if (scheme != null)
787 {
788
789 final FileProvider provider = (FileProvider) providers.get(scheme);
790 if (provider != null)
791 {
792 return provider.parseUri(null, uri);
793 }
794
795
796 }
797
798
799 if (localFileProvider != null
800 && localFileProvider.isAbsoluteLocalName(uri))
801 {
802 return localFileProvider.parseUri(null, uri);
803 }
804
805 if (scheme != null)
806 {
807
808 if (defaultProvider == null)
809 {
810 throw new FileSystemException("vfs.impl/unknown-scheme.error",
811 new Object[]
812 { scheme, uri });
813 }
814 return defaultProvider.parseUri(null, uri);
815 }
816
817
818 if (baseFile == null)
819 {
820 throw new FileSystemException("vfs.impl/find-rel-file.error", uri);
821 }
822
823 return resolveName(baseFile.getName(), uri, NameScope.FILE_SYSTEM);
824 }
825
826 /***
827 * Converts a local file into a {@link FileObject}.
828 */
829 public FileObject toFileObject(final File file) throws FileSystemException
830 {
831 return getLocalFileProvider().findLocalFile(file);
832 }
833
834 /***
835 * Creates a layered file system.
836 */
837 public FileObject createFileSystem(final String scheme,
838 final FileObject file) throws FileSystemException
839 {
840 final FileProvider provider = (FileProvider) providers.get(scheme);
841 if (provider == null)
842 {
843 throw new FileSystemException("vfs.impl/unknown-provider.error",
844 new Object[]
845 { scheme, file });
846 }
847 return provider.createFileSystem(scheme, file, file.getFileSystem()
848 .getFileSystemOptions());
849 }
850
851 /***
852 * Creates a layered file system.
853 */
854 public FileObject createFileSystem(final FileObject file)
855 throws FileSystemException
856 {
857 final String scheme = map.getScheme(file);
858 if (scheme == null)
859 {
860 throw new FileSystemException(
861 "vfs.impl/no-provider-for-file.error", file);
862 }
863
864 return createFileSystem(scheme, file);
865 }
866
867 /***
868 * Determines if a layered file system can be created for a given file.
869 *
870 * @param file
871 * The file to check for.
872 */
873 public boolean canCreateFileSystem(final FileObject file)
874 throws FileSystemException
875 {
876 return (map.getScheme(file) != null);
877 }
878
879 /***
880 * Creates a virtual file system.
881 */
882 public FileObject createVirtualFileSystem(final FileObject rootFile)
883 throws FileSystemException
884 {
885 return vfsProvider.createFileSystem(rootFile);
886 }
887
888 /***
889 * Creates an empty virtual file system.
890 */
891 public FileObject createVirtualFileSystem(final String rootUri)
892 throws FileSystemException
893 {
894 return vfsProvider.createFileSystem(rootUri);
895 }
896
897 /***
898 * Locates the local file provider.
899 */
900 private LocalFileProvider getLocalFileProvider() throws FileSystemException
901 {
902 if (localFileProvider == null)
903 {
904 throw new FileSystemException(
905 "vfs.impl/no-local-file-provider.error");
906 }
907 return localFileProvider;
908 }
909
910 /***
911 * Get the URLStreamHandlerFactory.
912 */
913 public URLStreamHandlerFactory getURLStreamHandlerFactory()
914 {
915 return new VfsStreamHandlerFactory();
916 }
917
918 /***
919 * Closes the given filesystem.<br />
920 * If you use VFS as singleton it is VERY dangerous to call this method
921 */
922 public void closeFileSystem(FileSystem filesystem)
923 {
924
925 getFilesCache().clear(filesystem);
926
927
928 _closeFileSystem(filesystem);
929 }
930
931 /***
932 * Closes the given filesystem.<br />
933 * If you use VFS as singleton it is VERY dangerous to call this method
934 */
935 public void _closeFileSystem(FileSystem filesystem)
936 {
937 FileProvider provider = (FileProvider) providers.get(filesystem
938 .getRootName().getScheme());
939 if (provider != null)
940 {
941 ((AbstractFileProvider) provider).closeFileSystem(filesystem);
942 }
943 }
944
945 /***
946 * This is an internal class because it needs access to the private member
947 * providers.
948 */
949 final class VfsStreamHandlerFactory implements URLStreamHandlerFactory
950 {
951 public URLStreamHandler createURLStreamHandler(final String protocol)
952 {
953 FileProvider provider = (FileProvider) providers.get(protocol);
954 if (provider != null)
955 {
956 return new DefaultURLStreamHandler(context);
957 }
958
959
960 return new URLStreamHandlerProxy();
961 }
962 }
963
964 /***
965 * Get the schemes currently available.
966 */
967 public String[] getSchemes()
968 {
969 String[] schemes = new String[providers.size()];
970 providers.keySet().toArray(schemes);
971 return schemes;
972 }
973
974 /***
975 * Get the capabilities for a given scheme.
976 *
977 * @throws FileSystemException
978 * if the given scheme is not konwn
979 */
980 public Collection getProviderCapabilities(final String scheme)
981 throws FileSystemException
982 {
983 FileProvider provider = (FileProvider) providers.get(scheme);
984 if (provider == null)
985 {
986 throw new FileSystemException("vfs.impl/unknown-scheme.error",
987 new Object[]
988 { scheme });
989 }
990
991 return provider.getCapabilities();
992 }
993
994 /***
995 * Get the configuration builder for the given scheme
996 *
997 * @throws FileSystemException
998 * if the given scheme is not konwn
999 */
1000 public FileSystemConfigBuilder getFileSystemConfigBuilder(
1001 final String scheme) throws FileSystemException
1002 {
1003 FileProvider provider = (FileProvider) providers.get(scheme);
1004 if (provider == null)
1005 {
1006 throw new FileSystemException("vfs.impl/unknown-scheme.error",
1007 new Object[]
1008 { scheme });
1009 }
1010
1011 return provider.getConfigBuilder();
1012 }
1013
1014
1015
1016 private final Map operationProviders = new HashMap();
1017
1018 /***
1019 * Adds the specified FileOperationProvider for the specified scheme.
1020 * Several FileOperationProvider's might be registered for the same scheme.
1021 * For example, for "file" scheme we can register SvnWsOperationProvider and
1022 * CvsOperationProvider.
1023 *
1024 * @param scheme
1025 * @param operationProvider
1026 * @throws FileSystemException
1027 */
1028 public void addOperationProvider(final String scheme,
1029 final FileOperationProvider operationProvider)
1030 throws FileSystemException
1031 {
1032 addOperationProvider(new String[]
1033 { scheme }, operationProvider);
1034 }
1035
1036 /***
1037 * @see FileSystemManager#addOperationProvider(String,
1038 * org.apache.commons.vfs.operations.FileOperationProvider)
1039 *
1040 * @param schemes
1041 * @param operationProvider
1042 * @throws FileSystemException
1043 */
1044 public void addOperationProvider(final String[] schemes,
1045 final FileOperationProvider operationProvider)
1046 throws FileSystemException
1047 {
1048 for (int i = 0; i < schemes.length; i++)
1049 {
1050 final String scheme = schemes[i];
1051
1052 if (!operationProviders.containsKey(scheme))
1053 {
1054 final List providers = new ArrayList();
1055 operationProviders.put(scheme, providers);
1056 }
1057
1058 final List providers = (List) operationProviders.get(scheme);
1059
1060 if (providers.contains(operationProvider))
1061 {
1062 throw new FileSystemException(
1063 "vfs.operation/operation-provider-already-added.error",
1064 scheme);
1065 }
1066
1067 setupComponent(operationProvider);
1068
1069 providers.add(operationProvider);
1070 }
1071 }
1072
1073 /***
1074 * @param scheme
1075 * the scheme for wich we want to get the list af registered
1076 * providers.
1077 *
1078 * @return the registered FileOperationProviders for the specified scheme.
1079 * If there were no providers registered for the scheme, it returns
1080 * null.
1081 *
1082 * @throws FileSystemException
1083 */
1084 public FileOperationProvider[] getOperationProviders(final String scheme)
1085 throws FileSystemException
1086 {
1087
1088 List providers = (List) operationProviders.get(scheme);
1089 if (providers == null || providers.size() == 0)
1090 {
1091 return null;
1092 }
1093 return (FileOperationProvider[]) providers
1094 .toArray(new FileOperationProvider[] {});
1095 }
1096 }