Uploaded image for project: 'Spring Web Services'
  1. Spring Web Services
  2. SWS-265

AbstractStaxXmlReader should support the required standard SAX features (namespace, namespace-prefixes...)

    Details

    • Type: New Feature
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 1.0.3
    • Fix Version/s: 1.5 M2
    • Component/s: XML
    • Labels:
      None
    • Environment:
      Java 5 (build 1.5.0_13-b05-241) with Saxon 6.5.5 / 9.0.0.2 & Axiom 1.2.5

      Description

      XSLT processors (Saxon & Xalan) expect the SAX XMLReader provided by SAXSource implementations such as AbstractStaxXmlReader to support at least the required standard SAX features.
      AbstractStaxXmlReader (through its superclass AbstractXmlReader) throws a SAXNotRecognizedException when trying to read or set any feature.
      This prevents using Saxon as XSLT processor when using the Axiom stack.

      The following patch add support for reading and setting (to their default value only) most SAX default features, making Saxon accept the Axiom StAXSource :

      — ../spring-ws-1.0.3/modules/xml/src/main/java/org/springframework/xml/stream/AbstractStaxXmlReader.java 2007-12-21 16:26:18.000000000 +0100
      +++ AbstractStaxXmlReader.java 2008-01-08 16:10:17.000000000 +0100
      @@ -16,6 +16,9 @@

      package org.springframework.xml.stream;

      +import java.util.Map;
      +import java.util.HashMap;
      +
      import javax.xml.stream.Location;
      import javax.xml.stream.XMLStreamException;

      @@ -24,6 +27,9 @@
      import org.xml.sax.Locator;
      import org.xml.sax.SAXException;
      import org.xml.sax.SAXParseException;
      +import org.xml.sax.SAXNotRecognizedException;
      +import org.xml.sax.SAXNotSupportedException;
      +import org.xml.sax.ext.LexicalHandler;

      import org.springframework.xml.sax.AbstractXmlReader;

      @@ -39,6 +45,40 @@
      */
      public abstract class AbstractStaxXmlReader extends AbstractXmlReader {

      + private final static String[][] DEFAULT_FEATURES = {
      +

      { "http://xml.org/sax/features/validation", "false" }

      ,
      +

      { "http://xml.org/sax/features/namespaces", "true" }

      ,
      +

      { "http://xml.org/sax/features/namespace-prefixes", "false" }

      ,
      +
      +

      { "http://xml.org/sax/features/external-general-entities", "true" }

      ,
      +

      { "http://xml.org/sax/features/external-parameter-entities", "true" }

      ,
      +

      { "http://xml.org/sax/features/lexical-handler/parameter-entities", "false" }

      ,
      +
      +

      { "http://xml.org/sax/features/resolve-dtd-uris", "true" }

      ,
      +

      { "http://xml.org/sax/features/string-interning", "false" }

      ,
      +

      { "http://xml.org/sax/features/unicode-normalization-checking", "false" }

      ,
      +
      +

      { "http://xml.org/sax/features/use-attributes2", "false" }

      ,
      +

      { "http://xml.org/sax/features/use-locator2", "false" }

      ,
      +

      { "http://xml.org/sax/features/use-entity-resolver2", "false" }

      ,
      +

      { "http://xml.org/sax/features/xmlns-uris", "false" }

      ,
      +

      { "http://xml.org/sax/features/xml-1.1", "false" }

      + };
      +
      + private final static Object[][] DEFAULT_PROPERTIES = {
      +

      { "http://xml.org/sax/properties/lexical-handler", null }

      ,
      +

      { "http://xml.org/sax/properties/document-xml-version", "1.0" }

      + };
      +
      + private final Map saxFeatures = new HashMap();
      + private final Map saxProps = new HashMap();
      +
      + public AbstractStaxXmlReader()
      +

      { + this.initSaxFeatures(); + this.initSaxProperties(); + }

      +
      /**

      • Parses the StAX XML reader passed at construction-time.
      • <p/>
        @@ -97,6 +137,102 @@
        /** Template-method that parses the StAX reader passed at construction-time. */
        protected abstract void parseInternal() throws SAXException, XMLStreamException;

      +
      + public void setLexicalHandler(LexicalHandler lexicalHandler)
      + {
      + super.setLexicalHandler(lexicalHandler);
      +
      + try
      +

      { + this.internalSetProperty( + "http://xml.org/sax/properties/lexical-handler", + lexicalHandler); + }

      + catch (SAXException e)

      { /* Ignore... */ }

      + }
      +
      + public boolean getFeature(String name)
      + throws SAXNotRecognizedException, SAXNotSupportedException
      + {
      + if (this.saxFeatures.containsKey(name))
      +

      { + return ((Boolean)(this.saxFeatures.get(name))).booleanValue(); + }

      + else
      +

      { + // Chaning feature values is not supported. + throw new SAXNotRecognizedException(name); + }

      + }
      +
      + public void setFeature(String name, boolean value)
      + throws SAXNotRecognizedException, SAXNotSupportedException
      + {
      + if (value != this.getFeature(name)) // Takes care of unsupp. features
      +

      { + throw new SAXNotSupportedException(name); + }

      + }
      +
      + public Object getProperty(String name)
      + throws SAXNotRecognizedException, SAXNotSupportedException
      + {
      + if (this.saxProps.containsKey(name))
      +

      { + return this.saxProps.get(name); + }

      + else
      +

      { + throw new SAXNotRecognizedException(name); + }

      + }
      +
      + public void setProperty(String name, Object value)
      + throws SAXNotRecognizedException, SAXNotSupportedException
      + {
      + if (("http://xml.org/sax/properties/lexical-handler".equals(name)) &&
      + (value instanceof LexicalHandler))
      +

      { + this.setLexicalHandler((LexicalHandler)value); + }

      + else
      +

      { + this.internalSetProperty(name, value); + }

      + }
      +
      +
      + private void initSaxFeatures()
      + {
      + for (int i=0; i<DEFAULT_FEATURES.length; i++)
      +

      { + this.saxFeatures.put(DEFAULT_FEATURES[i][0], + Boolean.valueOf(DEFAULT_FEATURES[i][1])); + }

      + }
      +
      + private void initSaxProperties()
      + {
      + for (int i=0; i<DEFAULT_PROPERTIES.length; i++)
      +

      { + this.saxProps.put(DEFAULT_PROPERTIES[i][0], + DEFAULT_PROPERTIES[i][1]); + }

      + }
      +
      + public void internalSetProperty(String name, Object value)
      + throws SAXNotRecognizedException, SAXNotSupportedException
      + {
      + Object oldValue = this.getProperty(name);
      + // Takes care of unsupported properties
      + if (((value == null) && (oldValue != null)) ||
      + ((value != null) && (value.equals(oldValue) == false)))
      +

      { + // Chaning property values is not supported. + throw new SAXNotSupportedException(name); + }

      + }
      +
      /**

      • Implementation of the <code>Locator</code> interface that is based on a StAX <code>Location</code>.
        *

        Activity

        Hide
        arjen.poutsma Arjen Poutsma added a comment -

        Added patch as attachment.

        Show
        arjen.poutsma Arjen Poutsma added a comment - Added patch as attachment.
        Hide
        arjen.poutsma Arjen Poutsma added a comment -

        Simply storing and querying these properties and features is not enough, I think. Instead, we should map the properties to the respective properties of the StAX API (exposed via XMLInputFactory), so that they are meaningful.

        For instance, the http://xml.org/sax/features/validation SAX feature maps to the javax.xml.stream.isValidating StAX feature.

        Show
        arjen.poutsma Arjen Poutsma added a comment - Simply storing and querying these properties and features is not enough, I think. Instead, we should map the properties to the respective properties of the StAX API (exposed via XMLInputFactory), so that they are meaningful. For instance, the http://xml.org/sax/features/validation SAX feature maps to the javax.xml.stream.isValidating StAX feature.
        Hide
        arjen.poutsma Arjen Poutsma added a comment -

        Well, it seems like setting the StAX features on an XMLInputFactory does not have the desired effect, so we need to do this differently.

        Show
        arjen.poutsma Arjen Poutsma added a comment - Well, it seems like setting the StAX features on an XMLInputFactory does not have the desired effect, so we need to do this differently.
        Hide
        arjen.poutsma Arjen Poutsma added a comment -

        Fixed, the AbstractStaxXmlReader and subclasses now work under Saxon (tested with version 9.0.0.2).

        Show
        arjen.poutsma Arjen Poutsma added a comment - Fixed, the AbstractStaxXmlReader and subclasses now work under Saxon (tested with version 9.0.0.2).
        Hide
        arjen.poutsma Arjen Poutsma added a comment -

        Reopening issues for 1.0.4

        Show
        arjen.poutsma Arjen Poutsma added a comment - Reopening issues for 1.0.4

          People

          • Assignee:
            arjen.poutsma Arjen Poutsma
            Reporter:
            lbihanic Laurent Bihanic
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: