Commons Configuration
  1. Commons Configuration
  2. CONFIGURATION-65

[configuration] XMLConfiguration cannot load from a jar

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Nightly Builds
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Environment:

      Operating System: other
      Platform: All

      Description

      In the current RC1 codebase, the XMLConfiguration class cannot read an xml
      configuration file packaged in a jar file. The PropertiesConfiguration class
      handles this correctly using an InputStream rather than a File object, but the
      XMLConfiguration does not.

      Here is a patch for XMLConfiguration that lets you put XML files into a jar
      file.

      Index: XMLConfiguration.java
      ===================================================================
      RCS file: /home/cvspublic/jakarta-
      commons/configuration/src/java/org/apache/commons/configuration/XMLConfiguration
      .java,v
      retrieving revision 1.10
      diff -u -r1.10 XMLConfiguration.java
      — XMLConfiguration.java 14 Aug 2004 11:32:06 -0000 1.10
      +++ XMLConfiguration.java 16 Aug 2004 21:55:26 -0000
      @@ -19,6 +19,7 @@
      import java.io.File;
      import java.io.FileWriter;
      import java.io.IOException;
      +import java.io.InputStream;
      import java.io.OutputStream;
      import java.io.OutputStreamWriter;
      import java.io.StringWriter;
      @@ -142,20 +143,20 @@
      }

      public void load() throws ConfigurationException {

      • File file = null;
        + InputStream resource = null;
        try { URL url = ConfigurationUtils.getURL(getBasePath(), getFileName()); - file = new File(url.getFile()); + resource = url.openStream(); DocumentBuilder builder = DocumentBuilderFactory.newInstance ().newDocumentBuilder(); - document = builder.parse(file); + document = builder.parse(resource); }

        catch (IOException de)

        { - throw new ConfigurationException("Could not load from " + file.getAbsolutePath(), de); + throw new ConfigurationException("Could not load from " + getFileName(), de); }

        catch (ParserConfigurationException ex)

        { throw new ConfigurationException("Could not configure parser", ex); }

        catch (FactoryConfigurationError ex)

        { throw new ConfigurationException("Could not create parser", ex); }

        catch (SAXException ex)

        { - throw new ConfigurationException("Error parsing file " + file.getAbsolutePath(), ex); + throw new ConfigurationException("Error parsing file " + getFileName(), ex); }

      initProperties(document.getDocumentElement(), new StringBuffer());

        Activity

        Hide
        Emmanuel Bourg added a comment -

        JC, do you have a test case for this by chance ?

        Show
        Emmanuel Bourg added a comment - JC, do you have a test case for this by chance ?
        Hide
        Emmanuel Bourg added a comment -

        With the patch you suggest the ConfigurationExceptions no longer mention the
        path of the file :/ Also the input stream must be closed in a finally block, I'm
        not sure the parser will close it on its own.

        What error did you get on loading a configuration from a jar initially ?

        Show
        Emmanuel Bourg added a comment - With the patch you suggest the ConfigurationExceptions no longer mention the path of the file :/ Also the input stream must be closed in a finally block, I'm not sure the parser will close it on its own. What error did you get on loading a configuration from a jar initially ?
        Hide
        J.C. Romanda added a comment -

        Created an attachment (id=12499)
        Test case to demonstrate the reported bug

        Show
        J.C. Romanda added a comment - Created an attachment (id=12499) Test case to demonstrate the reported bug
        Hide
        J.C. Romanda added a comment -

        Good point about closing the InputStream.

        The previously attached jar file contains the src, class, and config files to
        reproduce the problem (requires commons configuration and supporting jars). If
        you run the test from the jar file, the ConfigurationFactory will fail caused
        by an underlying FileNotFoundException. The entire stack trace is below. If
        you extract the files from the jar and run the test the ConfigurationFactory
        loads ok.

        I looking into this a little more and tried loading the XMLConfiguration
        directly which fails either way and is also demonstrated in the test. The
        XMLConfiguration fails in the constructor using an InputStream with a
        NullPointerException. Most likely this is because the XMLConfiguration tries
        to treat the InputStream as a File.

        The XMLConfiguration class should probably treat source config files as
        InputStreams like the PropertiesConfiguration class does rather than try to
        convert all InputStreams back to Files like it currently does. My patch
        doesn't completely resolve the issue, it simply demonstrated the fix for my
        issue.

        Here's the stack trace generated by the test class:
        Start test ConfigurationFactory from jar file...
        Aug 20, 2004 1:56:34 PM org.apache.commons.digester.Digester endElement
        SEVERE: End event threw exception
        java.lang.reflect.InvocationTargetException
        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.beanutils.MethodUtils.invokeMethod
        (MethodUtils.java:258)
        at org.apache.commons.digester.CallMethodRule.end
        (CallMethodRule.java:505)
        at org.apache.commons.digester.Rule.end(Rule.java:276)
        at org.apache.commons.digester.Digester.endElement(Digester.java:1058)
        at org.apache.crimson.parser.Parser2.maybeElement(Unknown Source)
        at org.apache.crimson.parser.Parser2.content(Unknown Source)
        at org.apache.crimson.parser.Parser2.maybeElement(Unknown Source)
        at org.apache.crimson.parser.Parser2.parseInternal(Unknown Source)
        at org.apache.crimson.parser.Parser2.parse(Unknown Source)
        at org.apache.crimson.parser.XMLReaderImpl.parse(Unknown Source)
        at org.apache.commons.digester.Digester.parse(Digester.java:1567)
        at
        org.apache.commons.configuration.ConfigurationFactory.getConfiguration
        (ConfigurationFactory.java:158)
        at ConfigurationBug30702.testFactory(ConfigurationBug30702.java:75)
        at ConfigurationBug30702.main(ConfigurationBug30702.java:28)
        Caused by: org.apache.commons.configuration.ConfigurationException: Could not
        load from D:\projects\commons-configuration\file:\D:\projects\commons-
        configuration\commons-configuration-bug30702.jar!\conf\test.xml
        at org.apache.commons.configuration.XMLConfiguration.load
        (XMLConfiguration.java:152)
        ... 18 more
        Caused by: java.io.FileNotFoundException: D:\projects\commons-
        configuration\file:\D:\projects\commons-configuration\commons-configuration-
        bug30702.jar!\conf\test.xml (The filename, directory name, or volume label
        syntax is incorrect)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source)
        at sun.net.www.protocol.file.FileURLConnection.getInputStream(Unknown
        Source)
        at java.net.URL.openStream(Unknown Source)
        at org.apache.crimson.parser.InputEntity.init(Unknown Source)
        at org.apache.crimson.parser.Parser2.parseInternal(Unknown Source)
        at org.apache.crimson.parser.Parser2.parse(Unknown Source)
        at org.apache.crimson.parser.XMLReaderImpl.parse(Unknown Source)
        at org.apache.crimson.jaxp.DocumentBuilderImpl.parse(Unknown Source)
        at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
        at org.apache.commons.configuration.XMLConfiguration.load
        (XMLConfiguration.java:150)
        ... 18 more

        If it's acceptable to rework the XMLConfiguration class to use InputStreams,
        I'll gladly try to do that and submit a complete patch. Just didn't have the
        time to do this previously.

        Show
        J.C. Romanda added a comment - Good point about closing the InputStream. The previously attached jar file contains the src, class, and config files to reproduce the problem (requires commons configuration and supporting jars). If you run the test from the jar file, the ConfigurationFactory will fail caused by an underlying FileNotFoundException. The entire stack trace is below. If you extract the files from the jar and run the test the ConfigurationFactory loads ok. I looking into this a little more and tried loading the XMLConfiguration directly which fails either way and is also demonstrated in the test. The XMLConfiguration fails in the constructor using an InputStream with a NullPointerException. Most likely this is because the XMLConfiguration tries to treat the InputStream as a File. The XMLConfiguration class should probably treat source config files as InputStreams like the PropertiesConfiguration class does rather than try to convert all InputStreams back to Files like it currently does. My patch doesn't completely resolve the issue, it simply demonstrated the fix for my issue. Here's the stack trace generated by the test class: Start test ConfigurationFactory from jar file... Aug 20, 2004 1:56:34 PM org.apache.commons.digester.Digester endElement SEVERE: End event threw exception java.lang.reflect.InvocationTargetException 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.beanutils.MethodUtils.invokeMethod (MethodUtils.java:258) at org.apache.commons.digester.CallMethodRule.end (CallMethodRule.java:505) at org.apache.commons.digester.Rule.end(Rule.java:276) at org.apache.commons.digester.Digester.endElement(Digester.java:1058) at org.apache.crimson.parser.Parser2.maybeElement(Unknown Source) at org.apache.crimson.parser.Parser2.content(Unknown Source) at org.apache.crimson.parser.Parser2.maybeElement(Unknown Source) at org.apache.crimson.parser.Parser2.parseInternal(Unknown Source) at org.apache.crimson.parser.Parser2.parse(Unknown Source) at org.apache.crimson.parser.XMLReaderImpl.parse(Unknown Source) at org.apache.commons.digester.Digester.parse(Digester.java:1567) at org.apache.commons.configuration.ConfigurationFactory.getConfiguration (ConfigurationFactory.java:158) at ConfigurationBug30702.testFactory(ConfigurationBug30702.java:75) at ConfigurationBug30702.main(ConfigurationBug30702.java:28) Caused by: org.apache.commons.configuration.ConfigurationException: Could not load from D:\projects\commons-configuration\ file:\D:\projects\commons- configuration\commons-configuration-bug30702.jar!\conf\test.xml at org.apache.commons.configuration.XMLConfiguration.load (XMLConfiguration.java:152) ... 18 more Caused by: java.io.FileNotFoundException: D:\projects\commons- configuration\ file:\D:\projects\commons-configuration\commons-configuration- bug30702.jar!\conf\test.xml (The filename, directory name, or volume label syntax is incorrect) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source) at sun.net.www.protocol.file.FileURLConnection.getInputStream(Unknown Source) at java.net.URL.openStream(Unknown Source) at org.apache.crimson.parser.InputEntity.init(Unknown Source) at org.apache.crimson.parser.Parser2.parseInternal(Unknown Source) at org.apache.crimson.parser.Parser2.parse(Unknown Source) at org.apache.crimson.parser.XMLReaderImpl.parse(Unknown Source) at org.apache.crimson.jaxp.DocumentBuilderImpl.parse(Unknown Source) at javax.xml.parsers.DocumentBuilder.parse(Unknown Source) at org.apache.commons.configuration.XMLConfiguration.load (XMLConfiguration.java:150) ... 18 more If it's acceptable to rework the XMLConfiguration class to use InputStreams, I'll gladly try to do that and submit a complete patch. Just didn't have the time to do this previously.
        Hide
        David Eric Pugh added a comment -

        Should we mark this as an enhancement? JC, if you can rework it, and provide
        the unit test, then I'd be happy to add it for 1.0. It does seem like a pretty
        common situtation. Otherwise, maybe we should mark it as a 1.1 thing?

        Eric

        Show
        David Eric Pugh added a comment - Should we mark this as an enhancement? JC, if you can rework it, and provide the unit test, then I'd be happy to add it for 1.0. It does seem like a pretty common situtation. Otherwise, maybe we should mark it as a 1.1 thing? Eric
        Hide
        Emmanuel Bourg added a comment -

        Yes this should be addressed for the 1.0 release, as well as unifying the
        loading mechanisms for the other file based configurations.

        Show
        Emmanuel Bourg added a comment - Yes this should be addressed for the 1.0 release, as well as unifying the loading mechanisms for the other file based configurations.
        Hide
        Emmanuel Bourg added a comment -

        Taking the bug, I have a test case and I'm working on a generic solution for all
        file based configurations.

        Show
        Emmanuel Bourg added a comment - Taking the bug, I have a test case and I'm working on a generic solution for all file based configurations.
        Hide
        Emmanuel Bourg added a comment -

        Fixed, let us know how it works for you JC.

        Show
        Emmanuel Bourg added a comment - Fixed, let us know how it works for you JC.
        Hide
        J.C. Romanda added a comment -

        Works like a charm. thanks!!!

        Show
        J.C. Romanda added a comment - Works like a charm. thanks!!!

          People

          • Assignee:
            Unassigned
            Reporter:
            J.C. Romanda
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development