diff --git a/core/src/main/java/org/springframework/ws/soap/SoapMessage.java b/core/src/main/java/org/springframework/ws/soap/SoapMessage.java index 46dd8743..3b345461 100644 --- a/core/src/main/java/org/springframework/ws/soap/SoapMessage.java +++ b/core/src/main/java/org/springframework/ws/soap/SoapMessage.java @@ -39,6 +39,13 @@ public interface SoapMessage extends WebServiceMessage { */ SoapEnvelope getEnvelope() throws SoapEnvelopeException; + /** + * Get the SOAP Action for this messaage, or null if not present. + * + * @return the SOAP Action. + */ + String getSoapAction(); + /** * Returns the SoapBody associated with this SoapMessage. This is a convenience method for * getEnvelope().getBody(). @@ -91,7 +98,7 @@ public interface SoapMessage extends WebServiceMessage { * @param file the File resource to take the content from * @return the added attachment * @throws AttachmentException in case of errors - * @see #addAttachment(InputStreamSource, String) + * @see #addAttachment(InputStreamSource,String) */ Attachment addAttachment(File file) throws AttachmentException; @@ -112,4 +119,5 @@ public interface SoapMessage extends WebServiceMessage { */ Attachment addAttachment(InputStreamSource inputStreamSource, String contentType); + void setSoapAction(String soapAction); } diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java index db9e6bdb..c90782ad 100644 --- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java +++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java @@ -61,6 +61,8 @@ public class AxiomSoapMessage extends AbstractSoapMessage { private AxiomSoapEnvelope envelope; + private String soapAction; + /** * Create a new, empty AxiomSoapMessage. * @@ -72,18 +74,21 @@ public class AxiomSoapMessage extends AbstractSoapMessage { axiomMessage = axiomFactory.createSOAPMessage(soapEnvelope, soapEnvelope.getBuilder()); attachments = null; payloadCaching = true; + soapAction = ""; } /** * Create a new AxiomSoapMessage based on the given AXIOM SOAPMessage. * * @param soapMessage the AXIOM SOAPMessage + * @param soapAction the value of the SOAP Action header * @param payloadCaching whether the contents of the SOAP body should be cached or not */ - public AxiomSoapMessage(SOAPMessage soapMessage, boolean payloadCaching) { + public AxiomSoapMessage(SOAPMessage soapMessage, String soapAction, boolean payloadCaching) { axiomMessage = soapMessage; axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory(); attachments = null; + this.soapAction = soapAction; this.payloadCaching = payloadCaching; } @@ -92,16 +97,23 @@ public class AxiomSoapMessage extends AbstractSoapMessage { * * @param soapMessage the AXIOM SOAPMessage * @param attachments the attachments + * @param soapAction the value of the SOAP Action header * @param payloadCaching whether the contents of the SOAP body should be cached or not */ - public AxiomSoapMessage(SOAPMessage soapMessage, Attachments attachments, boolean payloadCaching) { + public AxiomSoapMessage(SOAPMessage soapMessage, + Attachments attachments, + String soapAction, + boolean payloadCaching) { axiomMessage = soapMessage; axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory(); this.attachments = attachments; + this.soapAction = soapAction; this.payloadCaching = payloadCaching; } - /** Return the AXIOM SOAPMessage that this AxiomSoapMessage is based on. */ + /** + * Return the AXIOM SOAPMessage that this AxiomSoapMessage is based on. + */ public final SOAPMessage getAxiomMessage() { return axiomMessage; } @@ -118,6 +130,14 @@ public class AxiomSoapMessage extends AbstractSoapMessage { return envelope; } + public String getSoapAction() { + return soapAction; + } + + public void setSoapAction(String soapAction) { + this.soapAction = soapAction; + } + public Attachment getAttachment(String contentId) { DataHandler dataHandler = attachments.getDataHandler(contentId); return dataHandler != null ? new AxiomAttachment(contentId, dataHandler) : null; @@ -169,7 +189,9 @@ public class AxiomSoapMessage extends AbstractSoapMessage { } } - /** Axiom-specific implementation of org.springframework.ws.soap.Attachment */ + /** + * Axiom-specific implementation of org.springframework.ws.soap.Attachment + */ private static class AxiomAttachment implements Attachment { private final DataHandler dataHandler; diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java index 11ebd460..411423c7 100644 --- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java +++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java @@ -70,6 +70,8 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia private static final String DEFAULT_CHAR_SET_ENCODING = "UTF-8"; + private static final String SOAP_ACTION_HEADER = "SOAPAction"; + private static final String MULTI_PART_RELATED_CONTENT_TYPE = "multipart/related"; private static final Log logger = LogFactory.getLog(AxiomSoapMessageFactory.class); @@ -107,12 +109,17 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException { String contentType = null; + String soapAction = ""; if (inputStream instanceof TransportInputStream) { TransportInputStream transportInputStream = (TransportInputStream) inputStream; Iterator iterator = transportInputStream.getHeaders(CONTENT_TYPE_HEADER); if (iterator.hasNext()) { contentType = (String) iterator.next(); } + iterator = transportInputStream.getHeaders(SOAP_ACTION_HEADER); + if (iterator.hasNext()) { + soapAction = (String) iterator.next(); + } } if (!StringUtils.hasLength(contentType)) { // fall back to SOAP 1.1 as a default @@ -120,10 +127,10 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia } try { if (isMultiPartRelated(contentType)) { - return createMultiPartAxiomSoapMessage(inputStream, contentType); + return createMultiPartAxiomSoapMessage(inputStream, contentType, soapAction); } else { - return createAxiomSoapMessage(inputStream, contentType); + return createAxiomSoapMessage(inputStream, contentType, soapAction); } } catch (XMLStreamException ex) { @@ -141,20 +148,21 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia /** * Creates an AxiomSoapMessage without attachments. */ - private WebServiceMessage createAxiomSoapMessage(InputStream inputStream, String contentType) + private WebServiceMessage createAxiomSoapMessage(InputStream inputStream, String contentType, String soapAction) throws XMLStreamException { XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream, getCharSetEncoding(contentType)); SOAPFactory soapFactory = getSoapFactory(contentType); StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(reader, soapFactory, soapFactory.getSoapVersionURI()); SOAPMessage soapMessage = builder.getSoapMessage(); - return new AxiomSoapMessage(soapMessage, payloadCaching); + return new AxiomSoapMessage(soapMessage, soapAction, payloadCaching); } /** * Creates an AxiomSoapMessage with attachments. */ - private AxiomSoapMessage createMultiPartAxiomSoapMessage(InputStream inputStream, String contentType) - throws XMLStreamException { + private AxiomSoapMessage createMultiPartAxiomSoapMessage(InputStream inputStream, + String contentType, + String soapAction) throws XMLStreamException { Attachments attachments = new Attachments(inputStream, contentType); if (!(attachments.getAttachmentSpecType().equals(MTOMConstants.SWA_TYPE) || attachments.getAttachmentSpecType().equals(MTOMConstants.MTOM_TYPE))) { @@ -171,7 +179,7 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia else if (attachments.getAttachmentSpecType().equals(MTOMConstants.MTOM_TYPE)) { builder = new MTOMStAXSOAPModelBuilder(reader, attachments, soapFactory.getSoapVersionURI()); } - return new AxiomSoapMessage(builder.getSoapMessage(), attachments, payloadCaching); + return new AxiomSoapMessage(builder.getSoapMessage(), attachments, soapAction, payloadCaching); } private SOAPFactory getSoapFactory(String contentType) { diff --git a/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java b/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java index a3594fa7..24e301ed 100644 --- a/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java +++ b/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java @@ -16,8 +16,6 @@ package org.springframework.ws.soap.endpoint.mapping; -import java.util.Iterator; - import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.ws.EndpointInterceptor; @@ -26,8 +24,7 @@ import org.springframework.ws.context.MessageContext; import org.springframework.ws.endpoint.mapping.AbstractMapBasedEndpointMapping; import org.springframework.ws.soap.SoapEndpointInvocationChain; import org.springframework.ws.soap.SoapEndpointMapping; -import org.springframework.ws.transport.TransportContext; -import org.springframework.ws.transport.TransportContextHolder; +import org.springframework.ws.soap.SoapMessage; /** * Implementation of the EndpointMapping interface to map from SOAPAction headers to endpoint @@ -53,11 +50,6 @@ import org.springframework.ws.transport.TransportContextHolder; */ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping implements SoapEndpointMapping { - /** - * The name of the SOAPAction TransportRequest header. - */ - public static final String SOAP_ACTION_HEADER = "SOAPAction"; - private String[] actorsOrRoles; public final void setActorOrRole(String actorOrRole) { @@ -87,20 +79,19 @@ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping i } protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { - TransportContext transportContext = TransportContextHolder.getTransportContext(); - Assert.notNull(transportContext, - "No TransportContext associated with current thread, cannot read SOAPAction header"); - Iterator iterator = transportContext.getTransportInputStream().getHeaders(SOAP_ACTION_HEADER); - String soapAction = ""; - if (iterator.hasNext()) { - soapAction = (String) iterator.next(); - } - if (StringUtils.hasLength(soapAction) && soapAction.charAt(0) == '"' && - soapAction.charAt(soapAction.length() - 1) == '"') { - return soapAction.substring(1, soapAction.length() - 1); + if (messageContext.getRequest() instanceof SoapMessage) { + SoapMessage request = (SoapMessage) messageContext.getRequest(); + String soapAction = request.getSoapAction(); + if (StringUtils.hasLength(soapAction) && soapAction.charAt(0) == '"' && + soapAction.charAt(soapAction.length() - 1) == '"') { + return soapAction.substring(1, soapAction.length() - 1); + } + else { + return soapAction; + } } else { - return soapAction; + return null; } } 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 76ab0d70..49968513 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 @@ -127,27 +127,37 @@ public class Saaj11Implementation implements SaajImplementation { return fault; } - /** Returns the envelope of the given message. */ + /** + * Returns the envelope of the given message. + */ public SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException { return message.getSOAPPart().getEnvelope(); } - /** Returns the header of the given envelope. */ + /** + * Returns the header of the given envelope. + */ public SOAPHeader getHeader(SOAPEnvelope envelope) throws SOAPException { return envelope.getHeader(); } - /** Returns the body of the given envelope. */ + /** + * Returns the body of the given envelope. + */ public SOAPBody getBody(SOAPEnvelope envelope) throws SOAPException { return envelope.getBody(); } - /** Returns all header elements. */ + /** + * Returns all header elements. + */ public Iterator examineAllHeaderElements(SOAPHeader header) { return header.getChildElements(); } - /** Returns all header elements for which the must understand attribute is true, given the actor or role. */ + /** + * Returns all header elements for which the must understand attribute is true, given the actor or role. + */ public Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String actorOrRole) { List result = new ArrayList(); for (Iterator iterator = header.examineHeaderElements(actorOrRole); iterator.hasNext();) { @@ -159,62 +169,86 @@ public class Saaj11Implementation implements SaajImplementation { return result.iterator(); } - /** Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ + /** + * Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. + */ public String getActorOrRole(SOAPHeaderElement headerElement) { return headerElement.getActor(); } - /** Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ + /** + * Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. + */ public void setActorOrRole(SOAPHeaderElement headerElement, String actorOrRole) { headerElement.setActor(actorOrRole); } - /** Gets the must understand attribute for the given header element. */ + /** + * Gets the must understand attribute for the given header element. + */ public boolean getMustUnderstand(SOAPHeaderElement headerElement) { return headerElement.getMustUnderstand(); } - /** Sets the must understand attribute for the given header element. */ + /** + * Sets the must understand attribute for the given header element. + */ public void setMustUnderstand(SOAPHeaderElement headerElement, boolean mustUnderstand) { headerElement.setMustUnderstand(mustUnderstand); } - /** Returns true if the body has a fault, false otherwise. */ + /** + * Returns true if the body has a fault, false otherwise. + */ public boolean hasFault(SOAPBody body) { return body.hasFault(); } - /** Returns the fault for the given body, if any. */ + /** + * Returns the fault for the given body, if any. + */ public SOAPFault getFault(SOAPBody body) { return body.getFault(); } - /** Returns the actor for the given fault. */ + /** + * Returns the actor for the given fault. + */ public String getFaultActor(SOAPFault fault) { return fault.getFaultActor(); } - /** Sets the actor for the given fault. */ + /** + * Sets the actor for the given fault. + */ public void setFaultActor(SOAPFault fault, String actorOrRole) throws SOAPException { fault.setFaultActor(actorOrRole); } - /** Returns the fault string for the given fault. */ + /** + * Returns the fault string for the given fault. + */ public String getFaultString(SOAPFault fault) { return fault.getFaultString(); } - /** Returns the fault string language for the given fault. */ + /** + * Returns the fault string language for the given fault. + */ public Locale getFaultStringLocale(SOAPFault fault) { return Locale.ENGLISH; } - /** Returns the fault detail for the given fault. */ + /** + * Returns the fault detail for the given fault. + */ public Detail getFaultDetail(SOAPFault fault) { return fault.getDetail(); } - /** Adds a fault detail for the given fault. */ + /** + * Adds a fault detail for the given fault. + */ public Detail addFaultDetail(SOAPFault fault) throws SOAPException { return fault.addDetail(); } @@ -223,7 +257,9 @@ public class Saaj11Implementation implements SaajImplementation { detailEntry.addTextNode(text); } - /** Returns an iteration over all detail entries. */ + /** + * Returns an iteration over all detail entries. + */ public Iterator getDetailEntries(Detail detail) { return detail.getDetailEntries(); } @@ -267,6 +303,10 @@ public class Saaj11Implementation implements SaajImplementation { } + public MimeHeaders getMimeHeaders(SOAPMessage message) { + return message.getMimeHeaders(); + } + public Iterator getAttachments(SOAPMessage message) { return message.getAttachments(); } 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 46897e53..136187ae 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 @@ -217,6 +217,10 @@ public class Saaj12Implementation implements SaajImplementation { } + public MimeHeaders getMimeHeaders(SOAPMessage message) { + return message.getMimeHeaders(); + } + public Iterator getAttachments(SOAPMessage message) { return message.getAttachments(); } 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 72bac3dc..815ba51a 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 @@ -261,6 +261,10 @@ public class Saaj13Implementation implements SaajImplementation { } + public MimeHeaders getMimeHeaders(SOAPMessage message) { + return message.getMimeHeaders(); + } + public Iterator getAttachments(SOAPMessage message) { return message.getAttachments(); } 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 a9dab84e..a8803891 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,128 +45,215 @@ import javax.xml.transform.Source; */ public interface SaajImplementation { - /** Returns the name of the given element. */ + /** + * Returns the name of the given element. + */ QName getName(SOAPElement element); - /** Returns the readable Source of the given element. */ + /** + * Returns the readable Source of the given element. + */ Source getSource(SOAPElement element); - /** Returns the writable Result of the given element. */ + /** + * Returns the writable Result of the given element. + */ Result getResult(SOAPElement element); - /** Returns the envelope of the given message. */ + /** + * Returns the envelope of the given message. + */ SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException; - /** Returns the header of the given envelope. */ + /** + * Returns the header of the given envelope. + */ SOAPHeader getHeader(SOAPEnvelope envelope) throws SOAPException; - /** Returns the body of the given envelope. */ + /** + * Returns the body of the given envelope. + */ SOAPBody getBody(SOAPEnvelope envelope) throws SOAPException; - /** Adds a header element to the given header. */ + /** + * Adds a header element to the given header. + */ SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException; - /** Returns all header elements. */ + /** + * Returns all header elements. + */ Iterator examineAllHeaderElements(SOAPHeader header); - /** Returns all header elements for which the must understand attribute is true, given the actor or role. */ + /** + * Returns all header elements for which the must understand attribute is true, given the actor or role. + */ Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String actorOrRole); - /** Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ + /** + * Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. + */ String getActorOrRole(SOAPHeaderElement headerElement); - /** Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */ + /** + * Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. + */ void setActorOrRole(SOAPHeaderElement headerElement, String actorOrRole); - /** Gets the must understand attribute for the given header element. */ + /** + * Gets the must understand attribute for the given header element. + */ boolean getMustUnderstand(SOAPHeaderElement headerElement); - /** Sets the must understand attribute for the given header element. */ + /** + * Sets the must understand attribute for the given header element. + */ void setMustUnderstand(SOAPHeaderElement headerElement, boolean mustUnderstand); - /** Returns true if the body has a fault, false otherwise. */ + /** + * Returns true if the body has a fault, false otherwise. + */ boolean hasFault(SOAPBody body); - /** Returns the fault for the given body, if any. */ + /** + * Returns the fault for the given body, if any. + */ SOAPFault getFault(SOAPBody body); - /** Adds a fault to the given body. */ + /** + * Adds a fault to the given body. + */ SOAPFault addFault(SOAPBody body, QName faultCode, String faultString, Locale locale) throws SOAPException; - /** Returns the fault code for the given fault. */ + /** + * Returns the fault code for the given fault. + */ QName getFaultCode(SOAPFault fault); - /** Returns the actor for the given fault. */ + /** + * Returns the actor for the given fault. + */ String getFaultActor(SOAPFault fault); - /** Sets the actor for the given fault. */ + /** + * Sets the actor for the given fault. + */ void setFaultActor(SOAPFault fault, String actorOrRole) throws SOAPException; - /** Returns the fault string for the given fault. */ + /** + * Returns the fault string for the given fault. + */ String getFaultString(SOAPFault fault); - /** Returns the fault string language for the given fault. */ + /** + * Returns the fault string language for the given fault. + */ Locale getFaultStringLocale(SOAPFault fault); - /** Adds a detail entry to the given detail. */ + /** + * Adds a detail entry to the given detail. + */ DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException; - /** Returns the fault detail for the given fault. */ + /** + * Returns the fault detail for the given fault. + */ Detail getFaultDetail(SOAPFault fault); - /** Adds a fault detail for the given fault. */ + /** + * Adds a fault detail for the given fault. + */ Detail addFaultDetail(SOAPFault fault) throws SOAPException; void addTextNode(DetailEntry detailEntry, String text) throws SOAPException; - /** Returns an iteration over all detail entries. */ + /** + * Returns an iteration over all detail entries. + */ Iterator getDetailEntries(Detail detail); - /** Returns the first child element of the given body. */ + /** + * Returns the first child element of the given body. + */ SOAPBodyElement getFirstBodyElement(SOAPBody body); - /** Removes the contents (i.e. children) of the element. */ + /** + * Removes the contents (i.e. children) of the element. + */ void removeContents(SOAPElement element); - /** Writes the given message to the given stream. */ + /** + * Writes the given message to the given stream. + */ void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException; - /** Returns an iteration over all attachments in the message. */ + /** + * Returns the MIME headers of the message. + */ + MimeHeaders getMimeHeaders(SOAPMessage message); + + /** + * Returns an iteration over all attachments in the message. + */ Iterator getAttachments(SOAPMessage message); - /** Returns an iteration over all attachments in the message with the given headers. */ + /** + * Returns an iteration over all attachments in the message with the given headers. + */ Iterator getAttachment(SOAPMessage message, MimeHeaders mimeHeaders); - /** Adds an attachment to the given message. */ + /** + * Adds an attachment to the given message. + */ AttachmentPart addAttachmentPart(SOAPMessage message, DataSource dataSource); - /** Adds a not understood header element to the given header. */ + /** + * Adds a not understood header element to the given header. + */ SOAPHeaderElement addNotUnderstoodHeaderElement(SOAPHeader header, QName name) throws SOAPException; - /** Adds a upgrade header element to the given header. */ + /** + * Adds a upgrade header element to the given header. + */ SOAPHeaderElement addUpgradeHeaderElement(SOAPHeader header, String[] supportedSoapUris) throws SOAPException; - /** Returns the fault role. */ + /** + * Returns the fault role. + */ String getFaultRole(SOAPFault fault); - /** Sets the fault role. */ + /** + * Sets the fault role. + */ void setFaultRole(SOAPFault fault, String role) throws SOAPException; - /** Returns the fault sub code. */ + /** + * Returns the fault sub code. + */ Iterator getFaultSubcodes(SOAPFault fault); - /** Adds a fault sub code. */ + /** + * Adds a fault sub code. + */ void appendFaultSubcode(SOAPFault fault, QName subcode) throws SOAPException; - /** Returns the fault node. */ + /** + * Returns the fault node. + */ String getFaultNode(SOAPFault fault); - /** Sets the fault node. */ + /** + * Sets the fault node. + */ void setFaultNode(SOAPFault fault, String uri) throws SOAPException; - /** Returns the fault reason text. */ + /** + * Returns the fault reason text. + */ String getFaultReasonText(SOAPFault fault, Locale locale) throws SOAPException; - /** Sets the fault reason text. */ + /** + * Sets the fault reason text. + */ void setFaultReasonText(SOAPFault fault, Locale locale, String text) throws SOAPException; } diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java index 146255d1..fb42322e 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java @@ -31,6 +31,7 @@ import javax.xml.soap.SOAPMessage; import org.springframework.core.io.InputStreamSource; import org.springframework.core.io.Resource; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.ws.soap.AbstractSoapMessage; import org.springframework.ws.soap.Attachment; import org.springframework.ws.soap.AttachmentException; @@ -46,6 +47,8 @@ import org.springframework.ws.soap.saaj.support.SaajUtils; */ public class SaajSoapMessage extends AbstractSoapMessage { + private static final String SOAP_ACTION_HEADER = "SOAPAction"; + private SOAPMessage saajMessage; private SoapEnvelope envelope; @@ -60,12 +63,16 @@ public class SaajSoapMessage extends AbstractSoapMessage { saajMessage = soapMessage; } - /** Return the SAAJ SOAPMessage that this SaajSoapMessage is based on. */ + /** + * Return the SAAJ SOAPMessage that this SaajSoapMessage is based on. + */ public SOAPMessage getSaajMessage() { return saajMessage; } - /** Sets the SAAJ SOAPMessage that this SaajSoapMessage is based on. */ + /** + * Sets the SAAJ SOAPMessage that this SaajSoapMessage is based on. + */ public void setSaajMessage(SOAPMessage soapMessage) { Assert.notNull(soapMessage, "soapMessage must not be null"); saajMessage = soapMessage; @@ -74,7 +81,7 @@ public class SaajSoapMessage extends AbstractSoapMessage { public SoapEnvelope getEnvelope() { if (envelope == null) { try { - SOAPEnvelope saajEnvelope = getImplementation().getEnvelope(saajMessage); + SOAPEnvelope saajEnvelope = getImplementation().getEnvelope(getSaajMessage()); envelope = new SaajSoapEnvelope(saajEnvelope); } catch (SOAPException ex) { @@ -84,9 +91,20 @@ public class SaajSoapMessage extends AbstractSoapMessage { return envelope; } + public String getSoapAction() { + MimeHeaders mimeHeaders = getImplementation().getMimeHeaders(getSaajMessage()); + String[] values = mimeHeaders.getHeader(SOAP_ACTION_HEADER); + return ObjectUtils.isEmpty(values) ? null : values[0]; + } + + public void setSoapAction(String soapAction) { + MimeHeaders mimeHeaders = getImplementation().getMimeHeaders(getSaajMessage()); + mimeHeaders.setHeader(SOAP_ACTION_HEADER, soapAction); + } + public void writeTo(OutputStream outputStream) throws IOException { try { - getImplementation().writeTo(saajMessage, outputStream); + getImplementation().writeTo(getSaajMessage(), outputStream); } catch (SOAPException ex) { throw new SaajSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex); @@ -94,14 +112,14 @@ public class SaajSoapMessage extends AbstractSoapMessage { } public Iterator getAttachments() throws AttachmentException { - Iterator iterator = getImplementation().getAttachments(saajMessage); + Iterator iterator = getImplementation().getAttachments(getSaajMessage()); return new SaajAttachmentIterator(iterator); } public Attachment getAttachment(String contentId) { MimeHeaders mimeHeaders = new MimeHeaders(); mimeHeaders.addHeader("Content-Id", contentId); - Iterator iterator = getImplementation().getAttachment(saajMessage, mimeHeaders); + Iterator iterator = getImplementation().getAttachment(getSaajMessage(), mimeHeaders); if (!iterator.hasNext()) { return null; } @@ -114,7 +132,7 @@ public class SaajSoapMessage extends AbstractSoapMessage { public Attachment addAttachment(File file) throws AttachmentException { Assert.notNull(file, "File must not be null"); DataSource dataSource = new FileDataSource(file); - AttachmentPart attachmentPart = getImplementation().addAttachmentPart(saajMessage, dataSource); + AttachmentPart attachmentPart = getImplementation().addAttachmentPart(getSaajMessage(), dataSource); return new SaajAttachment(attachmentPart); } @@ -125,7 +143,7 @@ public class SaajSoapMessage extends AbstractSoapMessage { "SAAJ requires an InputStreamSource that creates a fresh stream for every call."); } DataSource dataSource = new InputStreamSourceDataSource(inputStreamSource, contentType); - AttachmentPart saajAttachment = getImplementation().addAttachmentPart(saajMessage, dataSource); + AttachmentPart saajAttachment = getImplementation().addAttachmentPart(getSaajMessage(), dataSource); return new SaajAttachment(saajAttachment); } diff --git a/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageTestCase.java b/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageTestCase.java index 7702b1e2..57182a31 100644 --- a/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageTestCase.java @@ -76,6 +76,12 @@ public abstract class AbstractSoapMessageTestCase extends AbstractWebServiceMess } } + public void testSoapAction() throws Exception { + String soapAction = "SoapAction"; + soapMessage.setSoapAction(soapAction); + assertEquals("Invalid SOAP Action", soapAction, soapMessage.getSoapAction()); + } + protected abstract Resource[] getSoapSchemas(); diff --git a/core/src/test/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMappingTest.java b/core/src/test/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMappingTest.java index 54aa73a9..2153615b 100644 --- a/core/src/test/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMappingTest.java +++ b/core/src/test/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMappingTest.java @@ -16,22 +16,13 @@ package org.springframework.ws.soap.endpoint.mapping; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.HashMap; -import java.util.Map; +import javax.xml.soap.MessageFactory; import junit.framework.TestCase; -import org.springframework.ws.MockWebServiceMessageFactory; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; -import org.springframework.ws.transport.DefaultTransportContext; -import org.springframework.ws.transport.StubTransportInputStream; -import org.springframework.ws.transport.StubTransportOutputStream; -import org.springframework.ws.transport.TransportContext; -import org.springframework.ws.transport.TransportContextHolder; -import org.springframework.ws.transport.TransportInputStream; -import org.springframework.ws.transport.TransportOutputStream; +import org.springframework.ws.soap.SoapMessage; +import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; public class SoapActionEndpointMappingTest extends TestCase { @@ -39,31 +30,20 @@ public class SoapActionEndpointMappingTest extends TestCase { private MessageContext context; - private Map headers; - protected void setUp() throws Exception { - headers = new HashMap(); - TransportInputStream tis = new StubTransportInputStream(new ByteArrayInputStream(new byte[0]), headers); - TransportOutputStream tos = new StubTransportOutputStream(new ByteArrayOutputStream()); - TransportContext transportContext = new DefaultTransportContext(tis, tos); - TransportContextHolder.setTransportContext(transportContext); mapping = new SoapActionEndpointMapping(); - context = new DefaultMessageContext(new MockWebServiceMessageFactory()); - } - - protected void tearDown() throws Exception { - TransportContextHolder.setTransportContext(null); + context = new DefaultMessageContext(new SaajSoapMessageFactory(MessageFactory.newInstance())); } public void testGetLookupKeyForMessage() throws Exception { String soapAction = "http://springframework.org/spring-ws/SoapAction"; - headers.put(SoapActionEndpointMapping.SOAP_ACTION_HEADER, soapAction); + ((SoapMessage) context.getRequest()).setSoapAction(soapAction); assertEquals("Invalid lookup key", soapAction, mapping.getLookupKeyForMessage(context)); } public void testGetLookupKeyForMessageQuoted() throws Exception { String soapAction = "http://springframework.org/spring-ws/SoapAction"; - headers.put(SoapActionEndpointMapping.SOAP_ACTION_HEADER, "\"" + soapAction + "\""); + ((SoapMessage) context.getRequest()).setSoapAction(soapAction); assertEquals("Invalid lookup key", soapAction, mapping.getLookupKeyForMessage(context)); } diff --git a/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java b/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java index 75450f7b..ed274aaa 100644 --- a/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java @@ -40,12 +40,15 @@ public abstract class AbstractSoap11MessageFactoryTestCase extends AbstractSoapM InputStream is = AbstractSoap11MessageFactoryTestCase.class.getResourceAsStream("soap11.xml"); final Properties headers = new Properties(); headers.setProperty("Content-Type", "text/xml"); + String soapAction = "http://springframework.org/spring-ws/Action"; + headers.setProperty("SOAPAction", soapAction); TransportInputStream tis = new StubTransportInputStream(is, headers); WebServiceMessage message = messageFactory.createWebServiceMessage(tis); assertTrue("Not a SoapMessage", message instanceof SoapMessage); SoapMessage soapMessage = (SoapMessage) message; assertEquals("Invalid soap version", SoapVersion.SOAP_11, soapMessage.getVersion()); + assertEquals("Invalid soap action", soapAction, soapMessage.getSoapAction()); } public void testCreateSoapMessageAttachment() throws Exception {