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.configuration;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.lang.reflect.Method;
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.net.URLConnection;
27  import java.net.URLStreamHandler;
28  import java.util.Map;
29  
30  import org.apache.commons.vfs2.FileContent;
31  import org.apache.commons.vfs2.FileName;
32  import org.apache.commons.vfs2.FileObject;
33  import org.apache.commons.vfs2.FileSystemConfigBuilder;
34  import org.apache.commons.vfs2.FileSystemException;
35  import org.apache.commons.vfs2.FileSystemManager;
36  import org.apache.commons.vfs2.FileSystemOptions;
37  import org.apache.commons.vfs2.FileType;
38  import org.apache.commons.vfs2.VFS;
39  import org.apache.commons.vfs2.provider.UriParser;
40  
41  /**
42   * FileSystem that uses Commons VFS
43   * @since 1.7
44   * @author <a
45   * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
46   * @version $Id: VFSFileSystem.java 1210205 2011-12-04 20:38:19Z oheger $
47   */
48  public class VFSFileSystem extends DefaultFileSystem
49  {
50      public VFSFileSystem()
51      {
52      }
53  
54      @Override
55      public InputStream getInputStream(String basePath, String fileName)
56          throws ConfigurationException
57      {
58          try
59          {
60              FileSystemManager manager = VFS.getManager();
61              FileName path;
62              if (basePath != null)
63              {
64                  FileName base = manager.resolveURI(basePath);
65                  path = manager.resolveName(base, fileName);
66              }
67              else
68              {
69                  FileName file = manager.resolveURI(fileName);
70                  FileName base = file.getParent();
71                  path = manager.resolveName(base, file.getBaseName());
72              }
73              FileSystemOptions opts = getOptions(path.getScheme());
74              FileObject file = (opts == null) ? manager.resolveFile(path.getURI())
75                      : manager.resolveFile(path.getURI(), opts);
76              FileContent content = file.getContent();
77              if (content == null)
78              {
79                  String msg = "Cannot access content of " + file.getName().getFriendlyURI();
80                  throw new ConfigurationException(msg);
81              }
82              return content.getInputStream();
83          }
84          catch (ConfigurationException e)
85          {
86              throw e;
87          }
88          catch (Exception e)
89          {
90              throw new ConfigurationException("Unable to load the configuration file " + fileName, e);
91          }
92      }
93  
94      @Override
95      public InputStream getInputStream(URL url) throws ConfigurationException
96      {
97          FileObject file;
98          try
99          {
100             FileSystemOptions opts = getOptions(url.getProtocol());
101             file = (opts == null) ? VFS.getManager().resolveFile(url.toString())
102                     : VFS.getManager().resolveFile(url.toString(), opts);
103             if (file.getType() != FileType.FILE)
104             {
105                 throw new ConfigurationException("Cannot load a configuration from a directory");
106             }
107             FileContent content = file.getContent();
108             if (content == null)
109             {
110                 String msg = "Cannot access content of " + file.getName().getFriendlyURI();
111                 throw new ConfigurationException(msg);
112             }
113             return content.getInputStream();
114         }
115         catch (FileSystemException fse)
116         {
117             String msg = "Unable to access " + url.toString();
118             throw new ConfigurationException(msg, fse);
119         }
120     }
121 
122     @Override
123     public OutputStream getOutputStream(URL url) throws ConfigurationException
124     {
125         try
126         {
127             FileSystemOptions opts = getOptions(url.getProtocol());
128             FileSystemManager fsManager = VFS.getManager();
129             FileObject file = (opts == null) ? fsManager.resolveFile(url.toString())
130                     : fsManager.resolveFile(url.toString(), opts);
131             // throw an exception if the target URL is a directory
132             if (file == null || file.getType() == FileType.FOLDER)
133             {
134                 throw new ConfigurationException("Cannot save a configuration to a directory");
135             }
136             FileContent content = file.getContent();
137 
138             if (content == null)
139             {
140                 throw new ConfigurationException("Cannot access content of " + url);
141             }
142             return content.getOutputStream();
143         }
144         catch (FileSystemException fse)
145         {
146             throw new ConfigurationException("Unable to access " + url, fse);
147         }
148     }
149 
150     @Override
151     public String getPath(File file, URL url, String basePath, String fileName)
152     {
153         if (file != null)
154         {
155             return super.getPath(file, url, basePath, fileName);
156         }
157         try
158         {
159             FileSystemManager fsManager = VFS.getManager();
160             if (url != null)
161             {
162                 FileName name = fsManager.resolveURI(url.toString());
163                 if (name != null)
164                 {
165                     return name.toString();
166                 }
167             }
168 
169             if (UriParser.extractScheme(fileName) != null)
170             {
171                 return fileName;
172             }
173             else if (basePath != null)
174             {
175                 FileName base = fsManager.resolveURI(basePath);
176                 return fsManager.resolveName(base, fileName).getURI();
177             }
178             else
179             {
180                 FileName name = fsManager.resolveURI(fileName);
181                 FileName base = name.getParent();
182                 return fsManager.resolveName(base, name.getBaseName()).getURI();
183             }
184         }
185         catch (FileSystemException fse)
186         {
187             fse.printStackTrace();
188             return null;
189         }
190     }
191 
192     @Override
193     public String getBasePath(String path)
194     {
195         if (UriParser.extractScheme(path) == null)
196         {
197             return super.getBasePath(path);
198         }
199         try
200         {
201             FileSystemManager fsManager = VFS.getManager();
202             FileName name = fsManager.resolveURI(path);
203             return name.getParent().getURI();
204         }
205         catch (FileSystemException fse)
206         {
207             fse.printStackTrace();
208             return null;
209         }
210     }
211 
212     @Override
213     public String getFileName(String path)
214     {
215         if (UriParser.extractScheme(path) == null)
216         {
217             return super.getFileName(path);
218         }
219         try
220         {
221             FileSystemManager fsManager = VFS.getManager();
222             FileName name = fsManager.resolveURI(path);
223             return name.getBaseName();
224         }
225         catch (FileSystemException fse)
226         {
227             fse.printStackTrace();
228             return null;
229         }
230     }
231 
232     @Override
233     public URL getURL(String basePath, String file) throws MalformedURLException
234     {
235         if ((basePath != null && UriParser.extractScheme(basePath) == null)
236             || (basePath == null && UriParser.extractScheme(file) == null))
237         {
238             return super.getURL(basePath, file);
239         }
240         try
241         {
242             FileSystemManager fsManager = VFS.getManager();
243 
244             FileName path;
245             if (basePath != null && UriParser.extractScheme(file) == null)
246             {
247                 FileName base = fsManager.resolveURI(basePath);
248                 path = fsManager.resolveName(base, file);
249             }
250             else
251             {
252                 path = fsManager.resolveURI(file);
253             }
254 
255             URLStreamHandler handler = new VFSURLStreamHandler(path);
256             return new URL(null, path.getURI(), handler);
257         }
258         catch (FileSystemException fse)
259         {
260             throw new ConfigurationRuntimeException("Could not parse basePath: " + basePath
261                 + " and fileName: " + file, fse);
262         }
263     }
264 
265     @Override
266     public URL locateFromURL(String basePath, String fileName)
267     {
268         String fileScheme = UriParser.extractScheme(fileName);
269 
270         // Use DefaultFileSystem if basePath and fileName don't have a scheme.
271         if ((basePath == null || UriParser.extractScheme(basePath) == null) && fileScheme == null)
272         {
273             return super.locateFromURL(basePath, fileName);
274         }
275         try
276         {
277             FileSystemManager fsManager = VFS.getManager();
278 
279             FileObject file;
280             // Only use the base path if the file name doesn't have a scheme.
281             if (basePath != null && fileScheme == null)
282             {
283                 String scheme = UriParser.extractScheme(basePath);
284                 FileSystemOptions opts = (scheme != null) ? getOptions(scheme) : null;
285                 FileObject base = (opts == null) ? fsManager.resolveFile(basePath)
286                         : fsManager.resolveFile(basePath, opts);
287                 if (base.getType() == FileType.FILE)
288                 {
289                     base = base.getParent();
290                 }
291 
292                 file = fsManager.resolveFile(base, fileName);
293             }
294             else
295             {
296                 FileSystemOptions opts = (fileScheme != null) ? getOptions(fileScheme) : null;
297                 file = (opts == null) ? fsManager.resolveFile(fileName)
298                         : fsManager.resolveFile(fileName, opts);
299             }
300 
301             if (!file.exists())
302             {
303                 return null;
304             }
305             FileName path = file.getName();
306             URLStreamHandler handler = new VFSURLStreamHandler(path);
307             return new URL(null, path.getURI(), handler);
308         }
309         catch (FileSystemException fse)
310         {
311             return null;
312         }
313         catch (MalformedURLException ex)
314         {
315             return null;
316         }
317     }
318 
319     private FileSystemOptions getOptions(String scheme)
320     {
321         FileSystemOptions opts = new FileSystemOptions();
322         FileSystemConfigBuilder builder;
323         try
324         {
325             builder = VFS.getManager().getFileSystemConfigBuilder(scheme);
326         }
327         catch (Exception ex)
328         {
329             return null;
330         }
331         FileOptionsProvider provider = getFileOptionsProvider();
332         if (provider != null)
333         {
334             Map<String, Object> map = provider.getOptions();
335             if (map == null)
336             {
337                 return null;
338             }
339             int count = 0;
340             for (Map.Entry<String, Object> entry : map.entrySet())
341             {
342                 try
343                 {
344                     String key = entry.getKey();
345                     if (FileOptionsProvider.CURRENT_USER.equals(key))
346                     {
347                         key = "creatorName";
348                     }
349                     setProperty(builder, opts, key, entry.getValue());
350                     ++count;
351                 }
352                 catch (Exception ex)
353                 {
354                     // Ignore an incorrect property.
355                     continue;
356                 }
357             }
358             if (count > 0)
359             {
360                 return opts;
361             }
362         }
363         return null;
364 
365     }
366 
367     private void setProperty(FileSystemConfigBuilder builder, FileSystemOptions options,
368                              String key, Object value)
369     {
370         String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
371         Class<?>[] paramTypes = new Class<?>[2];
372         paramTypes[0] = FileSystemOptions.class;
373         paramTypes[1] = value.getClass();
374 
375         try
376         {
377             Method method = builder.getClass().getMethod(methodName, paramTypes);
378             Object[] params = new Object[2];
379             params[0] = options;
380             params[1] = value;
381             method.invoke(builder, params);
382         }
383         catch (Exception ex)
384         {
385             return;
386         }
387 
388     }
389 
390     /**
391      * Stream handler required to create URL.
392      */
393     private static class VFSURLStreamHandler extends URLStreamHandler
394     {
395         /** The Protocol used */
396         private final String protocol;
397 
398         public VFSURLStreamHandler(FileName file)
399         {
400             this.protocol = file.getScheme();
401         }
402 
403         @Override
404         protected URLConnection openConnection(URL url) throws IOException
405         {
406             throw new IOException("VFS URLs can only be used with VFS APIs");
407         }
408     }
409 }