Making the StAX-based XML readers and handlers more compliant
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.soap.axiom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
|
||||
import org.apache.axiom.om.OMAttribute;
|
||||
import org.apache.axiom.om.OMContainer;
|
||||
import org.apache.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.OMFactory;
|
||||
import org.apache.axiom.om.OMNamespace;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
|
||||
/**
|
||||
* Specific SAX {@link ContentHandler} and {@link LexicalHandler} that adds the resulting AXIOM OMElement to a specified
|
||||
* parent element when <code>endDocument</code> is called. Used for returing <code>SAXResult</code>s from Axiom
|
||||
* elements.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class AxiomHandler implements ContentHandler, LexicalHandler {
|
||||
|
||||
private final OMFactory factory;
|
||||
|
||||
private final List elements = new ArrayList();
|
||||
|
||||
private Map namespaces = new HashMap();
|
||||
|
||||
private final OMContainer container;
|
||||
|
||||
private int charactersType = XMLStreamConstants.CHARACTERS;
|
||||
|
||||
AxiomHandler(OMContainer container, OMFactory factory) {
|
||||
Assert.notNull(container, "'container' must not be null");
|
||||
Assert.notNull(factory, "'factory' must not be null");
|
||||
this.factory = factory;
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
private OMContainer getParent() {
|
||||
if (!elements.isEmpty()) {
|
||||
return (OMContainer) elements.get(elements.size() - 1);
|
||||
}
|
||||
else {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
namespaces.put(prefix, uri);
|
||||
}
|
||||
|
||||
public void endPrefixMapping(String prefix) throws SAXException {
|
||||
namespaces.remove(prefix);
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
|
||||
OMContainer parent = getParent();
|
||||
OMElement element = factory.createOMElement(localName, null, parent);
|
||||
for (Iterator iterator = namespaces.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
String prefix = (String) entry.getKey();
|
||||
if (prefix.length() == 0) {
|
||||
element.declareDefaultNamespace((String) entry.getValue());
|
||||
}
|
||||
else {
|
||||
element.declareNamespace((String) entry.getValue(), prefix);
|
||||
}
|
||||
}
|
||||
QName qname = QNameUtils.toQName(uri, qName);
|
||||
element.setLocalName(qname.getLocalPart());
|
||||
element.setNamespace(element.findNamespace(qname.getNamespaceURI(), qname.getPrefix()));
|
||||
for (int i = 0; i < atts.getLength(); i++) {
|
||||
QName attrName = QNameUtils.toQName(atts.getURI(i), atts.getQName(i));
|
||||
String value = atts.getValue(i);
|
||||
if (!atts.getQName(i).startsWith("xmlns")) {
|
||||
OMNamespace namespace = factory.createOMNamespace(attrName.getNamespaceURI(), attrName.getPrefix());
|
||||
OMAttribute attribute = factory.createOMAttribute(attrName.getLocalPart(), namespace, value);
|
||||
element.addAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
elements.remove(elements.size() - 1);
|
||||
}
|
||||
|
||||
public void characters(char ch[], int start, int length) throws SAXException {
|
||||
String data = new String(ch, start, length);
|
||||
OMContainer parent = getParent();
|
||||
factory.createOMText(parent, data, charactersType);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
|
||||
charactersType = XMLStreamConstants.SPACE;
|
||||
characters(ch, start, length);
|
||||
charactersType = XMLStreamConstants.CHARACTERS;
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data) throws SAXException {
|
||||
OMContainer parent = getParent();
|
||||
factory.createOMProcessingInstruction(parent, target, data);
|
||||
}
|
||||
|
||||
public void comment(char ch[], int start, int length) throws SAXException {
|
||||
String content = new String(ch, start, length);
|
||||
OMContainer parent = getParent();
|
||||
factory.createOMComment(parent, content);
|
||||
}
|
||||
|
||||
public void startCDATA() throws SAXException {
|
||||
charactersType = XMLStreamConstants.CDATA;
|
||||
}
|
||||
|
||||
public void endCDATA() throws SAXException {
|
||||
charactersType = XMLStreamConstants.CHARACTERS;
|
||||
}
|
||||
|
||||
public void startEntity(String name) throws SAXException {
|
||||
charactersType = XMLStreamConstants.ENTITY_REFERENCE;
|
||||
}
|
||||
|
||||
public void endEntity(String name) throws SAXException {
|
||||
charactersType = XMLStreamConstants.CHARACTERS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unsupported
|
||||
*/
|
||||
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
}
|
||||
|
||||
public void startDocument() throws SAXException {
|
||||
}
|
||||
|
||||
public void endDocument() throws SAXException {
|
||||
}
|
||||
|
||||
public void skippedEntity(String name) throws SAXException {
|
||||
}
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId) throws SAXException {
|
||||
}
|
||||
|
||||
public void endDTD() throws SAXException {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.soap.axiom;
|
||||
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.apache.axiom.om.OMContainer;
|
||||
import org.apache.axiom.om.OMFactory;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Specific TrAX {@link javax.xml.transform.Result} that adds the resulting AXIOM OMElement to a specified parent
|
||||
* element when <code>endDocument</code> is called.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see AxiomHandler
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class AxiomResult extends SAXResult {
|
||||
|
||||
AxiomResult(OMContainer container, OMFactory factory) {
|
||||
AxiomHandler handler = new AxiomHandler(container, factory);
|
||||
super.setHandler(handler);
|
||||
super.setLexicalHandler(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a <code>UnsupportedOperationException</code>.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
public void setHandler(ContentHandler handler) {
|
||||
throw new UnsupportedOperationException("setHandler is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a <code>UnsupportedOperationException</code>.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
public void setLexicalHandler(LexicalHandler handler) {
|
||||
throw new UnsupportedOperationException("setLexicalHandler is not supported");
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import java.util.Iterator;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.apache.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.OMException;
|
||||
@@ -70,7 +69,7 @@ abstract class AxiomSoapBody extends AxiomSoapElement implements SoapBody {
|
||||
|
||||
public Result getPayloadResult() {
|
||||
AxiomUtils.removeContents(getAxiomBody());
|
||||
return new SAXResult(new AxiomContentHandler(getAxiomBody(), getAxiomFactory()));
|
||||
return new AxiomResult(getAxiomBody(), getAxiomFactory());
|
||||
}
|
||||
|
||||
public boolean hasFault() {
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.ws.soap.axiom;
|
||||
import java.util.Iterator;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.apache.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.OMException;
|
||||
@@ -57,7 +56,7 @@ class AxiomSoapFaultDetail extends AxiomSoapElement implements SoapFaultDetail {
|
||||
}
|
||||
|
||||
public Result getResult() {
|
||||
return new SAXResult(new AxiomContentHandler(getAxiomFaultDetail(), getAxiomFactory()));
|
||||
return new AxiomResult(getAxiomFaultDetail(), getAxiomFactory());
|
||||
}
|
||||
|
||||
protected SOAPFaultDetail getAxiomFaultDetail() {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.ws.soap.axiom;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.apache.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.OMException;
|
||||
@@ -39,7 +38,7 @@ class AxiomSoapFaultDetailElement extends AxiomSoapElement implements SoapFaultD
|
||||
|
||||
public Result getResult() {
|
||||
try {
|
||||
return new SAXResult(new AxiomContentHandler(getAxiomElement(), getAxiomFactory()));
|
||||
return new AxiomResult(getAxiomElement(), getAxiomFactory());
|
||||
}
|
||||
catch (OMException ex) {
|
||||
throw new AxiomSoapFaultException(ex);
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.ws.soap.axiom;
|
||||
import java.util.Iterator;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.apache.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.OMException;
|
||||
@@ -46,7 +45,7 @@ abstract class AxiomSoapHeader extends AxiomSoapElement implements SoapHeader {
|
||||
}
|
||||
|
||||
public Result getResult() {
|
||||
return new SAXResult(new AxiomContentHandler(getAxiomHeader(), getAxiomFactory()));
|
||||
return new AxiomResult(getAxiomHeader(), getAxiomFactory());
|
||||
}
|
||||
|
||||
public SoapHeaderElement addHeaderElement(QName name) {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.ws.soap.axiom;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.apache.axiom.om.OMException;
|
||||
import org.apache.axiom.soap.SOAPFactory;
|
||||
@@ -50,7 +49,7 @@ class AxiomSoapHeaderElement extends AxiomSoapElement implements SoapHeaderEleme
|
||||
|
||||
public Result getResult() {
|
||||
try {
|
||||
return new SAXResult(new AxiomContentHandler(getAxiomHeaderBlock(), getAxiomFactory()));
|
||||
return new AxiomResult(getAxiomHeaderBlock(), getAxiomFactory());
|
||||
}
|
||||
catch (OMException ex) {
|
||||
throw new AxiomSoapHeaderException(ex);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.ws.server.endpoint;
|
||||
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
@@ -30,6 +31,8 @@ import org.springframework.ws.context.DefaultMessageContext;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.soap.axiom.AxiomSoapMessage;
|
||||
import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessage;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
|
||||
@@ -82,6 +85,23 @@ public class StaxStreamPayloadEndpointTest extends AbstractMessageEndpointTestCa
|
||||
};
|
||||
}
|
||||
|
||||
public void testSaajResponse() throws Exception {
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
MessageFactory messageFactory = MessageFactory.newInstance();
|
||||
SaajSoapMessage request = new SaajSoapMessage(messageFactory.createMessage());
|
||||
transformer.transform(new StringSource(REQUEST), request.getPayloadResult());
|
||||
SaajSoapMessageFactory soapMessageFactory = new SaajSoapMessageFactory();
|
||||
soapMessageFactory.afterPropertiesSet();
|
||||
MessageContext context = new DefaultMessageContext(request, soapMessageFactory);
|
||||
|
||||
MessageEndpoint endpoint = createResponseEndpoint();
|
||||
endpoint.invoke(context);
|
||||
assertTrue("context has not response", context.hasResponse());
|
||||
StringResult stringResult = new StringResult();
|
||||
transformer.transform(context.getResponse().getPayloadSource(), stringResult);
|
||||
assertXMLEqual(RESPONSE, stringResult.toString());
|
||||
}
|
||||
|
||||
public void testAxiomResponse() throws Exception {
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
SOAPFactory axiomFactory = OMAbstractFactory.getSOAP11Factory();
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.soap.axiom;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.apache.axiom.om.OMAbstractFactory;
|
||||
import org.apache.axiom.om.OMDocument;
|
||||
import org.apache.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.OMFactory;
|
||||
import org.apache.axiom.om.OMNamespace;
|
||||
import org.custommonkey.xmlunit.XMLTestCase;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
public class AxiomHandlerTest extends XMLTestCase {
|
||||
|
||||
private static final String XML_1 = "<?xml version='1.0' encoding='UTF-8'?>" + "<?pi content?>" +
|
||||
"<root xmlns='namespace'>" +
|
||||
"<prefix:child xmlns:prefix='namespace2' xmlns:prefix2='namespace3' prefix2:attr='value'>content</prefix:child>" +
|
||||
"</root>";
|
||||
|
||||
private static final String XML_2_EXPECTED = "<?xml version='1.0' encoding='UTF-8'?>" + "<root xmlns='namespace'>" +
|
||||
"<child xmlns='namespace2' />" + "</root>";
|
||||
|
||||
private static final String XML_2_SNIPPET =
|
||||
"<?xml version='1.0' encoding='UTF-8'?>" + "<child xmlns='namespace2' />";
|
||||
|
||||
private AxiomHandler handler;
|
||||
|
||||
private OMDocument result;
|
||||
|
||||
private XMLReader xmlReader;
|
||||
|
||||
private OMFactory factory;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
factory = OMAbstractFactory.getOMFactory();
|
||||
result = factory.createOMDocument();
|
||||
xmlReader = XMLReaderFactory.createXMLReader();
|
||||
}
|
||||
|
||||
public void testContentHandlerDocumentNamespacePrefixes() throws Exception {
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
|
||||
handler = new AxiomHandler(result, factory);
|
||||
xmlReader.setContentHandler(handler);
|
||||
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
|
||||
xmlReader.parse(new InputSource(new StringReader(XML_1)));
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
result.serialize(bos);
|
||||
assertXMLEqual("Invalid result", XML_1, bos.toString("UTF-8"));
|
||||
}
|
||||
|
||||
public void testContentHandlerDocumentNoNamespacePrefixes() throws Exception {
|
||||
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
|
||||
handler = new AxiomHandler(result, factory);
|
||||
xmlReader.setContentHandler(handler);
|
||||
xmlReader.parse(new InputSource(new StringReader(XML_1)));
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
result.serialize(bos);
|
||||
assertXMLEqual("Invalid result", XML_1, bos.toString("UTF-8"));
|
||||
}
|
||||
|
||||
public void testContentHandlerElement() throws Exception {
|
||||
OMNamespace namespace = factory.createOMNamespace("namespace", "");
|
||||
OMElement rootElement = factory.createOMElement("root", namespace, result);
|
||||
handler = new AxiomHandler(rootElement, factory);
|
||||
xmlReader.setContentHandler(handler);
|
||||
xmlReader.parse(new InputSource(new StringReader(XML_2_SNIPPET)));
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
result.serialize(bos);
|
||||
assertXMLEqual("Invalid result", XML_2_EXPECTED, bos.toString("UTF-8"));
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,11 @@ import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.Characters;
|
||||
import javax.xml.stream.events.Comment;
|
||||
import javax.xml.stream.events.DTD;
|
||||
import javax.xml.stream.events.EndElement;
|
||||
import javax.xml.stream.events.EntityDeclaration;
|
||||
import javax.xml.stream.events.EntityReference;
|
||||
import javax.xml.stream.events.Namespace;
|
||||
import javax.xml.stream.events.NotationDeclaration;
|
||||
import javax.xml.stream.events.ProcessingInstruction;
|
||||
@@ -120,6 +123,15 @@ public class StaxEventXmlReader extends AbstractStaxXmlReader {
|
||||
case XMLStreamConstants.ENTITY_DECLARATION:
|
||||
handleEntityDeclaration((EntityDeclaration) event);
|
||||
break;
|
||||
case XMLStreamConstants.COMMENT:
|
||||
handleComment((Comment) event);
|
||||
break;
|
||||
case XMLStreamConstants.DTD:
|
||||
handleDtd((DTD) event);
|
||||
break;
|
||||
case XMLStreamConstants.ENTITY_REFERENCE:
|
||||
handleEntityReference((EntityReference) event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!documentEnded) {
|
||||
@@ -128,24 +140,41 @@ public class StaxEventXmlReader extends AbstractStaxXmlReader {
|
||||
|
||||
}
|
||||
|
||||
private void handleCharacters(Characters characters) throws SAXException {
|
||||
private void handleStartElement(StartElement startElement) throws SAXException {
|
||||
if (getContentHandler() != null) {
|
||||
if (characters.isIgnorableWhiteSpace()) {
|
||||
getContentHandler()
|
||||
.ignorableWhitespace(characters.getData().toCharArray(), 0, characters.getData().length());
|
||||
QName qName = startElement.getName();
|
||||
if (hasNamespacesFeature()) {
|
||||
for (Iterator i = startElement.getNamespaces(); i.hasNext();) {
|
||||
Namespace namespace = (Namespace) i.next();
|
||||
getContentHandler().startPrefixMapping(namespace.getPrefix(), namespace.getNamespaceURI());
|
||||
}
|
||||
getContentHandler().startElement(qName.getNamespaceURI(), qName.getLocalPart(),
|
||||
QNameUtils.toQualifiedName(qName), getAttributes(startElement));
|
||||
}
|
||||
else {
|
||||
if (characters.isCData() && getLexicalHandler() != null) {
|
||||
getLexicalHandler().startCDATA();
|
||||
}
|
||||
getContentHandler().characters(characters.getData().toCharArray(), 0, characters.getData().length());
|
||||
if (characters.isCData() && getLexicalHandler() != null) {
|
||||
getLexicalHandler().endCDATA();
|
||||
}
|
||||
getContentHandler()
|
||||
.startElement("", "", QNameUtils.toQualifiedName(qName), getAttributes(startElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCharacters(Characters characters) throws SAXException {
|
||||
char[] data = characters.getData().toCharArray();
|
||||
if (getContentHandler() != null && characters.isIgnorableWhiteSpace()) {
|
||||
getContentHandler().ignorableWhitespace(data, 0, data.length);
|
||||
return;
|
||||
}
|
||||
if (characters.isCData() && getLexicalHandler() != null) {
|
||||
getLexicalHandler().startCDATA();
|
||||
}
|
||||
if (getContentHandler() != null) {
|
||||
getContentHandler().characters(data, 0, data.length);
|
||||
}
|
||||
if (characters.isCData() && getLexicalHandler() != null) {
|
||||
getLexicalHandler().endCDATA();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEndDocument() throws SAXException {
|
||||
if (getContentHandler() != null) {
|
||||
getContentHandler().endDocument();
|
||||
@@ -195,24 +224,34 @@ public class StaxEventXmlReader extends AbstractStaxXmlReader {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStartElement(StartElement startElement) throws SAXException {
|
||||
if (getContentHandler() != null) {
|
||||
QName qName = startElement.getName();
|
||||
if (hasNamespacesFeature()) {
|
||||
for (Iterator i = startElement.getNamespaces(); i.hasNext();) {
|
||||
Namespace namespace = (Namespace) i.next();
|
||||
getContentHandler().startPrefixMapping(namespace.getPrefix(), namespace.getNamespaceURI());
|
||||
}
|
||||
getContentHandler().startElement(qName.getNamespaceURI(), qName.getLocalPart(),
|
||||
QNameUtils.toQualifiedName(qName), getAttributes(startElement));
|
||||
}
|
||||
else {
|
||||
getContentHandler()
|
||||
.startElement("", "", QNameUtils.toQualifiedName(qName), getAttributes(startElement));
|
||||
}
|
||||
private void handleComment(Comment comment) throws SAXException {
|
||||
if (getLexicalHandler() != null) {
|
||||
char[] ch = comment.getText().toCharArray();
|
||||
getLexicalHandler().comment(ch, 0, ch.length);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDtd(DTD dtd) throws SAXException {
|
||||
if (getLexicalHandler() != null) {
|
||||
javax.xml.stream.Location location = dtd.getLocation();
|
||||
getLexicalHandler().startDTD(null, location.getPublicId(), location.getSystemId());
|
||||
}
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().endDTD();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleEntityReference(EntityReference reference) throws SAXException {
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().startEntity(reference.getName());
|
||||
}
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().endEntity(reference.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Attributes getAttributes(StartElement event) {
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
|
||||
@@ -249,5 +288,4 @@ public class StaxEventXmlReader extends AbstractStaxXmlReader {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -99,6 +99,15 @@ public class StaxStreamXmlReader extends AbstractStaxXmlReader {
|
||||
handleEndDocument();
|
||||
documentEnded = true;
|
||||
break;
|
||||
case XMLStreamConstants.COMMENT:
|
||||
handleComment();
|
||||
break;
|
||||
case XMLStreamConstants.DTD:
|
||||
handleDtd();
|
||||
break;
|
||||
case XMLStreamConstants.ENTITY_REFERENCE:
|
||||
handleEntityReference();
|
||||
break;
|
||||
}
|
||||
if (reader.hasNext() && elementDepth >= 0) {
|
||||
eventType = reader.next();
|
||||
@@ -110,7 +119,6 @@ public class StaxStreamXmlReader extends AbstractStaxXmlReader {
|
||||
if (!documentEnded) {
|
||||
handleEndDocument();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleStartDocument() throws SAXException {
|
||||
@@ -163,15 +171,45 @@ public class StaxStreamXmlReader extends AbstractStaxXmlReader {
|
||||
}
|
||||
|
||||
private void handleCharacters() throws SAXException {
|
||||
if (getContentHandler() != null && reader.isWhiteSpace()) {
|
||||
getContentHandler()
|
||||
.ignorableWhitespace(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
|
||||
return;
|
||||
}
|
||||
if (XMLStreamConstants.CDATA == reader.getEventType() && getLexicalHandler() != null) {
|
||||
getLexicalHandler().startCDATA();
|
||||
}
|
||||
if (getContentHandler() != null) {
|
||||
if (reader.isWhiteSpace()) {
|
||||
getContentHandler()
|
||||
.ignorableWhitespace(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
|
||||
}
|
||||
else {
|
||||
getContentHandler()
|
||||
.characters(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
|
||||
}
|
||||
getContentHandler()
|
||||
.characters(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
|
||||
}
|
||||
if (XMLStreamConstants.CDATA == reader.getEventType() && getLexicalHandler() != null) {
|
||||
getLexicalHandler().endCDATA();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleComment() throws SAXException {
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().comment(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDtd() throws SAXException {
|
||||
if (getLexicalHandler() != null) {
|
||||
javax.xml.stream.Location location = reader.getLocation();
|
||||
getLexicalHandler().startDTD(null, location.getPublicId(), location.getSystemId());
|
||||
}
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().endDTD();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEntityReference() throws SAXException {
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().startEntity(reader.getLocalName());
|
||||
}
|
||||
if (getLexicalHandler() != null) {
|
||||
getLexicalHandler().endEntity(reader.getLocalName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
@@ -40,7 +41,7 @@ import org.springframework.xml.sax.SaxUtils;
|
||||
|
||||
public abstract class AbstractStaxXmlReaderTestCase extends TestCase {
|
||||
|
||||
protected static XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
protected static XMLInputFactory inputFactory;
|
||||
|
||||
private Resource testContentHandler;
|
||||
|
||||
@@ -51,6 +52,7 @@ public abstract class AbstractStaxXmlReaderTestCase extends TestCase {
|
||||
private ContentHandler contentHandler;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
inputFactory = XMLInputFactory.newInstance();
|
||||
standardReader = XMLReaderFactory.createXMLReader();
|
||||
contentHandlerControl = MockControl.createStrictControl(ContentHandler.class);
|
||||
contentHandlerControl.setDefaultMatcher(new SaxArgumentMatcher());
|
||||
@@ -109,6 +111,32 @@ public abstract class AbstractStaxXmlReaderTestCase extends TestCase {
|
||||
contentHandlerControl.verify();
|
||||
}
|
||||
|
||||
public void testLexicalHandler() throws SAXException, IOException, XMLStreamException {
|
||||
|
||||
MockControl lexicalHandlerControl = MockControl.createStrictControl(LexicalHandler.class);
|
||||
lexicalHandlerControl.setDefaultMatcher(new SaxArgumentMatcher());
|
||||
LexicalHandler lexicalHandlerMock = (LexicalHandler) lexicalHandlerControl.getMock();
|
||||
LexicalHandler lexicalHandler = new CopyingLexicalHandler(lexicalHandlerMock);
|
||||
|
||||
Resource testLexicalHandlerXml = new ClassPathResource("testLexicalHandler.xml", getClass());
|
||||
|
||||
standardReader.setContentHandler(null);
|
||||
standardReader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler);
|
||||
standardReader.parse(SaxUtils.createInputSource(testLexicalHandlerXml));
|
||||
lexicalHandlerControl.replay();
|
||||
|
||||
inputFactory.setProperty("javax.xml.stream.isCoalescing", Boolean.FALSE);
|
||||
inputFactory.setProperty("http://java.sun.com/xml/stream/properties/report-cdata-event", Boolean.TRUE);
|
||||
inputFactory.setProperty("javax.xml.stream.isReplacingEntityReferences", Boolean.FALSE);
|
||||
inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.FALSE);
|
||||
|
||||
AbstractStaxXmlReader staxXmlReader = createStaxXmlReader(testLexicalHandlerXml.getInputStream());
|
||||
|
||||
staxXmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler);
|
||||
staxXmlReader.parse(new InputSource());
|
||||
lexicalHandlerControl.verify();
|
||||
}
|
||||
|
||||
protected abstract AbstractStaxXmlReader createStaxXmlReader(InputStream inputStream) throws XMLStreamException;
|
||||
|
||||
/** Easymock <code>ArgumentMatcher</code> implementation that matches SAX arguments. */
|
||||
@@ -156,7 +184,6 @@ public abstract class AbstractStaxXmlReaderTestCase extends TestCase {
|
||||
for (int j = 0; j < actualAttributes.getLength(); j++) {
|
||||
if (expectedAttributes.getURI(i).equals(actualAttributes.getURI(j)) &&
|
||||
expectedAttributes.getQName(i).equals(actualAttributes.getQName(j)) &&
|
||||
// expectedAttributes.getLocalName(i).equals(actualAttributes.getLocalName(j)) &&
|
||||
expectedAttributes.getType(i).equals(actualAttributes.getType(j)) &&
|
||||
expectedAttributes.getValue(i).equals(actualAttributes.getValue(j))) {
|
||||
found = true;
|
||||
@@ -237,7 +264,7 @@ public abstract class AbstractStaxXmlReaderTestCase extends TestCase {
|
||||
|
||||
private static class CopyingContentHandler implements ContentHandler {
|
||||
|
||||
private ContentHandler wrappee;
|
||||
private final ContentHandler wrappee;
|
||||
|
||||
private CopyingContentHandler(ContentHandler wrappee) {
|
||||
this.wrappee = wrappee;
|
||||
@@ -286,7 +313,43 @@ public abstract class AbstractStaxXmlReaderTestCase extends TestCase {
|
||||
public void skippedEntity(String name) throws SAXException {
|
||||
wrappee.skippedEntity(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CopyingLexicalHandler implements LexicalHandler {
|
||||
|
||||
private final LexicalHandler wrappee;
|
||||
|
||||
private CopyingLexicalHandler(LexicalHandler wrappee) {
|
||||
this.wrappee = wrappee;
|
||||
}
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId) throws SAXException {
|
||||
wrappee.startDTD("element", publicId, systemId);
|
||||
}
|
||||
|
||||
public void endDTD() throws SAXException {
|
||||
wrappee.endDTD();
|
||||
}
|
||||
|
||||
public void startEntity(String name) throws SAXException {
|
||||
wrappee.startEntity(name);
|
||||
}
|
||||
|
||||
public void endEntity(String name) throws SAXException {
|
||||
wrappee.endEntity(name);
|
||||
}
|
||||
|
||||
public void startCDATA() throws SAXException {
|
||||
wrappee.startCDATA();
|
||||
}
|
||||
|
||||
public void endCDATA() throws SAXException {
|
||||
wrappee.endCDATA();
|
||||
}
|
||||
|
||||
public void comment(char ch[], int start, int length) throws SAXException {
|
||||
wrappee.comment(copy(ch), start, length);
|
||||
}
|
||||
}
|
||||
|
||||
private static char[] copy(char[] ch) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE element
|
||||
[<!ENTITY entity "entity">]>
|
||||
<!--Comment-->
|
||||
<element>
|
||||
<cdata><![CDATA[cdata]]></cdata>
|
||||
<entity>&entity;</entity>
|
||||
</element>
|
||||
Reference in New Issue
Block a user