Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
-
None
-
Operating System: Linux
Platform: Other
-
35198
Description
I'm writing an application with an OSGi framework that embeds VFS as a loadable
bundle. In the StandardFileSystem manager a call is made to get the
CONFIG_RESOURCE using getResource() in the classloader. The URL however is
converted to its external form before the call to config. Since it's in the
framework the URL is of the form bundle:// which causes the thing to upchuck
when the DocumentBuilder object tries to parse it. If instead a URL was used and
openStream to get an InputStream called, everything works fine. Below is the
source of the modified version with the configUri as a URL object.
/*
- Copyright 2002-2005 The Apache Software Foundation.
- Licensed 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.vfs.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.VfsLog;
import org.apache.commons.vfs.provider.FileProvider;
import org.apache.commons.vfs.util.Messages;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
- A
{@link org.apache.commons.vfs.FileSystemManager}
that configures itself
- from an XML (Default: providers.xml) configuration file.<br>
- Certain providers are only loaded and available if the dependend library is
in your - classpath. You have to configure your debugging facility to log "debug"
messages to see - if a provider was skipped due to "unresolved externals".
* - @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
- @version $Revision: 170205 $ $Date: 2005-05-15 08:21:59Z $
*/
public class StandardFileSystemManager
extends DefaultFileSystemManager
{
private Log log = LogFactory.getLog(StandardFileSystemManager.class);
private static final String CONFIG_RESOURCE = "providers.xml";
private static final String PLUGIN_CONFIG_RESOURCE =
"META-INF/vfs-providers.xml";
private URL configUri;
private ClassLoader classLoader;
/**
- Sets the configuration file for this manager.
*/
public void setConfiguration(final String configUri)Unknown macro: { try { this.configUri = new URL(configUri); } catch (MalformedURLException e) { log.warn(e.getLocalizedMessage(), e); } }
/**
- Sets the ClassLoader to use to load the providers. Default is to
- use the ClassLoader that loaded this class.
*/
public void setClassLoader(final ClassLoader classLoader) { this.classLoader = classLoader; }
/**
- Initializes this manager. Adds the providers and replicator.
*/
public void init() throws FileSystemException
{
// Set the replicator and temporary file store (use the same component)
final DefaultFileReplicator replicator = createDefaultFileReplicator();
setReplicator(new PrivilegedFileReplicator(replicator));
setTemporaryFileStore(replicator);
if (classLoader == null)
{ // Use default classloader classLoader = getClass().getClassLoader(); } if (configUri == null)
{
// Use default config
final URL url = getClass().getResource(CONFIG_RESOURCE);
if (url == null)
configUri = url;
}
// Configure
configure(configUri);
// Configure Plugins
configurePlugins();
// Initialise super-class
super.init();
}
/**
- Scans the classpath to find any droped plugin.<br />
- The plugin-description has to be in /META-INF/vfs-providers.xml
*/
protected void configurePlugins() throws FileSystemException
{
String classpath = System.getProperty("java.class.path");
if (classpath == null) { // huh? why should that be? return; }
StringTokenizer st = new StringTokenizer(classpath, File.pathSeparator,
false);
while (st.hasMoreTokens())
{
String path = st.nextToken();
if (path.length() > 4 &&
path.substring(path.length()-4).toLowerCase().equals(".jar"))
{
try
{
JarFile jarFile = new JarFile(path);
JarEntry jarEntry = jarFile.getJarEntry(PLUGIN_CONFIG_RESOURCE);
if (jarEntry != null)
{
InputStream configStream = null;
try
finally
{
if (configStream != null)
}
}
}
catch (FileSystemException e)
catch (IOException e)
{ // Maybe a damaged jar? Complain about but continue ... log.warn(e.getLocalizedMessage(), e); } }
else
{
File config = new File(path, PLUGIN_CONFIG_RESOURCE);
if (config.exists() && config.canRead())
{
try
catch (MalformedURLException e)
{ log.warn(e.getLocalizedMessage(), e); } }
}
}
}
protected DefaultFileReplicator createDefaultFileReplicator()
{ return new DefaultFileReplicator(); }/**
- Configures this manager from an XML configuration file.
*/
private void configure(final URL configUri) throws FileSystemExceptionUnknown macro: { try { // Load up the config // TODO - validate final DocumentBuilder builder = createDocumentBuilder(); final Element config = builder.parse(configUri.openStream()).getDocumentElement(); configure(config); } catch (final Exception e) { throw new FileSystemException("vfs.impl/load-config.error", configUri.toString(), e); } }
/**
- Configures this manager from an XML configuration file.
*/
private void configure(final String configUri, final InputStream
configStream) throws FileSystemExceptionUnknown macro: { try { // Load up the config // TODO - validate final DocumentBuilder builder = createDocumentBuilder(); final Element config = builder.parse(configStream).getDocumentElement(); configure(config); } catch (final Exception e) { throw new FileSystemException("vfs.impl/load-config.error", configUri, e); } }
/**
- Configure and create a DocumentBuilder
*/
private DocumentBuilder createDocumentBuilder() throws
ParserConfigurationException { final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringElementContentWhitespace(true); factory.setIgnoringComments(true); factory.setExpandEntityReferences(true); final DocumentBuilder builder = factory.newDocumentBuilder(); return builder; }
/**
- Configures this manager from an parsed XML configuration file
*/
private void configure(final Element config) throws FileSystemException
{
// Add the providers
final NodeList providers = config.getElementsByTagName("provider");
final int count = providers.getLength();
for (int i = 0; i < count; i++) { final Element provider = (Element) providers.item(i); addProvider(provider, false); }
// Add the default provider
final NodeList defProviders =
config.getElementsByTagName("default-provider");
if (defProviders.getLength() > 0)
// Add the mime-type maps
final NodeList mimeTypes = config.getElementsByTagName("mime-type-map");
for (int i = 0; i < mimeTypes.getLength(); i++)
// Add the extension maps
final NodeList extensions = config.getElementsByTagName("extension-map");
for (int i = 0; i < extensions.getLength(); i++)
}
/**
- Adds an extension map.
*/
private void addExtensionMap(final Element map)Unknown macro: { final String extension = map.getAttribute("extension"); final String scheme = map.getAttribute("scheme"); if (scheme != null && scheme.length() > 0) { addExtensionMap(extension, scheme); } }
/**
- Adds a mime-type map.
*/
private void addMimeTypeMap(final Element map) { final String mimeType = map.getAttribute("mime-type"); final String scheme = map.getAttribute("scheme"); addMimeTypeMap(mimeType, scheme); }
/**
- Adds a provider from a provider definition.
*/
private void addProvider(final Element providerDef, final boolean isDefault)
throws FileSystemException
{
final String classname = providerDef.getAttribute("class-name");
// Make sure all required schemes are available
final String[] requiredSchemes = getRequiredSchemes(providerDef);
for (int i = 0; i < requiredSchemes.length; i++)
{
final String requiredScheme = requiredSchemes[i];
if (!hasProvider(requiredScheme))
{
final String msg =
Messages.getString("vfs.impl/skipping-provider-scheme.debug",
new String[]
);
VfsLog.debug(getLogger(), log, msg);
return;
}
}
// Make sure all required classes are in classpath
final String[] requiredClasses = getRequiredClasses(providerDef);
for (int i = 0; i < requiredClasses.length; i++)
{
final String requiredClass = requiredClasses[i];
if (!findClass(requiredClass))
{
final String msg =
Messages.getString("vfs.impl/skipping-provider.debug",
new String[]
);
VfsLog.debug(getLogger(), log, msg);
return;
}
}
// Create and register the provider
final FileProvider provider = createProvider(classname);
final String[] schemas = getSchemas(providerDef);
if (schemas.length > 0)
// Set as default, if required
if (isDefault)
}
/**
- Tests if a class is available.
*/
private boolean findClass(final String className)Unknown macro: { try { classLoader.loadClass(className); return true; } catch (final ClassNotFoundException e) { return false; } }
/**
- Extracts the required classes from a provider definition.
*/
private String[] getRequiredClasses(final Element providerDef)
{
final ArrayList classes = new ArrayList();
final NodeList deps = providerDef.getElementsByTagName("if-available");
final int count = deps.getLength();
for (int i = 0; i < count; i++)Unknown macro: { final Element dep = (Element) deps.item(i); String className = dep.getAttribute("class-name"); if (className != null && className.length() > 0) { classes.add(className); } }return (String[]) classes.toArray(new String[classes.size()]);
}
/**
- Extracts the required schemes from a provider definition.
*/
private String[] getRequiredSchemes(final Element providerDef)
{
final ArrayList schemes = new ArrayList();
final NodeList deps = providerDef.getElementsByTagName("if-available");
final int count = deps.getLength();
for (int i = 0; i < count; i++)Unknown macro: { final Element dep = (Element) deps.item(i); String scheme = dep.getAttribute("scheme"); if (scheme != null && scheme.length() > 0) { schemes.add(scheme); } }return (String[]) schemes.toArray(new String[schemes.size()]);
}
/**
- Extracts the schema names from a provider definition.
*/
private String[] getSchemas(final Element provider)Unknown macro: { final ArrayList schemas = new ArrayList(); final NodeList schemaElements = provider.getElementsByTagName("scheme"); final int count = schemaElements.getLength(); for (int i = 0; i < count; i++) { final Element scheme = (Element) schemaElements.item(i); schemas.add(scheme.getAttribute("name")); } return (String[]) schemas.toArray(new String[schemas.size()]); }
/**
- Creates a provider.
*/
private FileProvider createProvider(final String providerClassName)
throws FileSystemExceptionUnknown macro: { try { final Class providerClass = classLoader.loadClass(providerClassName); return (FileProvider) providerClass.newInstance(); } catch (final Exception e) { throw new FileSystemException("vfs.impl/create-provider.error", providerClassName, e); } }}