From 4a112c85a8cead5e6efc6d13e1eff267c3494740 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 18 Oct 2006 18:55:27 +0000 Subject: [PATCH] Refactored SAAJ support to use Bridge pattern. --- .../springframework/ws/soap/SoapHeader.java | 9 -- .../saaj/Saaj11ImplementationStrategy.java | 121 ++++++++++++++++++ .../saaj/Saaj12ImplementationStrategy.java | 57 +++++++++ .../saaj/Saaj13ImplementationStrategy.java | 56 ++++++++ .../soap/saaj/SaajImplementationStrategy.java | 62 +++++++++ .../ws/soap/saaj/SaajSoap11Body.java | 87 +++++++++++++ .../ws/soap/saaj/SaajSoap11Fault.java | 37 ++++++ .../ws/soap/saaj/SaajSoap12Body.java | 36 ++++++ .../ws/soap/saaj/SaajSoap12Fault.java | 90 +++++++++++++ .../ws/soap/saaj/SaajSoapBody.java | 71 ++++++++++ .../ws/soap/saaj/SaajSoapElement.java | 54 ++++++++ .../ws/soap/saaj/SaajSoapFault.java | 70 ++++++++++ .../ws/soap/saaj/SaajSoapFaultDetail.java | 81 ++++++++++++ .../soap/saaj/SaajSoapFaultDetailElement.java | 50 ++++++++ .../ws/soap/saaj/SaajSoapHeader.java | 75 +++++++++++ .../ws/soap/saaj/SaajSoapHeaderElement.java | 54 ++++++++ .../ws/soap/saaj/support/SaajUtils.java | 31 ++++- .../support/SoapElementContentHandler.java | 92 +++++++++++++ .../saaj/support/SoapElementXmlReader.java | 112 ++++++++++++++++ .../ws/soap/AbstractSoapHeaderTestCase.java | 20 --- .../Saaj11ImplementationStrategyTest.java | 114 +++++++++++++++++ .../ws/soap/saaj/support/SaajUtilsTest.java | 14 +- .../SoapElementContentHandlerTest.java | 41 ++++++ .../support/SoapElementXmlReaderTest.java | 71 ++++++++++ 24 files changed, 1468 insertions(+), 37 deletions(-) create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategy.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/Saaj12ImplementationStrategy.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/Saaj13ImplementationStrategy.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementationStrategy.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapElement.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetail.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeader.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeaderElement.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandler.java create mode 100644 core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReader.java create mode 100644 core/src/test/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategyTest.java create mode 100644 core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandlerTest.java create mode 100644 core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReaderTest.java diff --git a/core/src/main/java/org/springframework/ws/soap/SoapHeader.java b/core/src/main/java/org/springframework/ws/soap/SoapHeader.java index 6a9e3a63..65da2130 100644 --- a/core/src/main/java/org/springframework/ws/soap/SoapHeader.java +++ b/core/src/main/java/org/springframework/ws/soap/SoapHeader.java @@ -49,13 +49,4 @@ public interface SoapHeader extends SoapElement { * @see SoapHeaderElement */ Iterator examineMustUnderstandHeaderElements(String actorOrRole) throws SoapHeaderException; - - /** - * Returns an Iterator over all the SoapHeaderElements in this header. - * - * @return an iterator over all the header elements - * @throws SoapHeaderException if the header cannot be returned - * @see SoapHeaderElement - */ - Iterator examineAllHeaderElements() throws SoapHeaderException; } diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategy.java b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategy.java new file mode 100644 index 00000000..edc489fc --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategy.java @@ -0,0 +1,121 @@ +/* + * 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.saaj; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.DetailEntry; +import javax.xml.soap.Name; +import javax.xml.soap.Node; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; +import javax.xml.soap.SOAPHeader; +import javax.xml.soap.SOAPHeaderElement; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXSource; + +import org.springframework.ws.soap.saaj.support.SaajUtils; +import org.springframework.ws.soap.saaj.support.SoapElementContentHandler; +import org.springframework.ws.soap.saaj.support.SoapElementXmlReader; +import org.springframework.xml.namespace.QNameUtils; +import org.xml.sax.InputSource; + +/** + * SAAJ 1.1 implementation of the SaajImplementationStrategy. + * + * @author Arjen Poutsma + */ +public class Saaj11ImplementationStrategy implements SaajImplementationStrategy { + + public QName getName(SOAPElement element) { + return SaajUtils.toQName(element.getElementName()); + } + + public Source getSource(SOAPElement element) { + return new SAXSource(new SoapElementXmlReader(element), new InputSource()); + } + + public Result getResult(SOAPElement element) { + return new SAXResult(new SoapElementContentHandler(element)); + } + + public QName getFaultCode(SOAPFault fault) { + String code = fault.getFaultCode(); + int idx = code.indexOf(':'); + if (idx == -1) { + return new QName(code); + } + else { + String prefix = code.substring(0, idx); + String localPart = code.substring(idx + 1); + String namespace = fault.getNamespaceURI(prefix); + return QNameUtils.createQName(namespace, localPart, prefix); + } + } + + public DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException { + return detail.addDetailEntry(SaajUtils.toName(name, detail)); + } + + public void removeContents(SOAPElement element) { + List children = new ArrayList(); + for (Iterator iterator = element.getChildElements(); iterator.hasNext();) { + Node node = (Node) iterator.next(); + children.add(node); + } + for (Iterator iterator = children.iterator(); iterator.hasNext();) { + Node node = (Node) iterator.next(); + node.detachNode(); + } + } + + public SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException { + Name saajName = SaajUtils.toName(name, header); + return header.addHeaderElement(saajName); + } + + public Locale getFaultStringLocale(SOAPFault saajFault) { + return null; + } + + public SOAPFault addFault(SOAPBody saajBody, QName faultCode, String faultString, Locale faultStringLocale) throws SOAPException { + SOAPFault fault = saajBody.addFault(); + String faultCodeQName = QNameUtils.toQualifiedName(faultCode); + fault.setFaultCode(faultCodeQName); + fault.setFaultString(faultString); + return fault; + } + + public Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String role) { + List result = new ArrayList(); + for (Iterator iterator = header.examineHeaderElements(role); iterator.hasNext();) { + SOAPHeaderElement headerElement = (SOAPHeaderElement) iterator.next(); + if (headerElement.getMustUnderstand()) { + result.add(headerElement); + } + } + return result.iterator(); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12ImplementationStrategy.java b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12ImplementationStrategy.java new file mode 100644 index 00000000..d83bf08a --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12ImplementationStrategy.java @@ -0,0 +1,57 @@ +/* + * 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.saaj; + +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.DetailEntry; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; + +import org.springframework.ws.soap.saaj.support.SaajUtils; + +class Saaj12ImplementationStrategy extends SaajImplementationStrategy { + + public Source getSource(SOAPElement element) { + return new DOMSource(element); + } + + public Result getResult(SOAPElement element) { + return new DOMResult(element); + } + + public QName getName(SOAPElement element) { + return SaajUtils.toQName(element.getElementName()); + } + + public QName getFaultCode(SOAPFault fault) { + return SaajUtils.toQName(fault.getFaultCodeAsName()); + } + + public DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException { + return detail.addDetailEntry(SaajUtils.toName(name, detail)); + } + + public void removeContents(SOAPElement element) { + element.removeContents(); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13ImplementationStrategy.java b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13ImplementationStrategy.java new file mode 100644 index 00000000..478aa24c --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13ImplementationStrategy.java @@ -0,0 +1,56 @@ +/* + * 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.saaj; + +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.DetailEntry; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; + +class Saaj13ImplementationStrategy extends SaajImplementationStrategy { + + public QName getName(SOAPElement element) { + return element.getElementQName(); + } + + public Source getSource(SOAPElement element) { + return new DOMSource(element); + } + + public Result getResult(SOAPElement element) { + return new DOMResult(element); + } + + public QName getFaultCode(SOAPFault fault) { + return fault.getFaultCodeAsQName(); + } + + public DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException { + return detail.addDetailEntry(name); + } + + public void removeContents(SOAPElement element) { + element.removeContents(); + } + +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementationStrategy.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementationStrategy.java new file mode 100644 index 00000000..16f198f6 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementationStrategy.java @@ -0,0 +1,62 @@ +/* + * 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.saaj; + +import java.util.Iterator; +import java.util.Locale; +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.DetailEntry; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; +import javax.xml.soap.SOAPHeader; +import javax.xml.soap.SOAPHeaderElement; +import javax.xml.transform.Result; +import javax.xml.transform.Source; + +/** + * Defines the contract for different implementation versions of SAAJ. + *

+ * This is pulled out into an interface as the various versions of SAAJ have different contracts with regard to naming, + * etc. + * + * @author Arjen Poutsma + */ +public interface SaajImplementationStrategy { + + public QName getName(SOAPElement element); + + public Source getSource(SOAPElement element); + + public Result getResult(SOAPElement element); + + public QName getFaultCode(SOAPFault fault); + + public DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException; + + public void removeContents(SOAPElement element); + + public SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException; + + public Locale getFaultStringLocale(SOAPFault saajFault); + + public Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String role); + + SOAPFault addFault(SOAPBody saajBody, QName faultCode, String faultString, Locale faultStringLocale) throws SOAPException; +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java new file mode 100644 index 00000000..c18f4e17 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Body.java @@ -0,0 +1,87 @@ +/* + * 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.saaj; + +import java.util.Locale; +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.ws.soap.SoapFault; +import org.springframework.ws.soap.soap11.Soap11Body; +import org.springframework.ws.soap.soap11.Soap11Fault; +import org.springframework.xml.namespace.QNameUtils; + +class SaajSoap11Body extends SaajSoapBody implements Soap11Body { + + private static final String CLIENT = "Client"; + + private static final String MUST_UNDERSTAND = "MustUnderstand"; + + private static final String SERVER = "Server"; + + private static final String VERSION_MISMATCH = "VersionMismatch"; + + public SaajSoap11Body(SOAPBody body, SaajImplementationStrategy strategy) { + super(body, strategy); + } + + public Soap11Fault addFault(QName faultCode, String faultString, Locale faultStringLocale) { + Assert.notNull(faultCode, "No faultCode given"); + Assert.hasLength(faultString, "faultString cannot be empty"); + if (!StringUtils.hasLength(faultCode.getNamespaceURI())) { + throw new IllegalArgumentException( + "A fault code with namespace and local part must be specific for a custom fault code"); + } + try { + getStrategy().removeContents(getSaajBody()); + SOAPFault saajFault = getStrategy().addFault(getSaajBody(), faultCode, faultString, faultStringLocale); + return new SaajSoap11Fault(saajFault, getStrategy()); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public SoapFault getFault() { + SOAPFault fault = getSaajBody().getFault(); + return fault == null ? null : new SaajSoap11Fault(fault, getStrategy()); + } + + public SoapFault addClientOrSenderFault(String faultString, Locale locale) { + return addFault(getStandardFaultCodeQName(CLIENT), faultString, locale); + } + + public SoapFault addMustUnderstandFault(String faultString, Locale locale) { + return addFault(getStandardFaultCodeQName(MUST_UNDERSTAND), faultString, locale); + } + + public SoapFault addServerOrReceiverFault(String faultString, Locale locale) { + return addFault(getStandardFaultCodeQName(SERVER), faultString, locale); + } + + public SoapFault addVersionMismatchFault(String faultString, Locale locale) { + return addFault(getStandardFaultCodeQName(VERSION_MISMATCH), faultString, locale); + } + + private QName getStandardFaultCodeQName(String localName) { + return QNameUtils.createQName(getSaajBody().getElementName().getURI(), localName, getSaajBody().getElementName().getPrefix()); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java new file mode 100644 index 00000000..fc910d97 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap11Fault.java @@ -0,0 +1,37 @@ +/* + * 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.saaj; + +import java.util.Locale; +import javax.xml.soap.SOAPFault; + +import org.springframework.ws.soap.soap11.Soap11Fault; + +class SaajSoap11Fault extends SaajSoapFault implements Soap11Fault { + + public SaajSoap11Fault(SOAPFault fault, SaajImplementationStrategy strategy) { + super(fault, strategy); + } + + public String getFaultString() { + return getSaajFault().getFaultString(); + } + + public Locale getFaultStringLocale() { + return getStrategy().getFaultStringLocale(getSaajFault()); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java new file mode 100644 index 00000000..1337495d --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Body.java @@ -0,0 +1,36 @@ +/* + * 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.saaj; + +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPFault; + +import org.springframework.ws.soap.SoapFault; +import org.springframework.ws.soap.soap12.Soap12Body; + +class SaajSoap12Body extends SaajSoapBody implements Soap12Body { + + public SaajSoap12Body(SOAPBody body) { + super(body); + } + + public SoapFault getFault() { + SOAPFault fault = getSaajBody().getFault(); + return fault == null ? null : new SaajSoap12Fault(fault); + } + +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.java new file mode 100644 index 00000000..5ce68c87 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoap12Fault.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.saaj; + +import java.util.Iterator; +import java.util.Locale; +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; + +import org.springframework.ws.soap.soap12.Soap12Fault; + +class SaajSoap12Fault extends SaajSoapFault implements Soap12Fault { + + public SaajSoap12Fault(SOAPFault saajFault) { + super(saajFault); + } + + public Iterator getFaultSubcodes() { + return getSaajFault().getFaultSubcodes(); + } + + public void addFaultSubcode(QName subcode) { + try { + getSaajFault().appendFaultSubcode(subcode); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public String getFaultActorOrRole() { + return getSaajFault().getFaultRole(); + } + + public void setFaultActorOrRole(String uri) { + try { + getSaajFault().setFaultRole(uri); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public String getFaultNode() { + return getSaajFault().getFaultNode(); + } + + public void setFaultNode(String uri) { + try { + getSaajFault().setFaultNode(uri); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public void setFaultReasonText(Locale locale, String text) { + try { + getSaajFault().addFaultReasonText(text, locale); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public String getFaultReasonText(Locale locale) { + try { + return getSaajFault().getFaultReasonText(locale); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java new file mode 100644 index 00000000..365b2a5f --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapBody.java @@ -0,0 +1,71 @@ +/* + * 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.saaj; + +import java.util.Iterator; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPBodyElement; +import javax.xml.transform.Result; +import javax.xml.transform.Source; + +import org.springframework.ws.soap.SoapBody; + +abstract class SaajSoapBody extends SaajSoapElement implements SoapBody { + + protected SaajSoapBody(SOAPBody body, SaajImplementationStrategy strategy) { + super(body, strategy); + } + + public boolean hasFault() { + return getSaajBody().hasFault(); + } + + public Source getPayloadSource() { + SOAPBodyElement payloadElement = getPayloadElement(); + if (payloadElement == null) { + return null; + } + else { + return getStrategy().getSource(payloadElement); + } + } + + public Result getPayloadResult() { + getStrategy().removeContents(getSaajBody()); + return getStrategy().getResult(getSaajBody()); + } + + /** + * Retrieves the payload of the wrapped SAAJ message as a single DOM element. The payload of a message is the + * contents of the SOAP body. + * + * @return the message payload, or null if none is set. + */ + protected SOAPBodyElement getPayloadElement() { + for (Iterator iterator = getSaajBody().getChildElements(); iterator.hasNext();) { + Object child = iterator.next(); + if (child instanceof SOAPBodyElement) { + return (SOAPBodyElement) child; + } + } + return null; + } + + protected SOAPBody getSaajBody() { + return (SOAPBody) getSaajElement(); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapElement.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapElement.java new file mode 100644 index 00000000..2d7416e2 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapElement.java @@ -0,0 +1,54 @@ +/* + * 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.saaj; + +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPElement; +import javax.xml.transform.Source; + +import org.springframework.util.Assert; +import org.springframework.ws.soap.SoapElement; + +abstract class SaajSoapElement implements SoapElement { + + private final SOAPElement saajElement; + + private final SaajImplementationStrategy strategy; + + protected SaajSoapElement(SOAPElement saajElement, SaajImplementationStrategy strategy) { + Assert.notNull(saajElement, "No saajElement given"); + Assert.notNull(strategy, "No strategy given"); + this.saajElement = saajElement; + this.strategy = strategy; + } + + protected final SOAPElement getSaajElement() { + return saajElement; + } + + protected final SaajImplementationStrategy getStrategy() { + return strategy; + } + + public final QName getName() { + return getStrategy().getName(saajElement); + } + + public final Source getSource() { + return getStrategy().getSource(saajElement); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java new file mode 100644 index 00000000..81741389 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFault.java @@ -0,0 +1,70 @@ +/* + * 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.saaj; + +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPFault; + +import org.springframework.ws.soap.SoapFault; +import org.springframework.ws.soap.SoapFaultDetail; + +abstract class SaajSoapFault extends SaajSoapElement implements SoapFault { + + protected SaajSoapFault(SOAPFault fault, SaajImplementationStrategy strategy) { + super(fault, strategy); + } + + public QName getFaultCode() { + return getStrategy().getFaultCode(getSaajFault()); + } + + public String getFaultActorOrRole() { + return getSaajFault().getFaultActor(); + } + + public void setFaultActorOrRole(String faultActor) { + try { + getSaajFault().setFaultActor(faultActor); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public SoapFaultDetail getFaultDetail() { + Detail saajDetail = getSaajFault().getDetail(); + return saajDetail == null ? null : new SaajSoapFaultDetail(saajDetail); + } + + public SoapFaultDetail addFaultDetail() { + try { + Detail saajDetail = getSaajFault().addDetail(); + return new SaajSoapFaultDetail(saajDetail); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + + } + + protected final SOAPFault getSaajFault() { + return (SOAPFault) getSaajElement(); + } + +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetail.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetail.java new file mode 100644 index 00000000..d8778d18 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetail.java @@ -0,0 +1,81 @@ +/* + * 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.saaj; + +import java.util.Iterator; +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.DetailEntry; +import javax.xml.soap.SOAPException; +import javax.xml.transform.Result; + +import org.springframework.util.Assert; +import org.springframework.ws.soap.SoapFaultDetail; +import org.springframework.ws.soap.SoapFaultDetailElement; + +class SaajSoapFaultDetail extends SaajSoapElement implements SoapFaultDetail { + + public SaajSoapFaultDetail(Detail detail, SaajImplementationStrategy strategy) { + super(detail, strategy); + } + + public SoapFaultDetailElement addFaultDetailElement(QName name) { + try { + DetailEntry detailEntry = getStrategy().addDetailEntry(getSaajDetail(), name); + return new SaajSoapFaultDetailElement(detailEntry, getStrategy()); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + public Result getResult() { + return getStrategy().getResult(getSaajDetail()); + } + + public Iterator getDetailEntries() { + return new SaajSoapFaultDetailIterator(getSaajDetail().getDetailEntries()); + } + + protected Detail getSaajDetail() { + return (Detail) getSaajElement(); + } + + private class SaajSoapFaultDetailIterator implements Iterator { + + private final Iterator saajIterator; + + public SaajSoapFaultDetailIterator(Iterator saajIterator) { + Assert.notNull(saajIterator, "No saajIterator given"); + this.saajIterator = saajIterator; + } + + public boolean hasNext() { + return saajIterator.hasNext(); + } + + public Object next() { + DetailEntry saajDetailEntry = (DetailEntry) saajIterator.next(); + return new SaajSoapFaultDetailElement(saajDetailEntry, getStrategy()); + } + + public void remove() { + saajIterator.remove(); + } + } + +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java new file mode 100644 index 00000000..f0dd903f --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapFaultDetailElement.java @@ -0,0 +1,50 @@ +/* + * 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.saaj; + +import javax.xml.soap.DetailEntry; +import javax.xml.soap.SOAPException; +import javax.xml.transform.Result; + +import org.springframework.ws.soap.SoapFaultDetailElement; + +/** + * @author Arjen Poutsma + */ +public class SaajSoapFaultDetailElement extends SaajSoapElement implements SoapFaultDetailElement { + + public SaajSoapFaultDetailElement(DetailEntry detailEntry, SaajImplementationStrategy strategy) { + super(detailEntry, strategy); + } + + public Result getResult() { + return getStrategy().getResult(getSaajDetailEntry()); + } + + public void addText(String text) { + try { + getSaajDetailEntry().addTextNode(text); + } + catch (SOAPException ex) { + throw new SaajSoapFaultException(ex); + } + } + + protected DetailEntry getSaajDetailEntry() { + return (DetailEntry) getSaajElement(); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeader.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeader.java new file mode 100644 index 00000000..089316ae --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeader.java @@ -0,0 +1,75 @@ +/* + * 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.saaj; + +import java.util.Iterator; +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPHeader; +import javax.xml.soap.SOAPHeaderElement; + +import org.springframework.ws.soap.SoapHeader; +import org.springframework.ws.soap.SoapHeaderElement; +import org.springframework.ws.soap.SoapHeaderException; + +class SaajSoapHeader extends SaajSoapElement implements SoapHeader { + + public SaajSoapHeader(SOAPHeader header, SaajImplementationStrategy strategy) { + super(header, strategy); + } + + public SoapHeaderElement addHeaderElement(QName name) throws SoapHeaderException { + try { + SOAPHeaderElement saajHeaderElement = getStrategy().addHeaderElement(getSaajHeader(), name); + return new SaajSoapHeaderElement(saajHeaderElement, getStrategy()); + } + catch (SOAPException ex) { + throw new SaajSoapHeaderException(ex); + } + } + + public Iterator examineMustUnderstandHeaderElements(String role) { + return new SaajSoapHeaderElementIterator(getStrategy().examineMustUnderstandHeaderElements(getSaajHeader(), role)); + } + + protected final SOAPHeader getSaajHeader() { + return (SOAPHeader) getSaajElement(); + } + + private class SaajSoapHeaderElementIterator implements Iterator { + + private final Iterator saajIterator; + + private SaajSoapHeaderElementIterator(Iterator saajIterator) { + this.saajIterator = saajIterator; + } + + public boolean hasNext() { + return saajIterator.hasNext(); + } + + public Object next() { + SOAPHeaderElement saajHeaderElement = (SOAPHeaderElement) saajIterator.next(); + return new SaajSoapHeaderElement(saajHeaderElement, getStrategy()); + } + + public void remove() { + saajIterator.remove(); + } + } + +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeaderElement.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeaderElement.java new file mode 100644 index 00000000..92199b07 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeaderElement.java @@ -0,0 +1,54 @@ +/* + * 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.saaj; + +import javax.xml.soap.SOAPHeaderElement; +import javax.xml.transform.Result; + +import org.springframework.ws.soap.SoapHeaderElement; +import org.springframework.ws.soap.SoapHeaderException; + +class SaajSoapHeaderElement extends SaajSoapElement implements SoapHeaderElement { + + public SaajSoapHeaderElement(SOAPHeaderElement headerElement, SaajImplementationStrategy strategy) { + super(headerElement, strategy); + } + + public String getActorOrRole() throws SoapHeaderException { + return getSaajHeaderElement().getActor(); + } + + public void setActorOrRole(String actorOrRole) throws SoapHeaderException { + getSaajHeaderElement().setActor(actorOrRole); + } + + public boolean getMustUnderstand() throws SoapHeaderException { + return getSaajHeaderElement().getMustUnderstand(); + } + + public void setMustUnderstand(boolean mustUnderstand) throws SoapHeaderException { + getSaajHeaderElement().setMustUnderstand(mustUnderstand); + } + + public Result getResult() throws SoapHeaderException { + return getStrategy().getResult(getSaajHeaderElement()); + } + + protected SOAPHeaderElement getSaajHeaderElement() { + return (SOAPHeaderElement) getSaajElement(); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java b/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java index 843ffb69..effc020b 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java @@ -29,6 +29,7 @@ import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import org.springframework.core.io.Resource; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.xml.namespace.QNameUtils; import org.w3c.dom.Element; @@ -59,7 +60,7 @@ public abstract class SaajUtils { saajVersion = SAAJ_13; } catch (ClassNotFoundException ex) { - if (Element.class.isAssignableFrom(SOAPElement.class) && !isWebLogic9Implementation()) { + if (Element.class.isAssignableFrom(SOAPElement.class)) { saajVersion = SAAJ_12; } else { @@ -72,6 +73,7 @@ public abstract class SaajUtils { * Checks whether we are dealing with a WebLogic 9 implementation of SAAJ. WebLogic 9 does implement SAAJ 1.2, but * throws UnsupportedOperationExceptions when a SAAJ 1.2 method is called. */ +/* private static boolean isWebLogic9Implementation() { try { MessageFactory messageFactory = MessageFactory.newInstance(); @@ -88,6 +90,7 @@ public abstract class SaajUtils { return false; } } +*/ /** * Gets the SAAJ version. @@ -106,25 +109,25 @@ public abstract class SaajUtils { * * @param qName the QName to convert * @param resolveElement a SOAPElement used to resolve namespaces to prefixes - * @param envelope a SOAPEnvelope necessary to create the Name * @return the converted SAAJ Name * @throws SOAPException if conversion is unsuccessful * @throws IllegalArgumentException if qName is not fully qualified */ - public static Name toName(QName qName, SOAPElement resolveElement, SOAPEnvelope envelope) throws SOAPException { + public static Name toName(QName qName, SOAPElement resolveElement) throws SOAPException { String qNamePrefix = QNameUtils.getPrefix(qName); + SOAPEnvelope envelope = getEnvelope(resolveElement); if (StringUtils.hasLength(qName.getNamespaceURI()) && StringUtils.hasLength(qNamePrefix)) { return envelope.createName(qName.getLocalPart(), qNamePrefix, qName.getNamespaceURI()); } else if (StringUtils.hasLength(qName.getNamespaceURI())) { - Iterator prefixes = resolveElement.getVisibleNamespacePrefixes(); + Iterator prefixes = resolveElement.getNamespacePrefixes(); while (prefixes.hasNext()) { String prefix = (String) prefixes.next(); if (qName.getNamespaceURI().equals(resolveElement.getNamespaceURI(prefix))) { return envelope.createName(qName.getLocalPart(), prefix, qName.getNamespaceURI()); } } - throw new IllegalArgumentException("Could not resolve namespace of QName [" + qName + "]"); + throw new IllegalArgumentException("Could not resolve prefix of QName [" + qName + "]"); } else { return envelope.createName(qName.getLocalPart()); @@ -183,4 +186,22 @@ public abstract class SaajUtils { is.close(); } } + + /** + * Returns the SAAJ SOAPEnvelope for the given element. + * + * @param element the element to return the envelope from + * @return the envelope, or null if not found + */ + public static SOAPEnvelope getEnvelope(SOAPElement element) { + Assert.notNull(element, "Element should not be null"); + do { + if (element instanceof SOAPEnvelope) { + return (SOAPEnvelope) element; + } + element = element.getParentElement(); + } + while (element != null); + return null; + } } diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandler.java b/core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandler.java new file mode 100644 index 00000000..094b0527 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandler.java @@ -0,0 +1,92 @@ +package org.springframework.ws.soap.saaj.support; + +import javax.xml.soap.Name; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPEnvelope; +import javax.xml.soap.SOAPException; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * @author Arjen Poutsma + */ +public class SoapElementContentHandler extends DefaultHandler { + + private final SOAPEnvelope envelope; + + private SOAPElement current; + + private static final String XMLNS = "xmlns"; + + public SoapElementContentHandler(SOAPElement element) { + this.envelope = SaajUtils.getEnvelope(element); + this.current = element; + } + + public void characters(char ch[], int start, int length) throws SAXException { + try { + current.addTextNode(new String(ch, start, length)); + } + catch (SOAPException ex) { + throw new SAXException(ex); + } + } + + public void endPrefixMapping(String prefix) throws SAXException { + current.removeNamespaceDeclaration(prefix); + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + try { + current.addNamespaceDeclaration(prefix, uri); + } + catch (SOAPException ex) { + throw new SAXException(ex); + } + } + + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + try { + Name elementName = createName(uri, qName); + SOAPElement child = current.addChildElement(elementName); + for (int i = 0; i < attributes.getLength(); i++) { + Name attributeName = createName(attributes.getURI(i), attributes.getQName(i)); + if (attributeName != null) { + child.addAttribute(attributeName, attributes.getValue(i)); + } else { + int idx = attributes.getQName(i).indexOf(':'); + String prefix = attributes.getQName(i).substring(idx+1); + child.addNamespaceDeclaration(prefix, attributes.getValue(i)); + } + } + current = child; + } + catch (SOAPException ex) { + throw new SAXException(ex); + } + } + + private Name createName(String namespaceUri, String qualifiedName) throws SOAPException { + int idx = qualifiedName.indexOf(':'); + String localName = qualifiedName.substring(idx + 1); + if (idx == -1) { + return envelope.createName(localName, "", namespaceUri); + } + else { + String prefix = qualifiedName.substring(0, idx); + if (!XMLNS.equals(prefix)) { + return envelope.createName(localName, prefix, namespaceUri); + } + else { + return null; + } + } + + } + + public void endElement(String uri, String localName, String qName) throws SAXException { + current = current.getParentElement(); + } +} diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReader.java b/core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReader.java new file mode 100644 index 00000000..56dc0e38 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReader.java @@ -0,0 +1,112 @@ +/* + * 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.saaj.support; + +import java.util.Iterator; +import javax.xml.soap.Name; +import javax.xml.soap.Node; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.Text; + +import org.springframework.xml.sax.AbstractXmlReader; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * SAX XMLReader that can read from a SAAJ SOAPElement + * @author Arjen Poutsma + */ +public class SoapElementXmlReader extends AbstractXmlReader { + + private SOAPElement element; + + public SoapElementXmlReader(SOAPElement element) { + this.element = element; + } + + /** + * Parses the StAX XML reader passed at construction-time. + *

+ * Note that the given InputSource is not read, but ignored. + * + * @param ignored is ignored + * @throws SAXException A SAX exception, possibly wrapping a XMLStreamException + */ + public final void parse(InputSource ignored) throws SAXException { + handleNode(element); + } + + /** + * Parses the StAX XML reader passed at construction-time. + *

+ * Note that the given system identifier is not read, but ignored. + * + * @param ignored is ignored + * @throws SAXException A SAX exception, possibly wrapping a XMLStreamException + */ + public final void parse(String ignored) throws SAXException { + handleNode(element); + } + + private void handleNode(Node node) throws SAXException { + if (node instanceof SOAPElement) { + SOAPElement soapElement = (SOAPElement) node; + handleSoapElement(soapElement); + } + else if (node instanceof Text) { + Text text = (Text) node; + handleText(text); + } + } + + private void handleText(Text text) throws SAXException { + if (!text.isComment() && getContentHandler() != null) { + char[] ch = text.getValue().toCharArray(); + getContentHandler().characters(ch, 0, ch.length); + } + } + + private void handleSoapElement(SOAPElement soapElement) throws SAXException { + if (getContentHandler() != null) { + for (Iterator i = soapElement.getNamespacePrefixes(); i.hasNext();) { + String prefix = (String) i.next(); + getContentHandler().startPrefixMapping(prefix, soapElement.getNamespaceURI(prefix)); + } + Name name = soapElement.getElementName(); + getContentHandler().startElement(name.getURI(), name.getLocalName(), name.getQualifiedName(), + getAttributes(soapElement)); + for (Iterator i = soapElement.getChildElements(); i.hasNext();) { + Node child = (Node) i.next(); + handleNode(child); + } + getContentHandler().endElement(name.getURI(), name.getLocalName(), name.getQualifiedName()); + } + } + + private Attributes getAttributes(SOAPElement soapElement) { + AttributesImpl attributes = new AttributesImpl(); + + for (Iterator i = soapElement.getAllAttributes(); i.hasNext();) { + Name name = (Name) i.next(); + attributes.addAttribute(name.getURI(), name.getLocalName(), name.getQualifiedName(), null, + soapElement.getAttributeValue(name)); + } + return attributes; + } +} diff --git a/core/src/test/java/org/springframework/ws/soap/AbstractSoapHeaderTestCase.java b/core/src/test/java/org/springframework/ws/soap/AbstractSoapHeaderTestCase.java index cb92e194..4acb4798 100644 --- a/core/src/test/java/org/springframework/ws/soap/AbstractSoapHeaderTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/AbstractSoapHeaderTestCase.java @@ -50,26 +50,6 @@ public abstract class AbstractSoapHeaderTestCase extends XMLTestCase { ""); } - public void testExamineAllHeaderElement() throws Exception { - QName qName = new QName("http://www.springframework.org", "localName", "spring"); - SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName); - assertEquals("Invalid qName for element", qName, headerElement.getName()); - String payload = ""; - assertNotNull("No SoapHeaderElement returned", headerElement); - transformer.transform(new StringSource(payload), headerElement.getResult()); - Iterator iterator = soapHeader.examineAllHeaderElements(); - assertNotNull("header element iterator is null", iterator); - assertTrue("header element iterator has no elements", iterator.hasNext()); - headerElement = (SoapHeaderElement) iterator.next(); - assertEquals("Invalid qName for element", qName, headerElement.getName()); - StringResult result = new StringResult(); - transformer.transform(headerElement.getSource(), result); - assertXMLEqual("Invalid contents of header element", - "", - result.toString()); - assertFalse("header element iterator has too many elements", iterator.hasNext()); - } - public void testExamineMustUnderstandHeaderElements() throws Exception { QName qName1 = new QName("http://www.springframework.org", "localName1", "spring"); SoapHeaderElement headerElement1 = soapHeader.addHeaderElement(qName1); diff --git a/core/src/test/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategyTest.java b/core/src/test/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategyTest.java new file mode 100644 index 00000000..02ce273e --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/saaj/Saaj11ImplementationStrategyTest.java @@ -0,0 +1,114 @@ +/* + * 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.saaj; + +import javax.xml.namespace.QName; +import javax.xml.soap.Detail; +import javax.xml.soap.DetailEntry; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPEnvelope; +import javax.xml.soap.SOAPFault; +import javax.xml.soap.SOAPHeader; +import javax.xml.soap.SOAPMessage; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; + +import org.custommonkey.xmlunit.XMLTestCase; +import org.springframework.ws.soap.SoapVersion; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; + +public class Saaj11ImplementationStrategyTest extends XMLTestCase { + + private Saaj11ImplementationStrategy strategy; + + private SOAPMessage message; + + private SOAPEnvelope envelope; + + private Transformer transformer; + + protected void setUp() throws Exception { + strategy = new Saaj11ImplementationStrategy(); + MessageFactory messageFactory = MessageFactory.newInstance(); + message = messageFactory.createMessage(); + envelope = message.getSOAPPart().getEnvelope(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformer = transformerFactory.newTransformer(); + } + + public void testGetName() throws Exception { + QName name = strategy.getName(envelope); + assertEquals("Invalid name", SoapVersion.SOAP_11.getEnvelopeName(), name); + } + + public void testGetSource() throws Exception { + StringResult result = new StringResult(); + transformer.transform(strategy.getSource(envelope), result); + + assertXMLEqual("Invalid source", + "

", + result.toString()); + } + + public void testGetResult() throws Exception { + SOAPBody body = envelope.getBody(); + StringSource content = new StringSource(""); + transformer.transform(content, strategy.getResult(body)); + + StringResult result = new StringResult(); + transformer.transform(strategy.getSource(envelope), result); + assertXMLEqual("Invalid source", + "
", + result.toString()); + } + + public void testGetFaultCode() throws Exception { + SOAPBody body = envelope.getBody(); + SOAPFault fault = body.addFault(); + fault.setFaultCode(fault.getElementName().getPrefix() + ":Client"); + QName faultCode = strategy.getFaultCode(fault); + assertEquals("Invalid fault code", SoapVersion.SOAP_11.getClientOrSenderFaultName(), faultCode); + } + + public void testAddDetailEntry() throws Exception { + SOAPBody body = envelope.getBody(); + SOAPFault fault = body.addFault(); + QName name = new QName("http://springframework.org/spring-ws", "name", "spring-ws"); + + Detail detail = fault.addDetail(); + DetailEntry result = strategy.addDetailEntry(detail, name); + assertNotNull("No result returned", result); + assertEquals("Invalid namespace", result.getElementName().getURI(), name.getNamespaceURI()); + assertEquals("Invalid namespace", result.getElementName().getLocalName(), name.getLocalPart()); + } + + public void testRemoveContents() throws Exception { + SOAPBody body = envelope.getBody(); + body.addTextNode("bla"); + body.addChildElement("bla"); + strategy.removeContents(body); + assertFalse("Children not removed", body.getChildElements().hasNext()); + } + + public void testAddHeaderElement() throws Exception { + SOAPHeader header = envelope.getHeader(); + + fail("Test is not implemented"); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/springframework/ws/soap/saaj/support/SaajUtilsTest.java b/core/src/test/java/org/springframework/ws/soap/saaj/support/SaajUtilsTest.java index 223ad9b5..668b5ae5 100644 --- a/core/src/test/java/org/springframework/ws/soap/saaj/support/SaajUtilsTest.java +++ b/core/src/test/java/org/springframework/ws/soap/saaj/support/SaajUtilsTest.java @@ -41,7 +41,7 @@ public class SaajUtilsTest extends XMLTestCase { SOAPMessage message = messageFactory.createMessage(); QName qName = new QName("localPart"); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); - Name name = SaajUtils.toName(qName, envelope, envelope); + Name name = SaajUtils.toName(qName, envelope); assertNotNull("Invalid name", name); assertEquals("Invalid local part", qName.getLocalPart(), name.getLocalName()); assertFalse("Invalid prefix", StringUtils.hasLength(name.getPrefix())); @@ -53,7 +53,7 @@ public class SaajUtilsTest extends XMLTestCase { QName qName = new QName("namespace", "localPart"); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.addNamespaceDeclaration("prefix", "namespace"); - Name name = SaajUtils.toName(qName, envelope, envelope); + Name name = SaajUtils.toName(qName, envelope); assertNotNull("Invalid name", name); assertEquals("Invalid namespace", qName.getNamespaceURI(), name.getURI()); assertEquals("Invalid local part", qName.getLocalPart(), name.getLocalName()); @@ -64,7 +64,7 @@ public class SaajUtilsTest extends XMLTestCase { SOAPMessage message = messageFactory.createMessage(); QName qName = new QName("namespace", "localPart", "prefix"); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); - Name name = SaajUtils.toName(qName, envelope, envelope); + Name name = SaajUtils.toName(qName, envelope); assertNotNull("Invalid name", name); assertEquals("Invalid namespace", qName.getNamespaceURI(), name.getURI()); assertEquals("Invalid local part", qName.getLocalPart(), name.getLocalName()); @@ -114,4 +114,12 @@ public class SaajUtilsTest extends XMLTestCase { public void testGetSaajVersion() throws Exception { assertEquals("Invalid SAAJ version", SaajUtils.SAAJ_13, SaajUtils.getSaajVersion()); } + + public void testGetEnvelope() throws Exception { + SOAPMessage message = messageFactory.createMessage(); + SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); + assertSame("Invalid envelope returned", envelope, SaajUtils.getEnvelope(envelope)); + assertSame("Invalid envelope returned", envelope, SaajUtils.getEnvelope(envelope.getBody())); + assertSame("Invalid envelope returned", envelope, SaajUtils.getEnvelope(envelope.getHeader())); + } } \ No newline at end of file diff --git a/core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandlerTest.java b/core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandlerTest.java new file mode 100644 index 00000000..71e92c10 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementContentHandlerTest.java @@ -0,0 +1,41 @@ +package org.springframework.ws.soap.saaj.support; + +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPConstants; +import javax.xml.soap.SOAPMessage; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; + +import org.custommonkey.xmlunit.XMLTestCase; +import org.springframework.xml.transform.StringSource; + +public class SoapElementContentHandlerTest extends XMLTestCase { + + private SOAPMessage message; + + private Transformer transformer; + + private SOAPMessage expected; + + protected void setUp() throws Exception { + MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL); + message = messageFactory.createMessage(); + expected = messageFactory.createMessage(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformer = transformerFactory.newTransformer(); + } + + public void testWriteToPayload() throws Exception { + StringSource contents = new StringSource( + "" + "DIS" + + ""); + transformer.transform(contents, new DOMResult(expected.getSOAPBody())); + SoapElementContentHandler handler = + new SoapElementContentHandler(message.getSOAPPart().getEnvelope(), message.getSOAPBody()); + transformer.transform(new DOMSource(expected.getSOAPBody().getFirstChild()), new SAXResult(handler)); + assertXMLEqual(expected.getSOAPPart(), message.getSOAPPart()); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReaderTest.java b/core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReaderTest.java new file mode 100644 index 00000000..fb60f491 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/saaj/support/SoapElementXmlReaderTest.java @@ -0,0 +1,71 @@ +/* + * 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.saaj.support; + +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPConstants; +import javax.xml.soap.SOAPEnvelope; +import javax.xml.soap.SOAPMessage; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; + +import org.custommonkey.xmlunit.XMLTestCase; +import org.springframework.core.io.ClassPathResource; +import org.springframework.xml.transform.StringResult; +import org.xml.sax.InputSource; + +public class SoapElementXmlReaderTest extends XMLTestCase { + + private Transformer transformer; + + private MessageFactory messageFactory; + + protected void setUp() throws Exception { + messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL); + transformer = TransformerFactory.newInstance().newTransformer(); + } + + public void testReader() throws Exception { + SOAPMessage message = messageFactory.createMessage(); + SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); + SoapElementXmlReader reader = new SoapElementXmlReader(envelope); + DOMSource domSource = new DOMSource(envelope); + StringResult expected = new StringResult(); + transformer.transform(domSource, expected); + + StringResult result = new StringResult(); + transformer.transform(new SAXSource(reader, new InputSource()), result); + assertXMLEqual(expected.toString(), result.toString()); + } + + public void testReader2() throws Exception { + SOAPMessage message = + SaajUtils.loadMessage(new ClassPathResource("org/springframework/ws/soap/context/soap11.xml")); + SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); + SoapElementXmlReader reader = new SoapElementXmlReader(envelope); + DOMSource domSource = new DOMSource(envelope); + StringResult expected = new StringResult(); + transformer.transform(domSource, expected); + + StringResult result = new StringResult(); + transformer.transform(new SAXSource(reader, new InputSource()), result); + assertXMLEqual(expected.toString(), result.toString()); + } + +} \ No newline at end of file