Uploaded image for project: 'Commons VFS'
  1. Commons VFS
  2. VFS-24

[VFS] [PATCH] StandardFileSystemManager configure to use classloader URL object

    XMLWordPrintableJSON

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)

      { throw new FileSystemException("vfs.impl/find-config-file.error", CONFIG_RESOURCE); }

      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

      { configStream = jarFile.getInputStream(jarEntry); configure(jarEntry.getName(), configStream); }

      finally
      {
      if (configStream != null)

      { configStream.close(); }

      }
      }
      }
      catch (FileSystemException e)

      { // VFS exception - rethrow // Need to do this as FileSystemException extends IOException throw 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

      { configure(config.toURL()); }

      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 FileSystemException
        Unknown 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 FileSystemException
        Unknown 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)

      { final Element provider = (Element) defProviders.item(0); addProvider(provider, true); }

      // Add the mime-type maps
      final NodeList mimeTypes = config.getElementsByTagName("mime-type-map");
      for (int i = 0; i < mimeTypes.getLength(); i++)

      { final Element map = (Element) mimeTypes.item(i); addMimeTypeMap(map); }

      // Add the extension maps
      final NodeList extensions = config.getElementsByTagName("extension-map");
      for (int i = 0; i < extensions.getLength(); i++)

      { final Element map = (Element) extensions.item(i); addExtensionMap(map); }

      }

      /**

      • 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[]

      {classname, requiredScheme}

      );
      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[]

      {classname, requiredClass}

      );
      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)

      { addProvider(schemas, provider); }

      // Set as default, if required
      if (isDefault)

      { setDefaultProvider(provider); }

      }

      /**

      • 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 FileSystemException
        Unknown 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); } }

        }

      Attachments

        1. ASF.LICENSE.NOT.GRANTED--diff.txt
          3 kB
          Christopher Ottley

        Activity

          People

            Unassigned Unassigned
            xknight@users.sourceforge.net Christopher Ottley
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: