/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.configuration2.io;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Map;

import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemConfigBuilder;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.provider.UriParser;

FileSystem that uses Commons VFS
Since:1.7
/** * FileSystem that uses Commons VFS * @since 1.7 */
public class VFSFileSystem extends DefaultFileSystem {
The logger.
/** The logger. */
private final Log log = LogFactory.getLog(getClass()); public VFSFileSystem() { } @Override public InputStream getInputStream(final URL url) throws ConfigurationException { FileObject file; try { final FileSystemOptions opts = getOptions(url.getProtocol()); file = opts == null ? VFS.getManager().resolveFile(url.toString()) : VFS.getManager().resolveFile(url.toString(), opts); if (file.getType() != FileType.FILE) { throw new ConfigurationException("Cannot load a configuration from a directory"); } final FileContent content = file.getContent(); if (content == null) { final String msg = "Cannot access content of " + file.getName().getFriendlyURI(); throw new ConfigurationException(msg); } return content.getInputStream(); } catch (final FileSystemException fse) { final String msg = "Unable to access " + url.toString(); throw new ConfigurationException(msg, fse); } } @Override public OutputStream getOutputStream(final URL url) throws ConfigurationException { try { final FileSystemOptions opts = getOptions(url.getProtocol()); final FileSystemManager fsManager = VFS.getManager(); final FileObject file = opts == null ? fsManager.resolveFile(url.toString()) : fsManager.resolveFile(url.toString(), opts); // throw an exception if the target URL is a directory if (file == null || file.getType() == FileType.FOLDER) { throw new ConfigurationException("Cannot save a configuration to a directory"); } final FileContent content = file.getContent(); if (content == null) { throw new ConfigurationException("Cannot access content of " + url); } return content.getOutputStream(); } catch (final FileSystemException fse) { throw new ConfigurationException("Unable to access " + url, fse); } } @Override public String getPath(final File file, final URL url, final String basePath, final String fileName) { if (file != null) { return super.getPath(file, url, basePath, fileName); } try { final FileSystemManager fsManager = VFS.getManager(); if (url != null) { final FileName name = fsManager.resolveURI(url.toString()); if (name != null) { return name.toString(); } } if (UriParser.extractScheme(fileName) != null) { return fileName; } else if (basePath != null) { final FileName base = fsManager.resolveURI(basePath); return fsManager.resolveName(base, fileName).getURI(); } else { final FileName name = fsManager.resolveURI(fileName); final FileName base = name.getParent(); return fsManager.resolveName(base, name.getBaseName()).getURI(); } } catch (final FileSystemException fse) { fse.printStackTrace(); return null; } } @Override public String getBasePath(final String path) { if (UriParser.extractScheme(path) == null) { return super.getBasePath(path); } try { final FileSystemManager fsManager = VFS.getManager(); final FileName name = fsManager.resolveURI(path); return name.getParent().getURI(); } catch (final FileSystemException fse) { fse.printStackTrace(); return null; } } @Override public String getFileName(final String path) { if (UriParser.extractScheme(path) == null) { return super.getFileName(path); } try { final FileSystemManager fsManager = VFS.getManager(); final FileName name = fsManager.resolveURI(path); return name.getBaseName(); } catch (final FileSystemException fse) { fse.printStackTrace(); return null; } } @Override public URL getURL(final String basePath, final String file) throws MalformedURLException { if ((basePath != null && UriParser.extractScheme(basePath) == null) || (basePath == null && UriParser.extractScheme(file) == null)) { return super.getURL(basePath, file); } try { final FileSystemManager fsManager = VFS.getManager(); FileName path; if (basePath != null && UriParser.extractScheme(file) == null) { final FileName base = fsManager.resolveURI(basePath); path = fsManager.resolveName(base, file); } else { path = fsManager.resolveURI(file); } final URLStreamHandler handler = new VFSURLStreamHandler(path); return new URL(null, path.getURI(), handler); } catch (final FileSystemException fse) { throw new ConfigurationRuntimeException("Could not parse basePath: " + basePath + " and fileName: " + file, fse); } } @Override public URL locateFromURL(final String basePath, final String fileName) { final String fileScheme = UriParser.extractScheme(fileName); // Use DefaultFileSystem if basePath and fileName don't have a scheme. if ((basePath == null || UriParser.extractScheme(basePath) == null) && fileScheme == null) { return super.locateFromURL(basePath, fileName); } try { final FileSystemManager fsManager = VFS.getManager(); FileObject file; // Only use the base path if the file name doesn't have a scheme. if (basePath != null && fileScheme == null) { final String scheme = UriParser.extractScheme(basePath); final FileSystemOptions opts = scheme != null ? getOptions(scheme) : null; FileObject base = opts == null ? fsManager.resolveFile(basePath) : fsManager.resolveFile(basePath, opts); if (base.getType() == FileType.FILE) { base = base.getParent(); } file = fsManager.resolveFile(base, fileName); } else { final FileSystemOptions opts = fileScheme != null ? getOptions(fileScheme) : null; file = opts == null ? fsManager.resolveFile(fileName) : fsManager.resolveFile(fileName, opts); } if (!file.exists()) { return null; } final FileName path = file.getName(); final URLStreamHandler handler = new VFSURLStreamHandler(path); return new URL(null, path.getURI(), handler); } catch (final FileSystemException fse) { return null; } catch (final MalformedURLException ex) { return null; } } private FileSystemOptions getOptions(final String scheme) { final FileSystemOptions opts = new FileSystemOptions(); FileSystemConfigBuilder builder; try { builder = VFS.getManager().getFileSystemConfigBuilder(scheme); } catch (final Exception ex) { return null; } final FileOptionsProvider provider = getFileOptionsProvider(); if (provider != null) { final Map<String, Object> map = provider.getOptions(); if (map == null) { return null; } int count = 0; for (final Map.Entry<String, Object> entry : map.entrySet()) { try { String key = entry.getKey(); if (FileOptionsProvider.CURRENT_USER.equals(key)) { key = "creatorName"; } setProperty(builder, opts, key, entry.getValue()); ++count; } catch (final Exception ex) { // Ignore an incorrect property. continue; } } if (count > 0) { return opts; } } return null; } private void setProperty(final FileSystemConfigBuilder builder, final FileSystemOptions options, final String key, final Object value) { final String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1); final Class<?>[] paramTypes = new Class<?>[2]; paramTypes[0] = FileSystemOptions.class; paramTypes[1] = value.getClass(); try { final Method method = builder.getClass().getMethod(methodName, paramTypes); final Object[] params = new Object[2]; params[0] = options; params[1] = value; method.invoke(builder, params); } catch (final Exception ex) { log.warn("Cannot access property '" + key + "'! Ignoring.", ex); } }
Stream handler required to create URL.
/** * Stream handler required to create URL. */
private static class VFSURLStreamHandler extends URLStreamHandler {
The Protocol used
/** The Protocol used */
private final String protocol; public VFSURLStreamHandler(final FileName file) { this.protocol = file.getScheme(); } @Override protected URLConnection openConnection(final URL url) throws IOException { throw new IOException("VFS URLs can only be used with VFS APIs"); } } }