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 c9266dcf..33647274 100644 --- a/core/src/main/java/org/springframework/ws/soap/SoapHeader.java +++ b/core/src/main/java/org/springframework/ws/soap/SoapHeader.java @@ -49,6 +49,17 @@ public interface SoapHeader extends SoapElement { */ SoapHeaderElement addHeaderElement(QName name) throws SoapHeaderException; + /** + * Removes the SoapHeaderElement with the specified qualified name from this header. + *

+ * This method will only remove the first child element with the specified name. If no element is found with the + * specified name, this method has no effect. + * + * @param name the qualified name of the header element to be removed + * @throws SoapHeaderException if the header cannot be removed + */ + void removeHeaderElement(QName name) throws SoapHeaderException; + /** * Returns an Iterator over all the SoapHeaderElements that have the specified actor or * role and that have a MustUnderstand attribute whose value is equivalent to true. diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapHeader.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapHeader.java index 7a836544..7804806b 100644 --- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapHeader.java +++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapHeader.java @@ -21,6 +21,7 @@ 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; import org.apache.axiom.om.OMNamespace; import org.apache.axiom.soap.SOAPFactory; @@ -60,6 +61,18 @@ abstract class AxiomSoapHeader extends AxiomSoapElement implements SoapHeader { } } + public void removeHeaderElement(QName name) throws SoapHeaderException { + try { + OMElement element = getAxiomHeader().getFirstChildWithName(name); + if (element != null) { + element.detach(); + } + } + catch (OMException ex) { + throw new AxiomSoapHeaderException(ex); + } + } + public Iterator examineMustUnderstandHeaderElements(String role) { try { return new AxiomSoapHeaderElementIterator(getAxiomHeader().examineMustUnderstandHeaderBlocks(role)); diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11Implementation.java b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11Implementation.java index dce1dbc9..6de04673 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11Implementation.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj11Implementation.java @@ -43,6 +43,8 @@ import javax.xml.transform.Source; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXSource; +import org.xml.sax.InputSource; + import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.ws.soap.SoapVersion; @@ -52,7 +54,6 @@ import org.springframework.ws.soap.saaj.support.SaajXmlReader; import org.springframework.ws.transport.TransportConstants; import org.springframework.ws.transport.TransportOutputStream; import org.springframework.xml.namespace.QNameUtils; -import org.xml.sax.InputSource; /** * SAAJ 1.1 specific implementation of the SaajImplementation interface. @@ -277,6 +278,11 @@ class Saaj11Implementation extends SaajImplementation { } } + Iterator getChildElements(SOAPElement element, QName name) throws SOAPException { + Name elementName = SaajUtils.toName(name, element); + return element.getChildElements(elementName); + } + public void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException { if (message.saveRequired()) { message.saveChanges(); diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12Implementation.java b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12Implementation.java index 6ee58c51..6a42f24c 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12Implementation.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj12Implementation.java @@ -228,6 +228,11 @@ class Saaj12Implementation extends SaajImplementation { element.removeContents(); } + Iterator getChildElements(SOAPElement element, QName name) throws SOAPException { + Name elementName = SaajUtils.toName(name, element); + return element.getChildElements(elementName); + } + public void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException { if (message.saveRequired()) { message.saveChanges(); diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13Implementation.java b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13Implementation.java index 4419c87d..17c156ac 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13Implementation.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/Saaj13Implementation.java @@ -255,6 +255,10 @@ class Saaj13Implementation extends SaajImplementation { element.removeContents(); } + Iterator getChildElements(SOAPElement element, QName name) throws SOAPException { + return element.getChildElements(name); + } + public void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException { if (message.saveRequired()) { message.saveChanges(); diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementation.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementation.java index 0615c172..4f79693c 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementation.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajImplementation.java @@ -45,152 +45,191 @@ import javax.xml.transform.Source; */ abstract class SaajImplementation { + /* + * SOAPElement + */ + /** Returns the name of the given element. */ - public abstract QName getName(SOAPElement element); + abstract QName getName(SOAPElement element); /** Returns the readable Source of the given element. */ - public abstract Source getSource(SOAPElement element); + abstract Source getSource(SOAPElement element); /** Returns the writable Result of the given element. */ - public abstract Result getResult(SOAPElement element); + abstract Result getResult(SOAPElement element); /** Returns the text of the given element */ - public abstract String getText(SOAPElement element); + abstract String getText(SOAPElement element); /** Returns the text of the given element */ - public abstract void setText(SOAPElement element, String content) throws SOAPException; + abstract void setText(SOAPElement element, String content) throws SOAPException; /** Adds an attribute to the specified element. */ - public abstract void addAttribute(SOAPElement element, QName name, String value) throws SOAPException; + abstract void addAttribute(SOAPElement element, QName name, String value) throws SOAPException; /** Removes an attribute from the specified element. */ - public abstract void removeAttribute(SOAPElement element, QName name) throws SOAPException; + abstract void removeAttribute(SOAPElement element, QName name) throws SOAPException; /** Returns the attribute value * */ - public abstract String getAttributeValue(SOAPElement element, QName name) throws SOAPException; + abstract String getAttributeValue(SOAPElement element, QName name) throws SOAPException; /** Returns all attributes as an iterator of QNames. * */ - public abstract Iterator getAllAttibutes(SOAPElement element); - - /** Returns the envelope of the given message. */ - public abstract SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException; - - /** Returns the header of the given envelope. */ - public abstract SOAPHeader getHeader(SOAPEnvelope envelope) throws SOAPException; - - /** Returns the body of the given envelope. */ - public abstract SOAPBody getBody(SOAPEnvelope envelope) throws SOAPException; - - /** Adds a header element to the given header. */ - public abstract SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException; - - /** Returns all header elements. */ - public abstract Iterator examineAllHeaderElements(SOAPHeader header); - - /** Returns all header elements for which the must understand attribute is true, given the actor or role. */ - public abstract Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String actorOrRole); - - /** Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ - public abstract String getActorOrRole(SOAPHeaderElement headerElement); - - /** Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ - public abstract void setActorOrRole(SOAPHeaderElement headerElement, String actorOrRole); - - /** Gets the must understand attribute for the given header element. */ - public abstract boolean getMustUnderstand(SOAPHeaderElement headerElement); - - /** Sets the must understand attribute for the given header element. */ - public abstract void setMustUnderstand(SOAPHeaderElement headerElement, boolean mustUnderstand); - - /** Returns true if the body has a fault, false otherwise. */ - public abstract boolean hasFault(SOAPBody body); - - /** Returns the fault for the given body, if any. */ - public abstract SOAPFault getFault(SOAPBody body); - - /** Adds a fault to the given body. */ - public abstract SOAPFault addFault(SOAPBody body, QName faultCode, String faultString, Locale locale) - throws SOAPException; - - /** Returns the fault code for the given fault. */ - public abstract QName getFaultCode(SOAPFault fault); - - /** Returns the actor for the given fault. */ - public abstract String getFaultActor(SOAPFault fault); - - /** Sets the actor for the given fault. */ - public abstract void setFaultActor(SOAPFault fault, String actorOrRole) throws SOAPException; - - /** Returns the fault string for the given fault. */ - public abstract String getFaultString(SOAPFault fault); - - /** Returns the fault string language for the given fault. */ - public abstract Locale getFaultStringLocale(SOAPFault fault); - - /** Adds a detail entry to the given detail. */ - public abstract DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException; - - /** Returns the fault detail for the given fault. */ - public abstract Detail getFaultDetail(SOAPFault fault); - - /** Adds a fault detail for the given fault. */ - public abstract Detail addFaultDetail(SOAPFault fault) throws SOAPException; - - public abstract void addTextNode(DetailEntry detailEntry, String text) throws SOAPException; - - /** Returns an iteration over all detail entries. */ - public abstract Iterator getDetailEntries(Detail detail); - - /** Returns the first child element of the given body. */ - public abstract SOAPElement getFirstBodyElement(SOAPBody body); + abstract Iterator getAllAttibutes(SOAPElement element); /** Removes the contents (i.e. children) of the element. */ - public abstract void removeContents(SOAPElement element); + abstract void removeContents(SOAPElement element); + + /** Returns an iterator over all the child elements with the specified name. */ + abstract Iterator getChildElements(SOAPElement element, QName name) throws SOAPException; + + /* + * SOAPMessage + */ + + /** Returns the envelope of the given message. */ + abstract SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException; /** Writes the given message to the given stream. */ - public abstract void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException; + abstract void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException; /** Returns the MIME headers of the message. */ - public abstract MimeHeaders getMimeHeaders(SOAPMessage message); + abstract MimeHeaders getMimeHeaders(SOAPMessage message); /** Returns an iteration over all attachments in the message. */ - public abstract Iterator getAttachments(SOAPMessage message); + abstract Iterator getAttachments(SOAPMessage message); /** Returns an iteration over all attachments in the message with the given headers. */ - public abstract Iterator getAttachment(SOAPMessage message, MimeHeaders mimeHeaders); + abstract Iterator getAttachment(SOAPMessage message, MimeHeaders mimeHeaders); /** Adds an attachment to the given message. */ - public abstract AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler); + abstract AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler); + + /* + * SOAPEnvelope + */ + + /** Returns the header of the given envelope. */ + abstract SOAPHeader getHeader(SOAPEnvelope envelope) throws SOAPException; + + /** Returns the body of the given envelope. */ + abstract SOAPBody getBody(SOAPEnvelope envelope) throws SOAPException; + + /* + * SOAPHeader + */ + + /** Adds a header element to the given header. */ + abstract SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException; + + /** Returns all header elements. */ + abstract Iterator examineAllHeaderElements(SOAPHeader header); + + /** Returns all header elements for which the must understand attribute is true, given the actor or role. */ + abstract Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String actorOrRole); /** Adds a not understood header element to the given header. */ - public abstract SOAPHeaderElement addNotUnderstoodHeaderElement(SOAPHeader header, QName name) throws SOAPException; + abstract SOAPHeaderElement addNotUnderstoodHeaderElement(SOAPHeader header, QName name) throws SOAPException; /** Adds a upgrade header element to the given header. */ - public abstract SOAPHeaderElement addUpgradeHeaderElement(SOAPHeader header, String[] supportedSoapUris) + abstract SOAPHeaderElement addUpgradeHeaderElement(SOAPHeader header, String[] supportedSoapUris) throws SOAPException; + /* + * SOAPHeaderElement + */ + + /** Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ + abstract String getActorOrRole(SOAPHeaderElement headerElement); + + /** Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ + abstract void setActorOrRole(SOAPHeaderElement headerElement, String actorOrRole); + + /** Gets the must understand attribute for the given header element. */ + abstract boolean getMustUnderstand(SOAPHeaderElement headerElement); + + /** Sets the must understand attribute for the given header element. */ + abstract void setMustUnderstand(SOAPHeaderElement headerElement, boolean mustUnderstand); + + /* + * SOAPBody + */ + + /** Returns true if the body has a fault, false otherwise. */ + abstract boolean hasFault(SOAPBody body); + + /** Returns the fault for the given body, if any. */ + abstract SOAPFault getFault(SOAPBody body); + + /** Adds a fault to the given body. */ + abstract SOAPFault addFault(SOAPBody body, QName faultCode, String faultString, Locale locale) throws SOAPException; + + /** Returns the first child element of the given body. */ + abstract SOAPElement getFirstBodyElement(SOAPBody body); + + /* + * SOAPFault + */ + + /** Returns the fault code for the given fault. */ + abstract QName getFaultCode(SOAPFault fault); + + /** Returns the actor for the given fault. */ + abstract String getFaultActor(SOAPFault fault); + + /** Sets the actor for the given fault. */ + abstract void setFaultActor(SOAPFault fault, String actorOrRole) throws SOAPException; + + /** Returns the fault string for the given fault. */ + abstract String getFaultString(SOAPFault fault); + + /** Returns the fault string language for the given fault. */ + abstract Locale getFaultStringLocale(SOAPFault fault); + + /** Returns the fault detail for the given fault. */ + abstract Detail getFaultDetail(SOAPFault fault); + + /** Adds a fault detail for the given fault. */ + abstract Detail addFaultDetail(SOAPFault fault) throws SOAPException; + /** Returns the fault role. */ - public abstract String getFaultRole(SOAPFault fault); + abstract String getFaultRole(SOAPFault fault); /** Sets the fault role. */ - public abstract void setFaultRole(SOAPFault fault, String role) throws SOAPException; + abstract void setFaultRole(SOAPFault fault, String role) throws SOAPException; /** Returns the fault sub code. */ - public abstract Iterator getFaultSubcodes(SOAPFault fault); + abstract Iterator getFaultSubcodes(SOAPFault fault); /** Adds a fault sub code. */ - public abstract void appendFaultSubcode(SOAPFault fault, QName subcode) throws SOAPException; + abstract void appendFaultSubcode(SOAPFault fault, QName subcode) throws SOAPException; /** Returns the fault node. */ - public abstract String getFaultNode(SOAPFault fault); + abstract String getFaultNode(SOAPFault fault); /** Sets the fault node. */ - public abstract void setFaultNode(SOAPFault fault, String uri) throws SOAPException; + abstract void setFaultNode(SOAPFault fault, String uri) throws SOAPException; /** Returns the fault reason text. */ - public abstract String getFaultReasonText(SOAPFault fault, Locale locale) throws SOAPException; + abstract String getFaultReasonText(SOAPFault fault, Locale locale) throws SOAPException; /** Sets the fault reason text. */ - public abstract void setFaultReasonText(SOAPFault fault, Locale locale, String text) throws SOAPException; + abstract void setFaultReasonText(SOAPFault fault, Locale locale, String text) throws SOAPException; + + /* + * Detail + */ + + /** Adds a detail entry to the given detail. */ + abstract DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException; + + /** Returns an iteration over all detail entries. */ + abstract Iterator getDetailEntries(Detail detail); + + /* + * DetailEntry + */ + + /** Adds a text node to the given detail entry. */ + abstract void addTextNode(DetailEntry detailEntry, String text) throws SOAPException; } 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 index 6e52e9a6..6abbcb5f 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeader.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapHeader.java @@ -18,6 +18,7 @@ package org.springframework.ws.soap.saaj; import java.util.Iterator; import javax.xml.namespace.QName; +import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPHeaderElement; @@ -60,6 +61,19 @@ abstract class SaajSoapHeader extends SaajSoapElement implements SoapHeader { } } + public void removeHeaderElement(QName name) throws SoapHeaderException { + try { + Iterator iterator = getImplementation().getChildElements(getSaajHeader(), name); + if (iterator.hasNext()) { + SOAPElement element = (SOAPElement) iterator.next(); + element.detachNode(); + } + } + catch (SOAPException ex) { + throw new SaajSoapHeaderException(ex); + } + } + protected SOAPHeader getSaajHeader() { return (SOAPHeader) getSaajElement(); } 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 e56e495d..46b306b3 100644 --- a/core/src/test/java/org/springframework/ws/soap/AbstractSoapHeaderTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/AbstractSoapHeaderTestCase.java @@ -42,12 +42,23 @@ public abstract class AbstractSoapHeaderTestCase extends AbstractSoapElementTest SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName); assertNotNull("No SoapHeaderElement returned", headerElement); assertEquals("Invalid qName for element", qName, headerElement.getName()); + Iterator iterator = soapHeader.examineAllHeaderElements(); + assertTrue("SoapHeader has no elements", iterator.hasNext()); String payload = ""; transformer.transform(new StringSource(payload), headerElement.getResult()); assertHeaderElementEqual(headerElement, ""); } + public void testRemoveHeaderElement() throws Exception { + QName qName = new QName(NAMESPACE, "localName", PREFIX); + soapHeader.removeHeaderElement(qName); + soapHeader.addHeaderElement(qName); + soapHeader.removeHeaderElement(qName); + Iterator iterator = soapHeader.examineAllHeaderElements(); + assertFalse("SoapHeader has elements", iterator.hasNext()); + } + public void testExamineAllHeaderElement() throws Exception { QName qName = new QName(NAMESPACE, "localName", PREFIX); SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName); diff --git a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java index b79a00cb..be35d8f2 100644 --- a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java +++ b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java @@ -25,6 +25,7 @@ public class AxiomSoap12MessageFactoryTest extends AbstractSoap12MessageFactoryT protected WebServiceMessageFactory createMessageFactory() throws Exception { AxiomSoapMessageFactory factory = new AxiomSoapMessageFactory(); factory.setSoapVersion(SoapVersion.SOAP_12); + factory.afterPropertiesSet(); return factory; }