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

VFS 2.0 class loading breaks in OSGi, regression from 1.0

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.0
    • 2.1
    • None

    Description

      Class loading changed between version 1.0 and 2.0 in org.apache.commons.vfs2.impl.StandardFileSystemManager.init()

      This breaks our app server running under OSGi (Equinox) like this:

      org.apache.commons.vfs2.FileSystemException: Could not create a file system manager of class "org.apache.commons.vfs2.impl.StandardFileSystemManager".
          at org.apache.commons.vfs2.VFS.createManager(VFS.java:99)
          at org.apache.commons.vfs2.VFS.getManager(VFS.java:50)
          at com.seagullsw.toolbox.config.ConfigurationDirectory.resolveFileObject(ConfigurationDirectory.java:315)
          at com.seagullsw.toolbox.config.Configuration.resolveFileObject(Configuration.java:135)
      <Snip: ...my app frames...>
          at com.seagullsw.appinterface.server.osgi.JCicsOsgiTestCase.testJcicsOsgiRoundtrip(JCicsOsgiTestCase.java:226)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
          at java.lang.reflect.Method.invoke(Unknown Source)
          at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307)
          at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
          at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
          at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
          at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
          at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
          at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
          at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
          at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)
          at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
          at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
          at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
      Caused by: org.apache.commons.vfs2.FileSystemException: Could not load VFS configuration from "bundleresource://7.fwk545215872:34/org/apache/commons/vfs2/impl/providers.xml".
          at org.apache.commons.vfs2.impl.StandardFileSystemManager.configure(StandardFileSystemManager.java:199)
          at org.apache.commons.vfs2.impl.StandardFileSystemManager.init(StandardFileSystemManager.java:123)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
          at java.lang.reflect.Method.invoke(Unknown Source)
          at org.apache.commons.vfs2.VFS.createManager(VFS.java:88)
          ... 49 more
      Caused by: java.lang.ClassCastException: org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider cannot be cast to org.apache.commons.vfs2.provider.FileProvider
          at org.apache.commons.vfs2.impl.StandardFileSystemManager.addProvider(StandardFileSystemManager.java:371)
          at org.apache.commons.vfs2.impl.StandardFileSystemManager.configure(StandardFileSystemManager.java:270)
          at org.apache.commons.vfs2.impl.StandardFileSystemManager.configure(StandardFileSystemManager.java:195)
          ... 55 more
      

      Which I work around with this hack:

          private void initVfs() {
              StandardFileSystemManager fsm = new StandardFileSystemManager();
              fsm.setClassLoader(fsm.getClass().getClassLoader());
              try {
                  FieldUtils.writeDeclaredStaticField(VFS.class, "instance", fsm, true);
                  fsm.init();
              } catch (FileSystemException e) {
                  ...
              } catch (IllegalAccessException e) {
                  ...
              }
          }
      

      Two questions:

      (1) Why is org.apache.commons.vfs2.VFS.getManager() coded with a class name ref instead of the a real Class object or an actual instance:

          public static synchronized FileSystemManager getManager()
              throws FileSystemException
          {
              if (instance == null)
              {
                  instance = createManager("org.apache.commons.vfs2.impl.StandardFileSystemManager");
              }
              return instance;
          }
      

      Why not:

          public static synchronized FileSystemManager getManager()
              throws FileSystemException
          {
              if (instance == null)
              {
                  instance = new StandardFileSystemManager();
                  // where the StandardFileSystemManager constructor calls init();
              }
              return instance;
          }
      

      If not, what about adding a setManager(FileSystemManager)?

      This did not happen in 1.0, it worked fine in OSGi.

      In 1.0, the init() method is:

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

      In 2.0, the init() method is:

          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);
      
              /* replaced by findClassLoader
              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();
          }
      

      Attachments

        Issue Links

          Activity

            People

              b.eckenfels Bernd Eckenfels
              ggregory Gary D. Gregory
              Votes:
              2 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: