[jdom-interest] SaxBuilder.setFeature Bug Report and Fix

Jason Winnebeck gillius at mail.rit.edu
Tue Nov 16 07:22:43 PST 2004


Confirmed to be working in JDOM-b9
Confirmed to be broken in JDOM-1.0 and JDOM nightly 11-16-2004

I recently upgraded from JDOM beta 9 to JDOM 1.0, and some of my parsing 
code broke.  I am using Xerces 2.6 with schema validation for some files, 
and no schema validation for others.  I reuse the same SAXBuilder to build 
the files, but I change features after build.

In JDOM b9, this code works.  Here are select lines of code from the actual 
program.

SAXBuilder builder = new SAXBuilder( "org.apache.xerces.parsers.SAXParser", 
false );
builder.setFeature( "http://apache.org/xml/features/validation/schema", true );

builder.setIgnoringElementContentWhitespace( true );
Document doc = builder.build( new File( "SystemConfigurations.xml" ) );

//Lines omitted that use doc

//Lines omitted that construct the userConfigs strings and check to see
//if file should be loaded
builder.setFeature( "http://apache.org/xml/features/validation/schema", false );
doc = builder.build( userConfigs );

In JDOM 1.0, the schema validation will not be turned off for Xerces, and 
the second document will not build since it cannot find the schema (and 
therefore not the definition for the root element).

Using a debugger and after examining code, I found that 
SAXBuilder.setFeature only sets an entry in a map which is used in 
createParser, which is only called once if reuseParser is true (default).

My first attempt to fix this problem was to add lines to setFeature and 
setProperty that would set the feature or property directly on 
this.saxParser if it was not null -- however the methods cannot throw 
JDOMException and I did not want to change the API.

So what I did was in SAXBuilder.build( InputSource ) I added a call to 
setFeaturesandProperties.

I modified both JDOM 11-16-04 nightly and JDOM 1.0 and the fix worked for 
both.  I decided for our organization it was best to patch 1.0 than patch 
and use the nightly, so the line number is based off of JDOM 1.0.

Insert at line 455:
               //If the user has changed features or properties, they need 
to be reset.
               //In the future we could have a flag to prevent extra work.
               setFeaturesAndProperties( parser, false );

Surrounding old code plus new code, starting at line 451:
             else {
                 // Reset content handler as SAXHandler instances cannot
                 // be reused
                 configureParser(parser, contentHandler);

               //If the user has changed features or properties, they need 
to be reset.
               //In the future we could have a flag to prevent extra work.
               setFeaturesAndProperties( parser, false );
             }

This seems to work for my application, but this is my first time looking at 
JDOM code and I only spent about 15 minutes examining the class before I 
made the change, so I do not know how correct the code is.  The one thing I 
am unsure of is the boolean parameter to setFeaturesAndProperties.  It uses 
true when createParser is called for my application's case, but the false 
seems to only set the user features, which are what I'm changing.

Rationale:
According to the API documentation, I cannot see a restriction that you are 
only allowed to call setFeature and setProperty before the first call to 
build.  Therefore I believe the code changes I proposed here better match 
the API documentation and expected behavior.

Jason Winnebeck


More information about the jdom-interest mailing list