001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.vfs2.provider;
018
019 import java.util.Map;
020 import java.util.TreeMap;
021
022 import org.apache.commons.vfs2.FileName;
023 import org.apache.commons.vfs2.FileObject;
024 import org.apache.commons.vfs2.FileSystem;
025 import org.apache.commons.vfs2.FileSystemConfigBuilder;
026 import org.apache.commons.vfs2.FileSystemException;
027 import org.apache.commons.vfs2.FileSystemOptions;
028 import org.apache.commons.vfs2.provider.local.GenericFileNameParser;
029
030 /**
031 * A partial {@link FileProvider} implementation. Takes care of managing the
032 * file systems created by the provider.
033 *
034 * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
035 */
036 public abstract class AbstractFileProvider
037 extends AbstractVfsContainer
038 implements FileProvider
039 {
040 /**
041 * The cached file systems. This is a mapping from root URI to
042 * FileSystem object.
043 */
044 // private final Map fileSystems = new HashMap();
045 private final Map<FileSystemKey, FileSystem> fileSystems = new TreeMap<FileSystemKey, FileSystem>();
046
047 private FileNameParser parser;
048
049 public AbstractFileProvider()
050 {
051 parser = GenericFileNameParser.getInstance();
052 }
053
054 protected FileNameParser getFileNameParser()
055 {
056 return parser;
057 }
058
059 protected void setFileNameParser(FileNameParser parser)
060 {
061 this.parser = parser;
062 }
063
064 /**
065 * Closes the file systems created by this provider.
066 */
067 @Override
068 public void close()
069 {
070 synchronized (this)
071 {
072 fileSystems.clear();
073 }
074
075 super.close();
076 }
077
078 /**
079 * Creates a layered file system. This method throws a 'not supported' exception.
080 * @param scheme The protocol to use to access the file.
081 * @param file a FileObject.
082 * @param properties Options to the file system.
083 * @return A FileObject associated with the new FileSystem.
084 * @throws FileSystemException if an error occurs.
085 */
086 public FileObject createFileSystem(final String scheme, final FileObject file, final FileSystemOptions properties)
087 throws FileSystemException
088 {
089 // Can't create a layered file system
090 throw new FileSystemException("vfs.provider/not-layered-fs.error", scheme);
091 }
092
093 /**
094 * Adds a file system to those cached by this provider. The file system
095 * may implement {@link VfsComponent}, in which case it is initialised.
096 */
097 protected void addFileSystem(final Comparable<?> key, final FileSystem fs)
098 throws FileSystemException
099 {
100 // Add to the cache
101 addComponent(fs);
102
103 FileSystemKey treeKey = new FileSystemKey(key, fs.getFileSystemOptions());
104 ((AbstractFileSystem) fs).setCacheKey(treeKey);
105
106 synchronized (this)
107 {
108 fileSystems.put(treeKey, fs);
109 }
110 }
111
112 /**
113 * Locates a cached file system
114 *
115 * @return The provider, or null if it is not cached.
116 */
117 protected FileSystem findFileSystem(final Comparable<?> key, final FileSystemOptions fileSystemProps)
118 {
119 FileSystemKey treeKey = new FileSystemKey(key, fileSystemProps);
120
121 synchronized (this)
122 {
123 return fileSystems.get(treeKey);
124 }
125 }
126
127 /**
128 * Returns the FileSystemConfigBuidler.
129 * @return the FileSystemConfigBuilder.
130 */
131 public FileSystemConfigBuilder getConfigBuilder()
132 {
133 return null;
134 }
135
136 /**
137 * Free unused resources.
138 */
139 public void freeUnusedResources()
140 {
141 Object[] item;
142 synchronized (this)
143 {
144 item = fileSystems.values().toArray();
145 }
146 for (int i = 0; i < item.length; ++i)
147 {
148 AbstractFileSystem fs = (AbstractFileSystem) item[i];
149 if (fs.isReleaseable())
150 {
151 fs.closeCommunicationLink();
152 }
153 }
154 }
155
156 /**
157 * Close the FileSystem.
158 * @param filesystem The FileSystem to close.
159 */
160 public void closeFileSystem(final FileSystem filesystem)
161 {
162 AbstractFileSystem fs = (AbstractFileSystem) filesystem;
163
164 synchronized (this)
165 {
166 if (fs.getCacheKey() != null)
167 {
168 fileSystems.remove(fs.getCacheKey());
169 }
170 }
171
172 removeComponent(fs);
173 fs.close();
174 }
175
176 /**
177 * Parses an absolute URI.
178 *
179 * @param base The base file - if null the <code>uri</code> needs to be absolute
180 * @param uri The URI to parse.
181 * @return The FileName.
182 * @throws FileSystemException if an error occurs.
183 */
184 public FileName parseUri(FileName base, String uri) throws FileSystemException
185 {
186 if (getFileNameParser() != null)
187 {
188 return getFileNameParser().parseUri(getContext(), base, uri);
189 }
190
191 throw new FileSystemException("vfs.provider/filename-parser-missing.error");
192 // return GenericFileName.parseUri(getFileNameParser(), uri, 0);
193 }
194 }