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 }