diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AddressingHelper.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractVersionBasedWsAddressingInterceptor.java
similarity index 76%
rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/AddressingHelper.java
rename to sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractVersionBasedWsAddressingInterceptor.java
index 654e6bf6..bb05aa45 100644
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AddressingHelper.java
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractVersionBasedWsAddressingInterceptor.java
@@ -35,37 +35,45 @@ import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.soap11.Soap11Body;
import org.springframework.ws.soap.soap12.Soap12Body;
import org.springframework.ws.soap.soap12.Soap12Fault;
-import org.springframework.xml.transform.TransformerObjectSupport;
import org.springframework.xml.xpath.XPathExpression;
import org.springframework.xml.xpath.XPathExpressionFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
-/** @author Arjen Poutsma */
-class AddressingHelper extends TransformerObjectSupport {
+/**
+ * Abstract extension of the {@link AbstractWsAddressingInterceptor} that uses a {@link WsAddressingVersion}.
+ *
+ * @author Arjen Poutsma
+ * @since 1.1.0
+ */
+abstract class AbstractVersionBasedWsAddressingInterceptor extends AbstractWsAddressingInterceptor {
private final WsAddressingVersion version;
private final XPathExpression toExpression;
- private XPathExpression actionExpression;
+ private final XPathExpression actionExpression;
- private XPathExpression messageIdExpression;
+ private final XPathExpression messageIdExpression;
- private XPathExpression fromExpression;
+ private final XPathExpression fromExpression;
- private XPathExpression replyToExpression;
+ private final XPathExpression replyToExpression;
- private XPathExpression faultToExpression;
+ private final XPathExpression faultToExpression;
- private XPathExpression addressExpression;
+ private final XPathExpression addressExpression;
private XPathExpression referencePropertiesExpression;
private XPathExpression referenceParametersExpression;
- public AddressingHelper(WsAddressingVersion version) {
+ /**
+ * Creates a new instance of the {@link AbstractVersionBasedWsAddressingInterceptor} with the given {@link
+ * WsAddressingVersion}.
+ */
+ protected AbstractVersionBasedWsAddressingInterceptor(WsAddressingVersion version) {
this.version = version;
Properties namespaces = new Properties();
namespaces.setProperty(version.getNamespacePrefix(), version.getNamespaceUri());
@@ -99,89 +107,13 @@ class AddressingHelper extends TransformerObjectSupport {
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
}
- public MessageAddressingProperties getMessageAddressingProperties(SoapMessage message) throws TransformerException {
- Element headerElement = getSoapHeaderElement(message);
- String to = toExpression.evaluateAsString(headerElement);
- EndpointReference from = getEndpointReference(fromExpression.evaluateAsNode(headerElement));
- EndpointReference replyTo = getEndpointReference(replyToExpression.evaluateAsNode(headerElement));
- EndpointReference faultTo = getEndpointReference(faultToExpression.evaluateAsNode(headerElement));
- String action = actionExpression.evaluateAsString(headerElement);
- String messageId = messageIdExpression.evaluateAsString(headerElement);
- return new MessageAddressingProperties(to, from, replyTo, faultTo, action, messageId);
+ public boolean understands(SoapHeaderElement header) {
+ return version.getNamespaceUri().equals(header.getName().getNamespaceURI());
}
- /** Given a ReplyTo, FaultTo, or From node, returns an endpoint reference. */
- private EndpointReference getEndpointReference(Node node) {
- if (node == null) {
- return null;
- }
- String address = addressExpression.evaluateAsString(node);
- if (!StringUtils.hasLength(address)) {
- return null;
- }
- List referenceProperties = referencePropertiesExpression != null ?
- referencePropertiesExpression.evaluateAsNodeList(node) : Collections.EMPTY_LIST;
- List referenceParameters = referenceParametersExpression != null ?
- referenceParametersExpression.evaluateAsNodeList(node) : Collections.EMPTY_LIST;
- return new EndpointReference(address, referenceProperties, referenceParameters);
- }
-
- public SoapFault addMessageHeaderRequiredFault(SoapMessage message) {
- return addAddressingFault(message, version.getMessageHeaderRequiredName(),
- version.getMessageHeaderRequiredText());
- }
-
- public SoapFault addDestinationUnreachableFault(SoapMessage message) {
- return addAddressingFault(message, version.getDestinationUnreachableName(),
- version.getDestinationUnreachableText());
- }
-
- public SoapFault addActionNotSupportedFault(SoapMessage message, String action) {
- return addAddressingFault(message, version.getActionNotSupportedName(),
- version.getActionNotSupportedText(action));
- }
-
- private SoapFault addAddressingFault(SoapMessage message, QName subcode, String reason) {
- if (message.getSoapBody() instanceof Soap11Body) {
- Soap11Body soapBody = (Soap11Body) message.getSoapBody();
- return soapBody.addFault(subcode, reason, Locale.ENGLISH);
- }
- else {
- Soap12Body soapBody = (Soap12Body) message.getSoapBody();
- Soap12Fault soapFault = (Soap12Fault) soapBody.addClientOrSenderFault(reason, Locale.ENGLISH);
- soapFault.addFaultSubcode(subcode);
- return soapFault;
- }
- }
-
- private Element getSoapHeaderElement(SoapMessage message) throws TransformerException {
- SoapHeader header = message.getSoapHeader();
- if (header.getSource() instanceof DOMSource) {
- DOMSource domSource = (DOMSource) header.getSource();
- if (domSource.getNode() != null && domSource.getNode().getNodeType() == Node.ELEMENT_NODE) {
- return (Element) domSource.getNode();
- }
- }
- Transformer transformer = createTransformer();
- DOMResult domResult = new DOMResult();
- transformer.transform(message.getSoapHeader().getSource(), domResult);
- Document document = (Document) domResult.getNode();
- return document.getDocumentElement();
- }
-
- public boolean hasNoneAddress(EndpointReference reference) {
- String none = version.getNoneUri();
- return none != null && none.equals(reference.getAddress());
- }
-
- public boolean hasAnonymousAddress(EndpointReference reference) {
- String anonymous = version.getAnonymousUri();
- return anonymous != null && anonymous.equals(reference.getAddress());
- }
-
- public void addAddressingHeaders(SoapMessage response, MessageAddressingProperties map)
+ protected void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map)
throws TransformerException {
- SoapHeader header = response.getSoapHeader();
+ SoapHeader header = message.getSoapHeader();
SoapHeaderElement messageId = header.addHeaderElement(version.getMessageIdName());
messageId.setText(map.getMessageId());
SoapHeaderElement relatesTo = header.addHeaderElement(version.getRelatesToName());
@@ -202,6 +134,101 @@ class AddressingHelper extends TransformerObjectSupport {
}
}
+ /**
+ * Adds a Message Addressing Header Required fault to the given message.
+ *
+ * @see Message Addressing Header Required
+ */
+ protected SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message) {
+ return addAddressingFault(message, version.getMessageAddressingHeaderRequiredFaultSubcode(),
+ version.getMessageAddressingHeaderRequiredFaultReason());
+ }
+
+ private SoapFault addAddressingFault(SoapMessage message, QName subcode, String reason) {
+ if (message.getSoapBody() instanceof Soap11Body) {
+ Soap11Body soapBody = (Soap11Body) message.getSoapBody();
+ return soapBody.addFault(subcode, reason, Locale.ENGLISH);
+ }
+ else if (message.getSoapBody() instanceof Soap12Body) {
+ Soap12Body soapBody = (Soap12Body) message.getSoapBody();
+ Soap12Fault soapFault = (Soap12Fault) soapBody.addClientOrSenderFault(reason, Locale.ENGLISH);
+ soapFault.addFaultSubcode(subcode);
+ return soapFault;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the {@link MessageAddressingProperties} for the given message.
+ *
+ * @param message the message to find the map for
+ * @return the message addressing properties
+ */
+ protected MessageAddressingProperties getMessageAddressingProperties(SoapMessage message)
+ throws TransformerException {
+ Element headerElement = getSoapHeaderElement(message);
+ String to = toExpression.evaluateAsString(headerElement);
+ EndpointReference from = getEndpointReference(fromExpression.evaluateAsNode(headerElement));
+ EndpointReference replyTo = getEndpointReference(replyToExpression.evaluateAsNode(headerElement));
+ EndpointReference faultTo = getEndpointReference(faultToExpression.evaluateAsNode(headerElement));
+ String action = actionExpression.evaluateAsString(headerElement);
+ String messageId = messageIdExpression.evaluateAsString(headerElement);
+ return new MessageAddressingProperties(to, from, replyTo, faultTo, action, messageId);
+ }
+
+ private Element getSoapHeaderElement(SoapMessage message) throws TransformerException {
+ SoapHeader header = message.getSoapHeader();
+ if (header.getSource() instanceof DOMSource) {
+ DOMSource domSource = (DOMSource) header.getSource();
+ if (domSource.getNode() != null && domSource.getNode().getNodeType() == Node.ELEMENT_NODE) {
+ return (Element) domSource.getNode();
+ }
+ }
+ Transformer transformer = createTransformer();
+ DOMResult domResult = new DOMResult();
+ transformer.transform(message.getSoapHeader().getSource(), domResult);
+ Document document = (Document) domResult.getNode();
+ return document.getDocumentElement();
+ }
+
+ /** Given a ReplyTo, FaultTo, or From node, returns an endpoint reference. */
+ private EndpointReference getEndpointReference(Node node) {
+ if (node == null) {
+ return null;
+ }
+ String address = addressExpression.evaluateAsString(node);
+ if (!StringUtils.hasLength(address)) {
+ return null;
+ }
+ List referenceProperties = referencePropertiesExpression != null ?
+ referencePropertiesExpression.evaluateAsNodeList(node) : Collections.EMPTY_LIST;
+ List referenceParameters = referenceParametersExpression != null ?
+ referenceParametersExpression.evaluateAsNodeList(node) : Collections.EMPTY_LIST;
+ return new EndpointReference(address, referenceProperties, referenceParameters);
+ }
+
+ /**
+ * Indicates whether the given endpoint reference has a Anonymous address. This address is used to indicate that a
+ * message should be sent in-band.
+ *
+ * @see Formulating a Reply Message
+ */
+ protected boolean hasAnonymousAddress(EndpointReference epr) {
+ String anonymous = version.getAnonymousUri();
+ return anonymous != null && anonymous.equals(epr.getAddress());
+ }
+
+ /**
+ * Indicates whether the given endpoint reference has a None address. Messages to be sent to this address will not
+ * be sent.
+ *
+ * @see Sending a Message to an EPR
+ */
+ protected boolean hasNoneAddress(EndpointReference epr) {
+ String none = version.getNoneUri();
+ return none != null && none.equals(epr.getAddress());
+ }
+
public boolean supports(SoapMessage message) {
SoapHeader header = message.getSoapHeader();
if (header != null) {
@@ -213,10 +240,5 @@ class AddressingHelper extends TransformerObjectSupport {
}
}
return false;
-
}
-
- public boolean understands(SoapHeaderElement header) {
- return version.getNamespaceUri().equals(header.getName().getNamespaceURI());
- }
-}
+}
\ No newline at end of file
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptor.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptor.java
new file mode 100644
index 00000000..01d3daa4
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptor.java
@@ -0,0 +1,142 @@
+package org.springframework.ws.soap.addressing;
+
+import java.io.IOException;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.util.Assert;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.soap.SoapFault;
+import org.springframework.ws.soap.SoapMessage;
+import org.springframework.ws.soap.addressing.messageid.MessageIdProvider;
+import org.springframework.ws.soap.server.SoapEndpointInterceptor;
+import org.springframework.ws.transport.WebServiceConnection;
+import org.springframework.ws.transport.WebServiceMessageSender;
+import org.springframework.xml.transform.TransformerObjectSupport;
+
+/** @author Arjen Poutsma */
+public abstract class AbstractWsAddressingInterceptor extends TransformerObjectSupport
+ implements SoapEndpointInterceptor {
+
+ /** Logger available for subclasses. */
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private MessageIdProvider messageIdProvider;
+
+ private WebServiceMessageSender[] messageSenders = new WebServiceMessageSender[0];
+
+ public final void setMessageIdProvider(MessageIdProvider messageIdProvider) {
+ this.messageIdProvider = messageIdProvider;
+ }
+
+ public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
+ Assert.isTrue(messageContext.getRequest() instanceof SoapMessage,
+ "WsAddressingInterceptor requires a SoapMessage request");
+ SoapMessage request = (SoapMessage) messageContext.getRequest();
+ MessageAddressingProperties requestMap = getMessageAddressingProperties(request);
+ if (!requestMap.isValid()) {
+ addMessageAddressingHeaderRequiredFault((SoapMessage) messageContext.getResponse());
+ return false;
+ }
+ return true;
+ }
+
+ public final boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
+ return handleResponseOrFault(messageContext);
+ }
+
+ public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
+ return handleResponseOrFault(messageContext);
+ }
+
+ /**
+ * Adds a Message Addressing Header Required fault to the given message.
+ *
+ * @see Message Addressing Header Required
+ */
+ protected abstract SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message);
+
+ private boolean handleResponseOrFault(MessageContext messageContext) throws Exception {
+ Assert.isTrue(messageContext.getRequest() instanceof SoapMessage &&
+ messageContext.getResponse() instanceof SoapMessage,
+ "WsAddressingInterceptor requires a SoapMessage request and response");
+ SoapMessage request = (SoapMessage) messageContext.getRequest();
+ MessageAddressingProperties requestMap = getMessageAddressingProperties(request);
+ SoapMessage response = (SoapMessage) messageContext.getResponse();
+ EndpointReference responseEpr = response.hasFault() ? requestMap.getFaultTo() : requestMap.getReplyTo();
+ if (responseEpr == null || hasNoneAddress(responseEpr)) {
+ logger.debug("Request has none reply address");
+ return false;
+ }
+ String responseMessageId = messageIdProvider.getMessageId(response);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Generated reply MessageID [" + responseMessageId + "]");
+ }
+ MessageAddressingProperties replyMap = requestMap.getResponseProperties(responseEpr, null, responseMessageId);
+ addAddressingHeaders(response, replyMap);
+ if (hasAnonymousAddress(responseEpr)) {
+ logger.debug("Request has anonymous reply address");
+ return true;
+ }
+ else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Sending reply message to EPR address [" + responseEpr.getAddress() + "]");
+ }
+ sendOutOfBand(responseEpr.getAddress(), response);
+ return false;
+ }
+ }
+
+ private void sendOutOfBand(String uri, SoapMessage message) throws IOException {
+ boolean supported = false;
+ for (int i = 0; i < messageSenders.length; i++) {
+ if (messageSenders[i].supports(uri)) {
+ supported = true;
+ WebServiceConnection connection = null;
+ try {
+ connection = messageSenders[i].createConnection(uri);
+ connection.send(message);
+ break;
+ }
+ finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+ }
+ if (!supported) {
+ throw new IllegalArgumentException("Could not resolve [" + uri + "] to a WebServiceMessageSender");
+ }
+ }
+
+ /**
+ * Returns the {@link MessageAddressingProperties} for the given message.
+ *
+ * @param message the message to find the map for
+ * @return the message addressing properties
+ */
+ protected abstract MessageAddressingProperties getMessageAddressingProperties(SoapMessage message)
+ throws TransformerException;
+
+ /**
+ * Indicates whether the given endpoint reference has a None address. Messages to be sent to this address will not
+ * be sent.
+ *
+ * @see Sending a Message to an EPR
+ */
+ protected abstract boolean hasNoneAddress(EndpointReference epr);
+
+ /**
+ * Indicates whether the given endpoint reference has a Anonymous address. This address is used to indicate that a
+ * message should be sent in-band.
+ *
+ * @see Formulating a Reply Message
+ */
+ protected abstract boolean hasAnonymousAddress(EndpointReference epr);
+
+ protected abstract void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map)
+ throws TransformerException;
+
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java
index e8345264..337d6115 100644
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java
@@ -16,6 +16,7 @@
package org.springframework.ws.soap.addressing;
+import java.util.Iterator;
import javax.xml.transform.TransformerException;
import org.springframework.core.JdkVersion;
@@ -23,6 +24,9 @@ import org.springframework.util.Assert;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.server.EndpointInvocationChain;
+import org.springframework.ws.server.EndpointMapping;
+import org.springframework.ws.soap.SoapHeader;
+import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.addressing.messageid.MessageIdProvider;
import org.springframework.ws.soap.addressing.messageid.UidMessageIdProvider;
@@ -32,7 +36,10 @@ import org.springframework.ws.soap.server.SoapEndpointMapping;
import org.springframework.xml.transform.TransformerObjectSupport;
/**
+ * Abstract base class for {@link EndpointMapping} implementations that implement WS-Addressing.
+ *
* @author Arjen Poutsma
+ * @since 1.1.0
*/
public abstract class AbstractWsAddressingMapping extends TransformerObjectSupport implements SoapEndpointMapping {
@@ -42,18 +49,16 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
private MessageIdProvider messageIdProvider;
- private AddressingHelper[] helpers = new AddressingHelper[]{new AddressingHelper(new WsAddressing200408())};
+ private AbstractWsAddressingInterceptor[] addressingInterceptors;
private EndpointInterceptor[] preInterceptors;
private EndpointInterceptor[] postInterceptors;
- private static final Object MISSING_HEADER_ENDPOINT = new Object();
-
- /**
- * Protected constructor
- */
+ /** Protected constructor */
protected AbstractWsAddressingMapping() {
+ addressingInterceptors = new AbstractWsAddressingInterceptor[]{new WsAddressing200408Interceptor(),
+ new WsAddressing200508Interceptor()};
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
messageIdProvider = new UuidMessageIdProvider();
}
@@ -77,47 +82,100 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
}
/**
- * Sets the message id provider used for creating WS-Addressing MessageIds. By default, the {@link
- * UuidMessageIdProvider} is used on Java 5 and higher, and the {@link UidMessageIdProvider} on Java 1.4 and lower.
+ * Set additional interceptors to be applied before the implicit WS-Addressing interceptor, e.g.
+ * XwsSecurityInterceptor.
+ */
+ public final void setPreInterceptors(EndpointInterceptor[] preInterceptors) {
+ this.preInterceptors = preInterceptors;
+ }
+
+ /**
+ * Set additional interceptors to be applied after the implicit WS-Addressing interceptor, e.g.
+ * PayloadLoggingInterceptor.
+ */
+ public final void setPostInterceptors(EndpointInterceptor[] postInterceptors) {
+ this.postInterceptors = postInterceptors;
+ }
+
+ /**
+ * Sets the message id provider used for creating WS-Addressing MessageIds.
+ *
null if no specific
+ * one is found. This template method is called by {@link #getEndpoint(MessageContext)}.
+ *
+ * @param map the message addressing properties
+ * @return the endpoint, or null
+ */
protected abstract Object getEndpointInternal(MessageAddressingProperties map);
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingVersion.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingVersion.java
new file mode 100644
index 00000000..6d90881c
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingVersion.java
@@ -0,0 +1,72 @@
+package org.springframework.ws.soap.addressing;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Abstract implementation of the {@link WsAddressingVersion} interface.
+ *
+ * @author Arjen Poutsma
+ */
+public abstract class AbstractWsAddressingVersion implements WsAddressingVersion {
+
+ public String getNamespacePrefix() {
+ return "wsa";
+ }
+
+ /*
+ * Message addressing properties
+ */
+
+ public QName getToName() {
+ return new QName(getNamespaceUri(), "To", getNamespacePrefix());
+ }
+
+ public QName getFromName() {
+ return new QName(getNamespaceUri(), "From", getNamespacePrefix());
+ }
+
+ public QName getReplyToName() {
+ return new QName(getNamespaceUri(), "ReplyTo", getNamespacePrefix());
+ }
+
+ public QName getFaultToName() {
+ return new QName(getNamespaceUri(), "FaultTo", getNamespacePrefix());
+ }
+
+ public QName getActionName() {
+ return new QName(getNamespaceUri(), "Action", getNamespacePrefix());
+ }
+
+ public QName getMessageIdName() {
+ return new QName(getNamespaceUri(), "MessageID", getNamespacePrefix());
+ }
+
+ public QName getRelatesToName() {
+ return new QName(getNamespaceUri(), "RelatesTo", getNamespacePrefix());
+ }
+
+ public QName getRelationshipTypeName() {
+ return new QName(getNamespaceUri(), "RelationshipType", getNamespacePrefix());
+ }
+
+ public QName getReferencePropertiesName() {
+ return new QName(getNamespaceUri(), "ReferenceProperties", getNamespacePrefix());
+ }
+
+ public QName getReferenceParametersName() {
+ return new QName(getNamespaceUri(), "ReferenceParameters", getNamespacePrefix());
+ }
+
+ /*
+ * Endpoint Reference
+ */
+
+ public QName getAddressName() {
+ return new QName(getNamespaceUri(), "Address", getNamespacePrefix());
+ }
+
+ public QName getMetadataName() {
+ return new QName(getNamespaceUri(), "Metadata", getNamespacePrefix());
+ }
+
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java
index c409133b..be18e9bf 100644
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java
@@ -20,9 +20,18 @@ import java.util.Collections;
import java.util.List;
import org.springframework.util.Assert;
+import org.w3c.dom.Node;
-/** @author Arjen Poutsma */
-public class EndpointReference {
+/**
+ * Represents a set of Message Addressing Properties, as defined in the WS-Addressing specification.
+ *
+ * In earlier versions of the spec, these properties were called Message Information Headers.
+ *
+ * @author Arjen Poutsma
+ * @see Endpoint References
+ * @since 1.1.0
+ */
+public final class EndpointReference {
private final String address;
@@ -30,12 +39,26 @@ public class EndpointReference {
private final List referenceParameters;
+ /**
+ * Creates a new instance of the {@link EndpointReference} class with the given address. The reference parameters
+ * and properties are empty.
+ *
+ * @param address the endpoint address
+ */
public EndpointReference(String address) {
this.address = address;
this.referenceParameters = Collections.EMPTY_LIST;
this.referenceProperties = Collections.EMPTY_LIST;
}
+ /**
+ * Creates a new instance of the {@link EndpointReference} class with the given address, reference properties, and
+ * reference paramters.
+ *
+ * @param address the endpoint address
+ * @param referenceProperties the reference properties, as a list of {@link Node}
+ * @param referenceProperties the reference parameters, as a list of {@link Node}
+ */
public EndpointReference(String address, List referenceProperties, List referenceParameters) {
Assert.notNull(address, "address must not be null");
Assert.notNull(referenceProperties, "referenceProperties must not be null");
@@ -45,14 +68,17 @@ public class EndpointReference {
this.referenceParameters = referenceParameters;
}
+ /** Returns the address of the endpoint. */
public String getAddress() {
return address;
}
+ /** Returns the reference properties of the endpoint, as a list of {@link Node} objects. */
public List getReferenceProperties() {
return referenceProperties;
}
+ /** Returns the reference parameters of the endpoint, as a list of {@link Node} objects. */
public List getReferenceParameters() {
return referenceParameters;
}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java
index e6d45488..ee281281 100644
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java
@@ -28,8 +28,9 @@ import org.springframework.util.StringUtils;
*
* @author Arjen Poutsma
* @see Message Addressing Properties
+ * @since 1.1.0
*/
-public class MessageAddressingProperties {
+public final class MessageAddressingProperties {
private final String to;
@@ -49,6 +50,7 @@ public class MessageAddressingProperties {
private final List referenceParameters;
+/*
public MessageAddressingProperties(String to, EndpointReference replyTo, String action, String messageId) {
this.to = to;
this.replyTo = replyTo;
@@ -60,6 +62,7 @@ public class MessageAddressingProperties {
this.referenceProperties = Collections.EMPTY_LIST;
this.referenceParameters = Collections.EMPTY_LIST;
}
+*/
public MessageAddressingProperties(String to,
EndpointReference from,
@@ -78,12 +81,13 @@ public class MessageAddressingProperties {
this.referenceParameters = Collections.EMPTY_LIST;
}
+/*
private MessageAddressingProperties(String to,
- String action,
- String messageId,
- String relatesTo,
- List referenceProperties,
- List referenceParameters) {
+ String action,
+ String messageId,
+ String relatesTo,
+ List referenceProperties,
+ List referenceParameters) {
this.to = to;
this.action = action;
this.messageId = messageId;
@@ -94,6 +98,19 @@ public class MessageAddressingProperties {
this.replyTo = null;
this.faultTo = null;
}
+*/
+
+ private MessageAddressingProperties(EndpointReference epr, String action, String messageId, String relatesTo) {
+ this.to = epr.getAddress();
+ this.action = action;
+ this.messageId = messageId;
+ this.relatesTo = relatesTo;
+ this.referenceParameters = epr.getReferenceParameters();
+ this.referenceProperties = epr.getReferenceProperties();
+ this.from = null;
+ this.replyTo = null;
+ this.faultTo = null;
+ }
public String getTo() {
return to;
@@ -124,13 +141,17 @@ public class MessageAddressingProperties {
}
public List getReferenceProperties() {
- return referenceProperties;
+ return Collections.unmodifiableList(referenceProperties);
}
public List getReferenceParameters() {
- return referenceParameters;
+ return Collections.unmodifiableList(referenceParameters);
}
+ /**
+ * Indicates whether the given {@link MessageAddressingProperties} are valid, i.e. whether all required elements are
+ * listed.
+ */
public boolean isValid() {
return StringUtils.hasLength(to) && StringUtils.hasLength(action) &&
!(replyTo != null && !StringUtils.hasLength(messageId)) &&
@@ -138,8 +159,8 @@ public class MessageAddressingProperties {
}
- public MessageAddressingProperties getReplyProperties(EndpointReference epr, String action, String messageId) {
- return new MessageAddressingProperties(epr.getAddress(), action, messageId, this.messageId,
- epr.getReferenceProperties(), epr.getReferenceParameters());
+ public MessageAddressingProperties getResponseProperties(EndpointReference epr, String action, String messageId) {
+ return new MessageAddressingProperties(epr, action, messageId, this.messageId);
}
+
}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/StatefulAddressingInterceptor.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/StatefulAddressingInterceptor.java
deleted file mode 100644
index 7a231fe5..00000000
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/StatefulAddressingInterceptor.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2007 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.addressing;
-
-import javax.xml.transform.TransformerException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.soap.SoapHeaderElement;
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.addressing.messageid.MessageIdProvider;
-import org.springframework.ws.soap.server.SoapEndpointInterceptor;
-
-/** @author Arjen Poutsma */
-class StatefulAddressingInterceptor implements SoapEndpointInterceptor {
-
- private static final Log logger = LogFactory.getLog(StatefulAddressingInterceptor.class);
-
- private final AddressingHelper helper;
-
- private final MessageIdProvider messageIdProvider;
-
- private final MessageAddressingProperties requestMap;
-
- public StatefulAddressingInterceptor(AddressingHelper helper,
- MessageIdProvider messageIdProvider,
- MessageAddressingProperties map) {
- this.helper = helper;
- this.messageIdProvider = messageIdProvider;
- this.requestMap = map;
- }
-
- public boolean understands(SoapHeaderElement header) {
- return helper.understands(header);
- }
-
- public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
- if (!requestMap.isValid()) {
- helper.addMessageHeaderRequiredFault((SoapMessage) messageContext.getResponse());
- return false;
- }
- return true;
- }
-
- public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
- SoapMessage response = (SoapMessage) messageContext.getResponse();
- return handleReturnMessage(response, requestMap.getReplyTo());
- }
-
- public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
- SoapMessage response = (SoapMessage) messageContext.getResponse();
- return handleReturnMessage(response, requestMap.getFaultTo());
- }
-
- private boolean handleReturnMessage(SoapMessage response, EndpointReference epr) throws TransformerException {
- if (epr == null || helper.hasNoneAddress(epr)) {
- logger.debug("Request has no response address");
- return false;
- }
- String replyMessageId = messageIdProvider.getMessageId(response);
- if (logger.isDebugEnabled()) {
- logger.debug("Generated response MessageID [" + replyMessageId + "]");
- }
- MessageAddressingProperties replyMap = requestMap.getReplyProperties(epr, null, replyMessageId);
- helper.addAddressingHeaders(response, replyMap);
- if (helper.hasAnonymousAddress(epr)) {
- logger.debug("Request has anonymous response address");
- return true;
- }
- else {
- if (logger.isDebugEnabled()) {
- logger.debug("Sending response message to EPR address [" + epr.getAddress() + "]");
- }
- // TODO: send the message
- throw new UnsupportedOperationException("Sending to out-of-band EPR not supported");
- }
- }
-
-
-}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408.java
deleted file mode 100644
index 17955066..00000000
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2007 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.addressing;
-
-import javax.xml.namespace.QName;
-
-/**
- * Implements the August 2004 edition of the WS-Addressing specification. This version of the specification is used by
- * Microsoft's Web Services Enhancements (WSE) 3.0.
- *
- * @author Arjen Poutsma
- * @see Web Services Addressing, August 2004
- * @see Web Services Enhancements
- */
-public class WsAddressing200408 implements WsAddressingVersion {
-
- private static final String NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
-
- private static final String NAMESPACE_PREFIX = "wsa";
-
- private static final QName TO = new QName(NAMESPACE_URI, "To", NAMESPACE_PREFIX);
-
- private static final QName REPLY_TO = new QName(NAMESPACE_URI, "ReplyTo", NAMESPACE_PREFIX);
-
- private static final QName FROM = new QName(NAMESPACE_URI, "From", NAMESPACE_PREFIX);
-
- private static final QName FAULT_TO = new QName(NAMESPACE_URI, "FaultTo", NAMESPACE_PREFIX);
-
- private static final QName ACTION = new QName(NAMESPACE_URI, "Action", NAMESPACE_PREFIX);
-
- private static final QName MESSAGE_ID = new QName(NAMESPACE_URI, "MessageID", NAMESPACE_PREFIX);
-
- private static final QName RELATES_TO = new QName(NAMESPACE_URI, "RelatesTo", NAMESPACE_PREFIX);
-
- private static final QName RELATIONSHIP_REPLY = new QName(NAMESPACE_URI, "Reply", NAMESPACE_PREFIX);
-
- private static final QName RELATIONSHIP_TYPE = new QName(NAMESPACE_URI, "RelationshipType", NAMESPACE_PREFIX);
-
- private static final QName MESSAGE_INFORMATION_HEADER_REQUIRED =
- new QName(NAMESPACE_URI, "MessageInformationHeaderRequired", NAMESPACE_PREFIX);
-
- private static final QName DESTINATION_UNREACHABLE =
- new QName(NAMESPACE_URI, "DestinationUnreachable", NAMESPACE_PREFIX);
-
- private static final QName ACTION_NOT_SUPPORTED_NAME =
- new QName(NAMESPACE_URI, "ActionNotSupported", NAMESPACE_PREFIX);
-
- private static final QName ADDRESS = new QName(NAMESPACE_URI, "Address", NAMESPACE_PREFIX);
-
- private static final QName REFERENCE_PARAMETERS = new QName(NAMESPACE_URI, "ReferenceParameters", NAMESPACE_PREFIX);
-
- private static final QName REFERENCE_PROPERTIES = new QName(NAMESPACE_URI, "ReferenceProperties", NAMESPACE_PREFIX);
-
- public String getNamespaceUri() {
- return NAMESPACE_URI;
- }
-
- public String getNamespacePrefix() {
- return NAMESPACE_PREFIX;
- }
-
- public String getAnonymousUri() {
- return NAMESPACE_URI + "/role/anonymous";
- }
-
- public String getNoneUri() {
- return null;
- }
-
- public QName getToName() {
- return TO;
- }
-
- public QName getFromName() {
- return FROM;
- }
-
- public QName getReplyToName() {
- return REPLY_TO;
- }
-
- public QName getFaultToName() {
- return FAULT_TO;
- }
-
- public QName getActionName() {
- return ACTION;
- }
-
- public QName getMessageIdName() {
- return MESSAGE_ID;
- }
-
- public QName getRelatesToName() {
- return RELATES_TO;
- }
-
- public QName getRelationshipReplyName() {
- return RELATIONSHIP_REPLY;
- }
-
- public QName getAddressName() {
- return ADDRESS;
- }
-
- public QName getRelationshipTypeName() {
- return RELATIONSHIP_TYPE;
- }
-
- public QName getReferenceParametersName() {
- return REFERENCE_PARAMETERS;
- }
-
- public QName getReferencePropertiesName() {
- return REFERENCE_PROPERTIES;
- }
-
- public QName getMessageHeaderRequiredName() {
- return MESSAGE_INFORMATION_HEADER_REQUIRED;
- }
-
- public String getMessageHeaderRequiredText() {
- return "A required message information header, To, MessageID, or Action, is not present.";
- }
-
- public QName getDestinationUnreachableName() {
- return DESTINATION_UNREACHABLE;
- }
-
- public String getDestinationUnreachableText() {
- return "No route can be determined to reach the destination role defined by the WS-Addressing To.";
- }
-
- public QName getActionNotSupportedName() {
- return ACTION_NOT_SUPPORTED_NAME;
- }
-
- public String getActionNotSupportedText(String action) {
- return "The " + action + " cannot be processed at the receiver.";
- }
-
- public String toString() {
- return NAMESPACE_URI;
- }
-}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408Interceptor.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408Interceptor.java
new file mode 100644
index 00000000..12c70030
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408Interceptor.java
@@ -0,0 +1,60 @@
+package org.springframework.ws.soap.addressing;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Implements the August 2004 edition of the WS-Addressing specification. This version of the specification is used by
+ * Microsoft's Web Services Enhancements (WSE) 3.0.
+ *
+ * @author Arjen Poutsma
+ * @see Web Services Addressing, August 2004
+ * @see Web Services Enhancements
+ * @since 1.1.0
+ */
+public class WsAddressing200408Interceptor extends AbstractVersionBasedWsAddressingInterceptor {
+
+ protected WsAddressing200408Interceptor() {
+ super(new WsAddressing200408());
+ }
+
+ private static class WsAddressing200408 extends AbstractWsAddressingVersion {
+
+ private static final String NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
+
+ public String getNamespaceUri() {
+ return NAMESPACE_URI;
+ }
+
+ /*
+ * Message addressing properties
+ */
+
+ public String getRelationshipReply() {
+ return getNamespacePrefix() + ":Reply";
+ }
+
+ /*
+ * Address URIs
+ */
+
+ public String getAnonymousUri() {
+ return NAMESPACE_URI + "/role/anonymous";
+ }
+
+ public String getNoneUri() {
+ return null;
+ }
+
+ /*
+ * Faults
+ */
+
+ public QName getMessageAddressingHeaderRequiredFaultSubcode() {
+ return new QName(NAMESPACE_URI, "MessageInformationHeaderRequired", getNamespacePrefix());
+ }
+
+ public String getMessageAddressingHeaderRequiredFaultReason() {
+ return "A required message information header, To, MessageID, or Action, is not present.";
+ }
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200508Interceptor.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200508Interceptor.java
new file mode 100644
index 00000000..49491e3e
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200508Interceptor.java
@@ -0,0 +1,58 @@
+package org.springframework.ws.soap.addressing;
+
+import javax.xml.namespace.QName;
+
+/** @author Arjen Poutsma */
+public class WsAddressing200508Interceptor extends AbstractVersionBasedWsAddressingInterceptor {
+
+ public WsAddressing200508Interceptor() {
+ super(new WsAddressing200508());
+ }
+
+ private static class WsAddressing200508 extends AbstractWsAddressingVersion {
+
+ private static final String NAMESPACE_URI = "http://www.w3.org/2005/08/addressing";
+
+ public String getNamespaceUri() {
+ return NAMESPACE_URI;
+ }
+
+ /*
+ * Message addressing properties
+ */
+
+ public String getRelationshipReply() {
+ return "http://www.w3.org/2005/08/addressing/reply";
+ }
+
+ public QName getReferencePropertiesName() {
+ return null;
+ }
+
+ /*
+ * Address URIs
+ */
+
+ public String getAnonymousUri() {
+ return NAMESPACE_URI + "/anonymous";
+ }
+
+ public String getNoneUri() {
+ return NAMESPACE_URI + "/none";
+ }
+
+ /*
+ * Faults
+ */
+
+ public QName getMessageAddressingHeaderRequiredFaultSubcode() {
+ return new QName(NAMESPACE_URI, "MessageAddressingHeaderRequired", getNamespacePrefix());
+ }
+
+ public String getMessageAddressingHeaderRequiredFaultReason() {
+ return "A required header representing a Message Addressing Property is not present";
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java
index fa991825..5d7b5430 100644
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java
@@ -31,11 +31,9 @@ public interface WsAddressingVersion {
/** Returns the prefix associated with the WS-Addressing namespace handled by this specification. */
String getNamespacePrefix();
- /** Returns the anonymous URI. */
- String getAnonymousUri();
-
- /** Returns the none URI, or null if the spec does not define it. */
- String getNoneUri();
+ /*
+ * Message addressing properties
+ */
/** Returns the qualified name of the To addressing header. */
QName getToName();
@@ -61,7 +59,7 @@ public interface WsAddressingVersion {
/**
* Returns the qualified name of the Relationship addressing attribute.
*
- * @see #getRelationshipReplyName()
+ * @see #getRelationshipReply()
*/
QName getRelationshipTypeName();
@@ -70,7 +68,7 @@ public interface WsAddressingVersion {
*
* @see #getRelationshipTypeName()
*/
- QName getRelationshipReplyName();
+ String getRelationshipReply();
/**
* Returns the qualified name of the ReferenceProperties in the endpoint reference. Returns
@@ -84,24 +82,34 @@ public interface WsAddressingVersion {
*/
QName getReferenceParametersName();
+ /*
+ * Endpoint Reference
+ */
+
/** The qualified name of the Address in EndpointReference. */
QName getAddressName();
+ /** The qualified name of the Metadata in EndpointReference. */
+ QName getMetadataName();
+
+ /*
+ * Address URIs
+ */
+
+ /** Returns the anonymous URI. */
+ String getAnonymousUri();
+
+ /** Returns the none URI, or null if the spec does not define it. */
+ String getNoneUri();
+
+ /*
+ * Faults
+ */
+
/** Returns the qualified name of the fault subcode that indicates that a header is missing. */
- QName getMessageHeaderRequiredName();
+ QName getMessageAddressingHeaderRequiredFaultSubcode();
- /** Returns the text of the fault that indicates that a header is missing. */
- String getMessageHeaderRequiredText();
+ /** Returns the reason of the fault that indicates that a header is missing. */
+ String getMessageAddressingHeaderRequiredFaultReason();
- /** Returns the qualified name of the DestinationUnreachable fault subcode. */
- QName getDestinationUnreachableName();
-
- /** Returns the text of the DestinationUnreachable fault. */
- String getDestinationUnreachableText();
-
- /** Returns the qualified name of the ActionNotSupported fault subcode. */
- QName getActionNotSupportedName();
-
- /** Returns the text of the ActionNotSupported fault. */
- String getActionNotSupportedText(String action);
}
diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java
index c3d0f0ae..82d6b9ed 100644
--- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java
+++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java
@@ -27,7 +27,6 @@ import org.springframework.ws.soap.SoapMessage;
* Note that the {@link UUID} class is only available on Java 5 and above.
*
* @author Arjen Poutsma
- * @see java.util.UUID
*/
public class UuidMessageIdProvider implements MessageIdProvider {
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java
new file mode 100644
index 00000000..d97107d3
--- /dev/null
+++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java
@@ -0,0 +1,103 @@
+package org.springframework.ws.soap.addressing;
+
+import java.util.Iterator;
+
+import org.easymock.MockControl;
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.soap.SoapHeaderElement;
+import org.springframework.ws.soap.addressing.messageid.MessageIdProvider;
+import org.springframework.ws.soap.saaj.SaajSoapMessage;
+import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
+
+public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWsAddressingTestCase {
+
+ protected AbstractWsAddressingInterceptor interceptor;
+
+ private MockControl providerControl;
+
+ private MessageIdProvider providerMock;
+
+ protected final void onSetUp() throws Exception {
+ providerControl = MockControl.createControl(MessageIdProvider.class);
+ providerMock = (MessageIdProvider) providerControl.getMock();
+ interceptor = createInterceptor();
+ interceptor.setMessageIdProvider(providerMock);
+ }
+
+ public void testUnderstands() throws Exception {
+ SaajSoapMessage validRequest = loadSaajMessage(getTestPath() + "/valid.xml");
+ Iterator iterator = validRequest.getSoapHeader().examineAllHeaderElements();
+ providerControl.replay();
+ while (iterator.hasNext()) {
+ SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
+ assertTrue("Header [" + headerElement.getName() + " not understood",
+ interceptor.understands(headerElement));
+ }
+ providerControl.verify();
+ }
+
+ public void testHandleValidRequest() throws Exception {
+ SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/valid.xml");
+ MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
+ providerControl.replay();
+ boolean result = interceptor.handleRequest(context, null);
+ assertTrue("Valid request not handled", result);
+ assertFalse("Message Context has response", context.hasResponse());
+ providerControl.verify();
+ }
+
+ public void testHandleInvalidRequest() throws Exception {
+ SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/invalid.xml");
+ MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
+ providerControl.replay();
+ boolean result = interceptor.handleRequest(context, null);
+ assertFalse("Invalid request handled", result);
+ assertTrue("Message Context has no response", context.hasResponse());
+ SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-invalid.xml");
+ assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse,
+ (SaajSoapMessage) context.getResponse());
+ providerControl.verify();
+ }
+
+ public void testHandleAnonymousReplyTo() throws Exception {
+ SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/anonymous.xml");
+ MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
+ SaajSoapMessage response = (SaajSoapMessage) context.getResponse();
+ String messageId = "uid:1234";
+ providerControl.expectAndReturn(providerMock.getMessageId(response), messageId);
+ providerControl.replay();
+ boolean result = interceptor.handleResponse(context, null);
+ assertTrue("Anonymous request not handled", result);
+ SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-anonymous.xml");
+ assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse,
+ (SaajSoapMessage) context.getResponse());
+ providerControl.verify();
+ }
+
+ public void testHandleNoneReplyTo() throws Exception {
+ SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/none.xml");
+ MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
+ providerControl.replay();
+ boolean result = interceptor.handleResponse(context, null);
+ assertFalse("None request handled", result);
+ providerControl.verify();
+ }
+
+ public void testHandleOutOfBandReplyTo() throws Exception {
+ SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/valid.xml");
+ MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
+ SaajSoapMessage response = (SaajSoapMessage) context.getResponse();
+ String messageId = "uid:1234";
+ providerControl.expectAndReturn(providerMock.getMessageId(response), messageId);
+ providerControl.replay();
+ boolean result = interceptor.handleResponse(context, null);
+ assertFalse("Out of Band request handled", result);
+ providerControl.verify();
+ }
+
+ protected abstract AbstractWsAddressingInterceptor createInterceptor();
+
+ protected abstract String getTestPath();
+
+}
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingTestCase.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingTestCase.java
index 7e2ec1b1..f8ee36e9 100644
--- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingTestCase.java
+++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingTestCase.java
@@ -24,15 +24,17 @@ import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import org.custommonkey.xmlunit.XMLTestCase;
+import org.custommonkey.xmlunit.XMLUnit;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
+import org.w3c.dom.Document;
-/** @author Arjen Poutsma */
public abstract class AbstractWsAddressingTestCase extends XMLTestCase {
protected MessageFactory messageFactory;
protected final void setUp() throws Exception {
messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
+ XMLUnit.setIgnoreWhitespace(true);
onSetUp();
}
@@ -43,6 +45,7 @@ public abstract class AbstractWsAddressingTestCase extends XMLTestCase {
MimeHeaders mimeHeaders = new MimeHeaders();
mimeHeaders.addHeader("Content-Type", " application/soap+xml");
InputStream is = getClass().getResourceAsStream(fileName);
+ assertNotNull("Could not load " + fileName, is);
try {
return new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, is));
}
@@ -50,4 +53,10 @@ public abstract class AbstractWsAddressingTestCase extends XMLTestCase {
is.close();
}
}
+
+ protected void assertXMLEqual(String message, SaajSoapMessage expected, SaajSoapMessage result) {
+ Document expectedDocument = expected.getSaajMessage().getSOAPPart();
+ Document resultDocument = result.getSaajMessage().getSOAPPart();
+ assertXMLEqual(message, expectedDocument, resultDocument);
+ }
}
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AddressingHelperTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AddressingHelperTest.java
deleted file mode 100644
index ac2ac7f8..00000000
--- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AddressingHelperTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2007 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.addressing;
-
-import javax.xml.soap.MessageFactory;
-import javax.xml.soap.SOAPConstants;
-import javax.xml.soap.SOAPMessage;
-
-import org.springframework.ws.soap.saaj.SaajSoapMessage;
-
-public class AddressingHelperTest extends AbstractWsAddressingTestCase {
-
- private AddressingHelper helper;
-
- protected void onSetUp() throws Exception {
- helper = new AddressingHelper(new WsAddressing200408());
- SaajSoapMessage message = loadSaajMessage("request-200408.xml");
- }
-
- public void testAddMessageHeaderRequiredFault12() throws Exception {
- MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
- SOAPMessage saajMessage = messageFactory.createMessage();
- SaajSoapMessage message = new SaajSoapMessage(saajMessage);
- helper.addMessageHeaderRequiredFault(message);
-
- saajMessage.writeTo(System.out);
- System.out.println();
- }
-
- public void testAddDestinationUnreachableFault() throws Exception {
- MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
- SOAPMessage saajMessage = messageFactory.createMessage();
- SaajSoapMessage message = new SaajSoapMessage(saajMessage);
- helper.addDestinationUnreachableFault(message);
- saajMessage.writeTo(System.out);
- System.out.println();
- }
-
- public void testAddActionNotSupportedFault() throws Exception {
- MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
- SOAPMessage saajMessage = messageFactory.createMessage();
- SaajSoapMessage message = new SaajSoapMessage(saajMessage);
- helper.addActionNotSupportedFault(message, "myAction");
- saajMessage.writeTo(System.out);
- System.out.println();
- }
-}
\ No newline at end of file
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/StatefulAddressingInterceptorTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/StatefulAddressingInterceptorTest.java
deleted file mode 100644
index 51a4ad05..00000000
--- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/StatefulAddressingInterceptorTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2007 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.addressing;
-
-import java.util.Iterator;
-import javax.xml.namespace.QName;
-import javax.xml.soap.SOAPElement;
-import javax.xml.soap.SOAPException;
-import javax.xml.soap.SOAPMessage;
-
-import org.springframework.ws.context.DefaultMessageContext;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.soap.SoapHeaderElement;
-import org.springframework.ws.soap.addressing.messageid.UuidMessageIdProvider;
-import org.springframework.ws.soap.saaj.SaajSoapMessage;
-import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
-
-public class StatefulAddressingInterceptorTest extends AbstractWsAddressingTestCase {
-
- private StatefulAddressingInterceptor interceptor;
-
- private SaajSoapMessage request;
-
- private SOAPMessage saajRequest;
-
- private MessageContext messageContext;
-
- private WsAddressing200408 version;
-
- protected void onSetUp() throws Exception {
- version = new WsAddressing200408();
- MessageAddressingProperties map = new MessageAddressingProperties("mailto:joe@fabrikam123.example",
- new EndpointReference("http://business456.example/client1"), "http://fabrikam123.example/mail/Delete",
- "uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff");
- interceptor =
- new StatefulAddressingInterceptor(new AddressingHelper(version), new UuidMessageIdProvider(), map);
- request = loadSaajMessage("request-200408.xml");
- saajRequest = request.getSaajMessage();
- messageContext = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory));
- }
-
- public void testUnderstands() throws Exception {
- Iterator iterator = request.getSoapHeader()
- .examineAllHeaderElements();
- SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
- assertTrue("Interceptor does not understand header", interceptor.understands(headerElement));
- }
-
- public void testHandleRequestNormal() throws Exception {
- boolean result = interceptor.handleRequest(messageContext, null);
- assertTrue("Invalid result", result);
- }
-
- public void testHandleRequestToMissing() throws Exception {
- removeElement(version.getToName());
- boolean result = interceptor.handleRequest(messageContext, null);
- assertFalse("Invalid result", result);
- assertTrue("Response has no fault", messageContext.getResponse().hasFault());
- }
-
- public void testHandleRequestActionMissing() throws Exception {
- removeElement(version.getActionName());
- boolean result = interceptor.handleRequest(messageContext, null);
- assertFalse("Invalid result", result);
- assertTrue("Response has no fault", messageContext.getResponse().hasFault());
- }
-
- public void testHandleRequestMessageIdMissing() throws Exception {
- removeElement(version.getMessageIdName());
- boolean result = interceptor.handleRequest(messageContext, null);
- assertFalse("Invalid result", result);
- assertTrue("Response has no fault", messageContext.getResponse().hasFault());
- }
-
- public void testHandleResponse() throws Exception {
- interceptor.handleRequest(messageContext, null);
- interceptor.handleResponse(messageContext, null);
- messageContext.getResponse().writeTo(System.out);
- }
-
- public void testHandleFault() throws Exception {
- interceptor.handleRequest(messageContext, null);
- interceptor.handleFault(messageContext, null);
- messageContext.getResponse().writeTo(System.out);
- }
-
- private void removeElement(QName name) throws SOAPException {
- Iterator iterator = saajRequest.getSOAPHeader().getChildElements(name);
- while (iterator.hasNext()) {
- SOAPElement element = (SOAPElement) iterator.next();
- element.detachNode();
- }
- }
-
-}
\ No newline at end of file
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200408InterceptorTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200408InterceptorTest.java
new file mode 100644
index 00000000..1aaa7d51
--- /dev/null
+++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200408InterceptorTest.java
@@ -0,0 +1,16 @@
+package org.springframework.ws.soap.addressing;
+
+public class WsAddressing200408InterceptorTest extends AbstractWsAddressingInterceptorTestCase {
+
+ protected AbstractWsAddressingInterceptor createInterceptor() {
+ return new WsAddressing200408Interceptor();
+ }
+
+ protected String getTestPath() {
+ return "200408";
+ }
+
+ public void testHandleNoneReplyTo() throws Exception {
+ // This version of the spec does not have none addresses
+ }
+}
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200508InterceptorTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200508InterceptorTest.java
new file mode 100644
index 00000000..1ca93765
--- /dev/null
+++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200508InterceptorTest.java
@@ -0,0 +1,12 @@
+package org.springframework.ws.soap.addressing;
+
+public class WsAddressing200508InterceptorTest extends AbstractWsAddressingInterceptorTestCase {
+
+ protected AbstractWsAddressingInterceptor createInterceptor() {
+ return new WsAddressing200508Interceptor();
+ }
+
+ protected String getTestPath() {
+ return "200508";
+ }
+}
\ No newline at end of file
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingMappingTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingMappingTest.java
deleted file mode 100644
index f5078b8a..00000000
--- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingMappingTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2007 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.addressing;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathFactory;
-
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.xml.namespace.SimpleNamespaceContext;
-import org.w3c.dom.Element;
-
-/** Test case for AbstractWsAddressingMapping */
-public class WsAddressingMappingTest extends AbstractWsAddressingTestCase {
-
- private AbstractWsAddressingMapping mapping;
-
- protected void onSetUp() throws Exception {
- mapping = new MyWsAddressingMapping();
-// mapping.afterPropertiesSet();
- }
-
- public void testGetSoapHeaderElement() throws Exception {
- SoapMessage message = loadSaajMessage("request-200408.xml");
- Element element = mapping.getSoapHeaderElement(message);
- assertNotNull("No element returned", element);
- assertEquals("Invalid header element returned", "Header", element.getLocalName());
- XPathFactory factory = XPathFactory.newInstance();
- XPath xpath = factory.newXPath();
- SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
- namespaceContext.bindNamespaceUri("wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing");
- xpath.setNamespaceContext(namespaceContext);
- XPathExpression expression = xpath.compile("wsa:To");
- String result = expression.evaluate(element);
- System.out.println("result = " + result);
- }
-
- private static class MyWsAddressingMapping extends AbstractWsAddressingMapping {
-
- }
-
-}
\ No newline at end of file
diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java
index 259273c5..50bc7b6a 100644
--- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java
+++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java
@@ -31,7 +31,6 @@ public abstract class AbstractMessageIdProviderTestCase extends TestCase {
public void testProvider() {
String messageId1 = provider.getMessageId(null);
- System.out.println(messageId1);
assertTrue("Empty messageId", StringUtils.hasLength(messageId1));
String messageId2 = provider.getMessageId(null);
assertTrue("Empty messageId", StringUtils.hasLength(messageId2));
diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml
new file mode 100644
index 00000000..6db3c331
--- /dev/null
+++ b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml
@@ -0,0 +1,17 @@
+