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 java.io.File; 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.io.OutputStream; 023 import java.lang.reflect.Method; 024 import java.net.MalformedURLException; 025 import java.net.URL; 026 import java.net.URLConnection; 027 import java.net.URLStreamHandler; 028 import java.util.Map; 029 030 import org.apache.commons.vfs2.FileContent; 031 import org.apache.commons.vfs2.FileName; 032 import org.apache.commons.vfs2.FileObject; 033 import org.apache.commons.vfs2.FileSystemConfigBuilder; 034 import org.apache.commons.vfs2.FileSystemException; 035 import org.apache.commons.vfs2.FileSystemManager; 036 import org.apache.commons.vfs2.FileSystemOptions; 037 import org.apache.commons.vfs2.FileType; 038 import org.apache.commons.vfs2.VFS; 039 import org.apache.commons.vfs2.provider.UriParser; 040 041 /** 042 * FileSystem that uses Commons VFS 043 * @since 1.7 044 * @author <a 045 * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a> 046 * @version $Id: VFSFileSystem.java 1210205 2011-12-04 20:38:19Z oheger $ 047 */ 048 public class VFSFileSystem extends DefaultFileSystem 049 { 050 public VFSFileSystem() 051 { 052 } 053 054 @Override 055 public InputStream getInputStream(String basePath, String fileName) 056 throws ConfigurationException 057 { 058 try 059 { 060 FileSystemManager manager = VFS.getManager(); 061 FileName path; 062 if (basePath != null) 063 { 064 FileName base = manager.resolveURI(basePath); 065 path = manager.resolveName(base, fileName); 066 } 067 else 068 { 069 FileName file = manager.resolveURI(fileName); 070 FileName base = file.getParent(); 071 path = manager.resolveName(base, file.getBaseName()); 072 } 073 FileSystemOptions opts = getOptions(path.getScheme()); 074 FileObject file = (opts == null) ? manager.resolveFile(path.getURI()) 075 : manager.resolveFile(path.getURI(), opts); 076 FileContent content = file.getContent(); 077 if (content == null) 078 { 079 String msg = "Cannot access content of " + file.getName().getFriendlyURI(); 080 throw new ConfigurationException(msg); 081 } 082 return content.getInputStream(); 083 } 084 catch (ConfigurationException e) 085 { 086 throw e; 087 } 088 catch (Exception e) 089 { 090 throw new ConfigurationException("Unable to load the configuration file " + fileName, e); 091 } 092 } 093 094 @Override 095 public InputStream getInputStream(URL url) throws ConfigurationException 096 { 097 FileObject file; 098 try 099 { 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 }