STAX Utiltiy object W3CDOMStreamReader has errant / incomplete logic for the 
method implementations of getLocalName,  moveToChild, and getText.
-----------------------------------------------------------------------------------------------------------------------------------------------

                 Key: XFIRE-960
                 URL: http://jira.codehaus.org/browse/XFIRE-960
             Project: XFire
          Issue Type: Bug
          Components: Core
    Affects Versions: 1.2.4
         Environment: JDK 1.5.0_09
            Reporter: Scott Seixas
            Assignee: Dan Diephouse


I have created a Web Service whose i/o is an XMLStreamReader object and this 
service is invoked via XFire's MessageBinding implementation.  The service 
converts the XMLStreamReader input into a W3C DOM object via the STAXUtils read 
method, applies business logic to the DOM, and then converts the DOM back to a 
XMLStreamReader object via the STAX Utility object W3CDomStreamReader. 


{code} // pseudo code for MessageBinding XMLStreamReader Service
public XMLStreamReader call (XMLStreamReader body)
{
    Document doc  =  STAXUtils.read( _db, body, true );
    ...................
    // apply business logic to doc
    ..................
    return new W3CDOMStreamReader( doc );
}
{code}

After this service is invoked, the XFire MessageBinding solution copies the 
XMLStreamReader output to an XMLStreamWriter object via the STAXUtils copy 
method before returning the response back to the client.  During this copy, the 
method calls to the W3CDOMStreamReader methods getLocalName, moveToChild, and 
getText are causing errant behavior.

---------------------------------------- getLocalName 
------------------------------------------
In my above logic, if any elements in the DOM document (doc) were created via 
the DOM Level 1 method doc.createElement then that element would return null 
during the copy process when calling the W3CDOMStreamReader method 
getLocalName, which results in a NULL Pointer exception being thrown.  Since a 
MessageBinding solution should not care about the structure of the underlying 
XML payload, the doc.createElement method should not cause the STAXUtils copy 
method to fail for a W3CDOMStreamReader(doc) created XMLStreamReader object. 

To avoid this error and allow the DOM Level 1 approach, the getLocalName method 
implementation needs to be updated to the following:
{code}
private String getLocalName(Attr attr )
{          
   String name= attr.getLocalName();
        
   // if DOM Level 2 approach didn't work, try DOM Level 1 approach.
   if( name == null ) 
      name = attr.getNodeName();
        
   return name;
}
{code}

--------------------------------------- moveToChild 
----------------------------------------- 
In my above logic, if any elements in the DOM document (doc) were added as 
CDATA elements via the doc.createCDATASection API then this element is treated 
simply as a Text element during the STAXUtils copy and not as a CDATA element.  
The root cause for this is that in JDK 1.5 the W3C CDATASection interface 
extends the Text interface.  The moveToChild method which determines the 
content type of an W3CDOMStreamReader(doc) created XMLStreamReader element 
contains conditional logic that checks the instanceof the content input.  The 
existing method implementation checks if the content is an instanceof a Text 
before it checks if it is an instanceof a CDATASection.  Since the CDATASection 
is a type of Text, this method always treats CDATASection content simply as 
Text.  Thus the XMLStreamWriter representation of this XMLStreamReader CDATA 
section is represented simply as text which causes parsing errors due to 
illegal characters in the original CDATA section.  

To avoid CDATA content from being treated as simply Text content during this 
copy process, the W3CDOMStreamReader moveToChild method needs to be updated to 
the following:
{code}
protected int moveToChild(int currentChild)
{
   this.content = getCurrentElement().getChildNodes().item(currentChild);

   if (content instanceof Element)
      return START_ELEMENT;
   // check for CDATASection before checking for Text
   if (content instanceof CDATASection)
      return CDATA;
   else if (content instanceof Text)
      return CHARACTERS;        
   else if (content instanceof Comment)
      return CHARACTERS;
   else if (content instanceof EntityReference)
      return ENTITY_REFERENCE;
        
   throw new IllegalStateException();
} 
{code}
--------------------------------------------- getText 
-------------------------------------------
The getText method is called in the STAXUtils copy method when copying over 
XMLStreamReader Characters and CDATA text.  The getText method in turn calls 
the DOMUtils.getRawContent method.  The getRawContent method implementation in 
DOMUtils treats the input node always as a Text node even though this method is 
ultimately called for both Text nodes and CDATA nodes.  So for CDATA nodes the 
DOMUtils getRawContent method returns null.

To enable CDATA text from being read and copied correctly, the DOMUtils 
getRawContent method needs to be updated to the following:
{code}
public static String getRawContent(Node n)
{
   if (n == null)
      return null;

   Node n1 = DOMUtils.getChild(n, Node.TEXT_NODE);

   // check to see if it is a CDATA node instead of a TEXT node.
   if (n1 == null)
      n1 = DOMUtils.getChild( n, Node.CDATA_SECTION_NODE );
   
   if( n1 == null )
      return null;

   String s1 = n1.getNodeValue();
      return s1.trim();
}
{code}

It may also be required to update the DOMUtils getContent method as well with 
above changes.  However, I did not determine if that is absolutely necessary.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to