From 320dee580091d80d78d6ab2aa4064d0dbf2716b8 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Fri, 15 Feb 2008 19:01:11 +0000 Subject: [PATCH] --- .../ws/soap/axiom/AxiomHandler.java | 178 ++++++++++++++++++ .../ws/soap/axiom/AxiomHandlerTest.java | 90 +++++++++ 2 files changed, 268 insertions(+) create mode 100644 core/src/main/java/org/springframework/ws/soap/axiom/AxiomHandler.java create mode 100644 core/src/test/java/org/springframework/ws/soap/axiom/AxiomHandlerTest.java diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomHandler.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomHandler.java new file mode 100644 index 00000000..784f8f8d --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomHandler.java @@ -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 endDocument is called. Used for returing SAXResults 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 { + } +} diff --git a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomHandlerTest.java b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomHandlerTest.java new file mode 100644 index 00000000..bad5a63d --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomHandlerTest.java @@ -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 = "" + "" + + "" + + "content" + + ""; + + private static final String XML_2_EXPECTED = "" + "" + + "" + ""; + + private static final String XML_2_SNIPPET = + "" + ""; + + 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")); + } +} \ No newline at end of file