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.configuration;
018
019 import org.apache.commons.vfs2.FileObject;
020 import org.apache.commons.vfs2.FileName;
021 import org.apache.commons.vfs2.VFS;
022 import org.apache.commons.vfs2.FileSystemManager;
023 import org.apache.commons.vfs2.FileContent;
024 import org.apache.commons.vfs2.FileSystemException;
025 import org.apache.commons.vfs2.FileType;
026 import org.apache.commons.vfs2.FileSystemOptions;
027 import org.apache.commons.vfs2.FileSystemConfigBuilder;
028 import org.apache.commons.vfs2.provider.UriParser;
029
030 import java.io.InputStream;
031 import java.io.OutputStream;
032 import java.io.File;
033 import java.io.IOException;
034 import java.net.URL;
035 import java.net.URLStreamHandler;
036 import java.net.MalformedURLException;
037 import java.net.URLConnection;
038 import java.util.Map;
039 import java.util.Iterator;
040 import java.lang.reflect.Method;
041
042 /**
043 * FileSystem that uses Commons VFS
044 * @since 1.7
045 * @author <a
046 * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
047 */
048 public class VFSFileSystem extends DefaultFileSystem
049 {
050 public VFSFileSystem()
051 {
052 }
053
054 public InputStream getInputStream(String basePath, String fileName)
055 throws ConfigurationException
056 {
057 try
058 {
059 FileSystemManager manager = VFS.getManager();
060 FileName path;
061 if (basePath != null)
062 {
063 FileName base = manager.resolveURI(basePath);
064 path = manager.resolveName(base, fileName);
065 }
066 else
067 {
068 FileName file = manager.resolveURI(fileName);
069 FileName base = file.getParent();
070 path = manager.resolveName(base, file.getBaseName());
071 }
072 FileSystemOptions opts = getOptions(path.getScheme());
073 FileObject file = (opts == null) ? manager.resolveFile(path.getURI())
074 : manager.resolveFile(path.getURI(), opts);
075 FileContent content = file.getContent();
076 if (content == null)
077 {
078 String msg = "Cannot access content of " + file.getName().getFriendlyURI();
079 throw new ConfigurationException(msg);
080 }
081 return content.getInputStream();
082 }
083 catch (ConfigurationException e)
084 {
085 throw e;
086 }
087 catch (Exception e)
088 {
089 throw new ConfigurationException("Unable to load the configuration file " + fileName, e);
090 }
091 }
092
093 public InputStream getInputStream(URL url) throws ConfigurationException
094 {
095 FileObject file;
096 try
097 {
098 FileSystemOptions opts = getOptions(url.getProtocol());
099 file = (opts == null) ? VFS.getManager().resolveFile(url.toString())
100 : VFS.getManager().resolveFile(url.toString(), opts);
101 if (file.getType() != FileType.FILE)
102 {
103 throw new ConfigurationException("Cannot load a configuration from a directory");
104 }
105 FileContent content = file.getContent();
106 if (content == null)
107 {
108 String msg = "Cannot access content of " + file.getName().getFriendlyURI();
109 throw new ConfigurationException(msg);
110 }
111 return content.getInputStream();
112 }
113 catch (FileSystemException fse)
114 {
115 String msg = "Unable to access " + url.toString();
116 throw new ConfigurationException(msg, fse);
117 }
118 }
119
120 public OutputStream getOutputStream(URL url) throws ConfigurationException
121 {
122 try
123 {
124 FileSystemOptions opts = getOptions(url.getProtocol());
125 FileSystemManager fsManager = VFS.getManager();
126 FileObject file = (opts == null) ? fsManager.resolveFile(url.toString())
127 : fsManager.resolveFile(url.toString(), opts);
128 // throw an exception if the target URL is a directory
129 if (file == null || file.getType() == FileType.FOLDER)
130 {
131 throw new ConfigurationException("Cannot save a configuration to a directory");
132 }
133 FileContent content = file.getContent();
134
135 if (content == null)
136 {
137 throw new ConfigurationException("Cannot access content of " + url);
138 }
139 return content.getOutputStream();
140 }
141 catch (FileSystemException fse)
142 {
143 throw new ConfigurationException("Unable to access " + url, fse);
144 }
145 }
146
147 public String getPath(File file, URL url, String basePath, String fileName)
148 {
149 if (file != null)
150 {
151 return super.getPath(file, url, basePath, fileName);
152 }
153 try
154 {
155 FileSystemManager fsManager = VFS.getManager();
156 if (url != null)
157 {
158 FileName name = fsManager.resolveURI(url.toString());
159 if (name != null)
160 {
161 return name.toString();
162 }
163 }
164
165 if (UriParser.extractScheme(fileName) != null)
166 {
167 return fileName;
168 }
169 else if (basePath != null)
170 {
171 FileName base = fsManager.resolveURI(basePath);
172 return fsManager.resolveName(base, fileName).getURI();
173 }
174 else
175 {
176 FileName name = fsManager.resolveURI(fileName);
177 FileName base = name.getParent();
178 return fsManager.resolveName(base, name.getBaseName()).getURI();
179 }
180 }
181 catch (FileSystemException fse)
182 {
183 fse.printStackTrace();
184 return null;
185 }
186 }
187
188 public String getBasePath(String path)
189 {
190 if (UriParser.extractScheme(path) == null)
191 {
192 return super.getBasePath(path);
193 }
194 try
195 {
196 FileSystemManager fsManager = VFS.getManager();
197 FileName name = fsManager.resolveURI(path);
198 return name.getParent().getURI();
199 }
200 catch (FileSystemException fse)
201 {
202 fse.printStackTrace();
203 return null;
204 }
205 }
206
207 public String getFileName(String path)
208 {
209 if (UriParser.extractScheme(path) == null)
210 {
211 return super.getFileName(path);
212 }
213 try
214 {
215 FileSystemManager fsManager = VFS.getManager();
216 FileName name = fsManager.resolveURI(path);
217 return name.getBaseName();
218 }
219 catch (FileSystemException fse)
220 {
221 fse.printStackTrace();
222 return null;
223 }
224 }
225
226 public URL getURL(String basePath, String file) throws MalformedURLException
227 {
228 if ((basePath != null && UriParser.extractScheme(basePath) == null)
229 || (basePath == null && UriParser.extractScheme(file) == null))
230 {
231 return super.getURL(basePath, file);
232 }
233 try
234 {
235 FileSystemManager fsManager = VFS.getManager();
236
237 FileName path;
238 if (basePath != null && UriParser.extractScheme(file) == null)
239 {
240 FileName base = fsManager.resolveURI(basePath);
241 path = fsManager.resolveName(base, file);
242 }
243 else
244 {
245 path = fsManager.resolveURI(file);
246 }
247
248 URLStreamHandler handler = new VFSURLStreamHandler(path);
249 return new URL(null, path.getURI(), handler);
250 }
251 catch (FileSystemException fse)
252 {
253 throw new ConfigurationRuntimeException("Could not parse basePath: " + basePath
254 + " and fileName: " + file, fse);
255 }
256 }
257
258 public URL locateFromURL(String basePath, String fileName)
259 {
260 String fileScheme = UriParser.extractScheme(fileName);
261
262 // Use DefaultFileSystem if basePath and fileName don't have a scheme.
263 if ((basePath == null || UriParser.extractScheme(basePath) == null) && fileScheme == null)
264 {
265 return super.locateFromURL(basePath, fileName);
266 }
267 try
268 {
269 FileSystemManager fsManager = VFS.getManager();
270
271 FileObject file;
272 // Only use the base path if the file name doesn't have a scheme.
273 if (basePath != null && fileScheme == null)
274 {
275 String scheme = UriParser.extractScheme(basePath);
276 FileSystemOptions opts = (scheme != null) ? getOptions(scheme) : null;
277 FileObject base = (opts == null) ? fsManager.resolveFile(basePath)
278 : fsManager.resolveFile(basePath, opts);
279 if (base.getType() == FileType.FILE)
280 {
281 base = base.getParent();
282 }
283
284 file = fsManager.resolveFile(base, fileName);
285 }
286 else
287 {
288 FileSystemOptions opts = (fileScheme != null) ? getOptions(fileScheme) : null;
289 file = (opts == null) ? fsManager.resolveFile(fileName)
290 : fsManager.resolveFile(fileName, opts);
291 }
292
293 if (!file.exists())
294 {
295 return null;
296 }
297 FileName path = file.getName();
298 URLStreamHandler handler = new VFSURLStreamHandler(path);
299 return new URL(null, path.getURI(), handler);
300 }
301 catch (FileSystemException fse)
302 {
303 return null;
304 }
305 catch (MalformedURLException ex)
306 {
307 return null;
308 }
309 }
310
311 private FileSystemOptions getOptions(String scheme)
312 {
313 FileSystemOptions opts = new FileSystemOptions();
314 FileSystemConfigBuilder builder;
315 try
316 {
317 builder = VFS.getManager().getFileSystemConfigBuilder(scheme);
318 }
319 catch (Exception ex)
320 {
321 return null;
322 }
323 FileOptionsProvider provider = getFileOptionsProvider();
324 if (provider != null)
325 {
326 Map map = provider.getOptions();
327 if (map == null)
328 {
329 return null;
330 }
331 Iterator iter = map.entrySet().iterator();
332 int count = 0;
333 while (iter.hasNext())
334 {
335 Map.Entry entry = (Map.Entry) iter.next();
336 try
337 {
338 String key = (String) entry.getKey();
339 if (FileOptionsProvider.CURRENT_USER.equals(key))
340 {
341 key = "creatorName";
342 }
343 setProperty(builder, opts, key, entry.getValue());
344 ++count;
345 }
346 catch (Exception ex)
347 {
348 // Ignore an incorrect property.
349 continue;
350 }
351 }
352 if (count > 0)
353 {
354 return opts;
355 }
356 }
357 return null;
358
359 }
360
361 private void setProperty(FileSystemConfigBuilder builder, FileSystemOptions options,
362 String key, Object value)
363 {
364 String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
365 Class[] paramTypes = new Class[2];
366 paramTypes[0] = FileSystemOptions.class;
367 paramTypes[1] = value.getClass();
368
369 try
370 {
371 Method method = builder.getClass().getMethod(methodName, paramTypes);
372 Object[] params = new Object[2];
373 params[0] = options;
374 params[1] = value;
375 method.invoke(builder, params);
376 }
377 catch (Exception ex)
378 {
379 return;
380 }
381
382 }
383
384 /**
385 * Stream handler required to create URL.
386 */
387 private static class VFSURLStreamHandler extends URLStreamHandler
388 {
389 /** The Protocol used */
390 private final String protocol;
391
392 public VFSURLStreamHandler(FileName file)
393 {
394 this.protocol = file.getScheme();
395 }
396
397 protected URLConnection openConnection(URL url) throws IOException
398 {
399 throw new IOException("VFS URLs can only be used with VFS APIs");
400 }
401 }
402 }