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