View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.provider;
18  
19  import java.util.Map;
20  import java.util.TreeMap;
21  
22  import org.apache.commons.vfs2.FileName;
23  import org.apache.commons.vfs2.FileObject;
24  import org.apache.commons.vfs2.FileSystem;
25  import org.apache.commons.vfs2.FileSystemConfigBuilder;
26  import org.apache.commons.vfs2.FileSystemException;
27  import org.apache.commons.vfs2.FileSystemOptions;
28  import org.apache.commons.vfs2.provider.local.GenericFileNameParser;
29  
30  /**
31   * A partial {@link FileProvider} implementation. Takes care of managing the file systems created by the provider.
32   */
33  public abstract class AbstractFileProvider extends AbstractVfsContainer implements FileProvider {
34      private static final AbstractFileSystembstractFileSystem">AbstractFileSystem[] EMPTY_ABSTRACTFILESYSTEMS = new AbstractFileSystem[0];
35  
36      /**
37       * The cached file systems.
38       * <p>
39       * This is a mapping from {@link FileSystemKey} (root URI and options) to {@link FileSystem}.
40       * </p>
41       */
42      private final Map<FileSystemKey, FileSystem> fileSystems = new TreeMap<>(); // @GuardedBy("self")
43  
44      private FileNameParser parser;
45  
46      public AbstractFileProvider() {
47          parser = GenericFileNameParser.getInstance();
48      }
49  
50      protected FileNameParser getFileNameParser() {
51          return parser;
52      }
53  
54      protected void setFileNameParser(final FileNameParser parser) {
55          this.parser = parser;
56      }
57  
58      /**
59       * Closes the file systems created by this provider.
60       */
61      @Override
62      public void close() {
63          synchronized (fileSystems) {
64              fileSystems.clear();
65          }
66  
67          super.close();
68      }
69  
70      /**
71       * Creates a layered file system. This method throws a 'not supported' exception.
72       *
73       * @param scheme The protocol to use to access the file.
74       * @param file a FileObject.
75       * @param properties Options to the file system.
76       * @return A FileObject associated with the new FileSystem.
77       * @throws FileSystemException if an error occurs.
78       */
79      @Override
80      public FileObject createFileSystem(FileObject="jxr_keyword">final String scheme, final FileObject file, final FileSystemOptions properties)
81              throws FileSystemException {
82          // Can't create a layered file system
83          throw new FileSystemException("vfs.provider/not-layered-fs.error", scheme);
84      }
85  
86      /**
87       * Adds a file system to those cached by this provider.
88       * <p>
89       * The file system may implement {@link VfsComponent}, in which case it is initialised.
90       * </p>
91       *
92       * @param key The root file of the file system, part of the cache key.
93       * @param fs the file system to add.
94       * @throws FileSystemException if any error occurs.
95       */
96      protected void addFileSystem(final Comparable<?> key, final FileSystem fs) throws FileSystemException {
97          // Add to the container and initialize
98          addComponent(fs);
99  
100         final FileSystemKeyFileSystemKey.html#FileSystemKey">FileSystemKey treeKey = new FileSystemKey(key, fs.getFileSystemOptions());
101         ((AbstractFileSystem) fs).setCacheKey(treeKey);
102 
103         synchronized (fileSystems) {
104             fileSystems.put(treeKey, fs);
105         }
106     }
107 
108     /**
109      * Locates a cached file system.
110      *
111      * @param key The root file of the file system, part of the cache key.
112      * @param fileSystemProps file system options the file system instance must have.
113      * @return The file system instance, or null if it is not cached.
114      */
115     protected FileSystem findFileSystem(final Comparable<?> key, final FileSystemOptions fileSystemProps) {
116         final FileSystemKeyFileSystemKey.html#FileSystemKey">FileSystemKey treeKey = new FileSystemKey(key, fileSystemProps);
117 
118         synchronized (fileSystems) {
119             return fileSystems.get(treeKey);
120         }
121     }
122 
123     /**
124      * Returns the FileSystemConfigBuidler.
125      *
126      * @return the FileSystemConfigBuilder.
127      */
128     @Override
129     public FileSystemConfigBuilder getConfigBuilder() {
130         return null;
131     }
132 
133     /**
134      * Free unused resources.
135      */
136     public void freeUnusedResources() {
137         AbstractFileSystem[] abstractFileSystems;
138         synchronized (fileSystems) {
139             // create snapshot under lock
140             abstractFileSystems = fileSystems.values().toArray(EMPTY_ABSTRACTFILESYSTEMS);
141         }
142 
143         // process snapshot outside lock
144         for (final AbstractFileSystem fs : abstractFileSystems) {
145             if (fs.isReleaseable()) {
146                 fs.closeCommunicationLink();
147             }
148         }
149     }
150 
151     /**
152      * Close the FileSystem.
153      *
154      * @param fileSystem The FileSystem to close.
155      */
156     public void closeFileSystem(final FileSystem fileSystem) {
157         final AbstractFileSystem/../../org/apache/commons/vfs2/provider/AbstractFileSystem.html#AbstractFileSystem">AbstractFileSystem fs = (AbstractFileSystem) fileSystem;
158 
159         final FileSystemKey key = fs.getCacheKey();
160         if (key != null) {
161             synchronized (fileSystems) {
162                 fileSystems.remove(key);
163             }
164         }
165 
166         removeComponent(fs);
167         fs.close();
168     }
169 
170     /**
171      * Parses an absolute URI.
172      *
173      * @param base The base file - if null the {@code uri} needs to be absolute
174      * @param uri The URI to parse.
175      * @return The FileName.
176      * @throws FileSystemException if an error occurs.
177      */
178     @Override
179     public FileNameame.html#FileName">FileName parseUri(final FileName base, final String uri) throws FileSystemException {
180         if (getFileNameParser() != null) {
181             return getFileNameParser().parseUri(getContext(), base, uri);
182         }
183 
184         throw new FileSystemException("vfs.provider/filename-parser-missing.error");
185     }
186 }