Working on SWS-84 (WS-Addressing)
This commit is contained in:
@@ -73,6 +73,10 @@ public class DefaultMessageContext extends AbstractMessageContext {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public void clearResponse() {
|
||||
response = null;
|
||||
}
|
||||
|
||||
public void readResponse(InputStream inputStream) throws IOException {
|
||||
checkForResponse();
|
||||
response = messageFactory.createWebServiceMessage(inputStream);
|
||||
|
||||
@@ -66,6 +66,9 @@ public interface MessageContext {
|
||||
*/
|
||||
void setResponse(WebServiceMessage response);
|
||||
|
||||
/** Removes the response message, if any. */
|
||||
void clearResponse();
|
||||
|
||||
/**
|
||||
* Reads a response message from the given input stream.
|
||||
*
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -70,12 +70,12 @@
|
||||
<distributionManagement>
|
||||
<downloadUrl>http://static.springframework.org/spring-ws/site/downloads/releases.html</downloadUrl>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<id>spring-s3</id>
|
||||
<name>Spring Milestone Repository</name>
|
||||
<url>s3://maven.springframework.org/milestone</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>spring-snapshot</id>
|
||||
<id>spring-s3</id>
|
||||
<name>Spring Snapshot Repository</name>
|
||||
<url>s3://maven.springframework.org/snapshot</url>
|
||||
</snapshotRepository>
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.JdkVersion;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
@@ -29,7 +31,7 @@ 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.MessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.messageid.UidMessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.messageid.RandomGuidMessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.messageid.UuidMessageIdStrategy;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
|
||||
import org.springframework.ws.soap.server.SoapEndpointMapping;
|
||||
@@ -40,9 +42,10 @@ import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
* Abstract base class for {@link EndpointMapping} implementations that implement WS-Addressing.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class AbstractWsAddressingMapping extends TransformerObjectSupport implements SoapEndpointMapping {
|
||||
public abstract class AbstractWsAddressingMapping extends TransformerObjectSupport
|
||||
implements SoapEndpointMapping, InitializingBean {
|
||||
|
||||
private String[] actorsOrRoles;
|
||||
|
||||
@@ -58,14 +61,27 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
|
||||
private EndpointInterceptor[] postInterceptors;
|
||||
|
||||
private int wsAddressingInterceptorIdx = -1;
|
||||
|
||||
private EndpointInterceptor[] allInterceptors;
|
||||
|
||||
/** Protected constructor. Initializes the default settings. */
|
||||
protected AbstractWsAddressingMapping() {
|
||||
initDefaultStrategies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the default implementation for this mapping's strategies: the {@link WsAddressing200408} and {@link
|
||||
* WsAddressing200605} versions of the specication, and the {@link UuidMessageIdStrategy} on Java 5 and higher; the
|
||||
* {@link RandomGuidMessageIdStrategy} on Java 1.4.
|
||||
*/
|
||||
protected void initDefaultStrategies() {
|
||||
this.versions = new WsAddressingVersion[]{new WsAddressing200408(), new WsAddressing200605()};
|
||||
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
|
||||
if (JdkVersion.isAtLeastJava15()) {
|
||||
messageIdStrategy = new UuidMessageIdStrategy();
|
||||
}
|
||||
else {
|
||||
messageIdStrategy = new UidMessageIdStrategy();
|
||||
messageIdStrategy = new RandomGuidMessageIdStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +118,8 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
/**
|
||||
* Sets the message id provider used for creating WS-Addressing MessageIds.
|
||||
* <p/>
|
||||
* By default, the {@link UuidMessageIdStrategy} is used on Java 5 and higher, and the {@link UidMessageIdStrategy}
|
||||
* on Java 1.4 and lower.
|
||||
* By default, the {@link UuidMessageIdStrategy} is used on Java 5 and higher, and the {@link
|
||||
* RandomGuidMessageIdStrategy} on Java 1.4.
|
||||
*/
|
||||
public final void setMessageIdProvider(MessageIdStrategy messageIdStrategy) {
|
||||
this.messageIdStrategy = messageIdStrategy;
|
||||
@@ -123,9 +139,14 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
this.versions = versions;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Supporting WS-Addressing " + Arrays.asList(versions));
|
||||
}
|
||||
}
|
||||
|
||||
public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws TransformerException {
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse(),
|
||||
"WsAddressingMapping requires a SoapMessage request");
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest());
|
||||
SoapMessage request = (SoapMessage) messageContext.getRequest();
|
||||
for (int i = 0; i < versions.length; i++) {
|
||||
if (supports(versions[i], request)) {
|
||||
@@ -158,18 +179,21 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
}
|
||||
|
||||
private EndpointInterceptor[] getAllEndpointInterceptors(WsAddressingVersion version) {
|
||||
if (preInterceptors == null) {
|
||||
preInterceptors = new EndpointInterceptor[0];
|
||||
// lazy init
|
||||
if (allInterceptors == null) {
|
||||
if (preInterceptors == null) {
|
||||
preInterceptors = new EndpointInterceptor[0];
|
||||
}
|
||||
if (postInterceptors == null) {
|
||||
postInterceptors = new EndpointInterceptor[0];
|
||||
}
|
||||
allInterceptors = new EndpointInterceptor[preInterceptors.length + postInterceptors.length + 1];
|
||||
System.arraycopy(preInterceptors, 0, allInterceptors, 0, preInterceptors.length);
|
||||
System.arraycopy(postInterceptors, 0, allInterceptors, preInterceptors.length + 1, postInterceptors.length);
|
||||
}
|
||||
if (postInterceptors == null) {
|
||||
postInterceptors = new EndpointInterceptor[0];
|
||||
}
|
||||
EndpointInterceptor[] interceptors =
|
||||
new EndpointInterceptor[preInterceptors.length + postInterceptors.length + 1];
|
||||
System.arraycopy(preInterceptors, 0, interceptors, 0, preInterceptors.length);
|
||||
interceptors[preInterceptors.length] = new WsAddressingInterceptor(version, messageIdStrategy, messageSenders);
|
||||
System.arraycopy(postInterceptors, 0, interceptors, preInterceptors.length + 1, postInterceptors.length);
|
||||
return interceptors;
|
||||
allInterceptors[preInterceptors.length] =
|
||||
new WsAddressingEndpointInterceptor(version, messageIdStrategy, messageSenders);
|
||||
return allInterceptors;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -27,6 +29,10 @@ import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.soap.SoapFault;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
@@ -39,16 +45,13 @@ import org.springframework.xml.namespace.QNameUtils;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link WsAddressingVersion} implementations. Uses {@link XPathExpression}s to retrieve
|
||||
* addressing information.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class AbstractWsAddressingVersion extends TransformerObjectSupport implements WsAddressingVersion {
|
||||
|
||||
@@ -111,15 +114,34 @@ public abstract class AbstractWsAddressingVersion extends TransformerObjectSuppo
|
||||
|
||||
public MessageAddressingProperties getMessageAddressingProperties(SoapMessage message) {
|
||||
Element headerElement = getSoapHeaderElement(message);
|
||||
String to = toExpression.evaluateAsString(headerElement);
|
||||
URI to = getUri(headerElement, toExpression);
|
||||
EndpointReference from = getEndpointReference(fromExpression.evaluateAsNode(headerElement));
|
||||
EndpointReference replyTo = getEndpointReference(replyToExpression.evaluateAsNode(headerElement));
|
||||
if (replyTo == null && getAnonymous() != null) {
|
||||
replyTo = getDefaultReplyTo(from);
|
||||
}
|
||||
EndpointReference faultTo = getEndpointReference(faultToExpression.evaluateAsNode(headerElement));
|
||||
String action = actionExpression.evaluateAsString(headerElement);
|
||||
String messageId = messageIdExpression.evaluateAsString(headerElement);
|
||||
if (faultTo == null) {
|
||||
faultTo = replyTo;
|
||||
}
|
||||
URI action = getUri(headerElement, actionExpression);
|
||||
URI messageId = getUri(headerElement, messageIdExpression);
|
||||
return new MessageAddressingProperties(to, from, replyTo, faultTo, action, messageId);
|
||||
}
|
||||
|
||||
private URI getUri(Node node, XPathExpression expression) {
|
||||
String messageId = expression.evaluateAsString(node);
|
||||
if (!StringUtils.hasLength(messageId)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new URI(messageId);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Element getSoapHeaderElement(SoapMessage message) {
|
||||
SoapHeader header = message.getSoapHeader();
|
||||
if (header.getSource() instanceof DOMSource) {
|
||||
@@ -144,8 +166,8 @@ public abstract class AbstractWsAddressingVersion extends TransformerObjectSuppo
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
String address = addressExpression.evaluateAsString(node);
|
||||
if (!StringUtils.hasLength(address)) {
|
||||
URI address = getUri(node, addressExpression);
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
List referenceProperties = referencePropertiesExpression != null ?
|
||||
@@ -162,11 +184,11 @@ public abstract class AbstractWsAddressingVersion extends TransformerObjectSuppo
|
||||
public final void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map) {
|
||||
SoapHeader header = message.getSoapHeader();
|
||||
SoapHeaderElement messageId = header.addHeaderElement(getMessageIdName());
|
||||
messageId.setText(map.getMessageId());
|
||||
messageId.setText(map.getMessageId().toString());
|
||||
SoapHeaderElement relatesTo = header.addHeaderElement(getRelatesToName());
|
||||
relatesTo.setText(map.getRelatesTo());
|
||||
relatesTo.setText(map.getRelatesTo().toString());
|
||||
SoapHeaderElement to = header.addHeaderElement(getToName());
|
||||
to.setText(map.getTo());
|
||||
to.setText(map.getTo().toString());
|
||||
to.setMustUnderstand(true);
|
||||
try {
|
||||
Transformer transformer = createTransformer();
|
||||
@@ -215,12 +237,12 @@ public abstract class AbstractWsAddressingVersion extends TransformerObjectSuppo
|
||||
*/
|
||||
|
||||
public final boolean hasAnonymousAddress(EndpointReference epr) {
|
||||
String anonymous = getAnonymousUri();
|
||||
URI anonymous = getAnonymous();
|
||||
return anonymous != null && anonymous.equals(epr.getAddress());
|
||||
}
|
||||
|
||||
public final boolean hasNoneAddress(EndpointReference epr) {
|
||||
String none = getNoneUri();
|
||||
URI none = getNone();
|
||||
return none != null && none.equals(epr.getAddress());
|
||||
}
|
||||
|
||||
@@ -296,15 +318,18 @@ public abstract class AbstractWsAddressingVersion extends TransformerObjectSuppo
|
||||
return QNameUtils.createQName(getNamespaceUri(), "Address", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the default ReplyTo EPR. Can be based on the From EPR, or the anonymous URI. */
|
||||
protected abstract EndpointReference getDefaultReplyTo(EndpointReference from);
|
||||
|
||||
/*
|
||||
* Address URIs
|
||||
*/
|
||||
|
||||
/** Returns the anonymous URI. */
|
||||
protected abstract String getAnonymousUri();
|
||||
protected abstract URI getAnonymous();
|
||||
|
||||
/** Returns the none URI, or <code>null</code> if the spec does not define it. */
|
||||
protected abstract String getNoneUri();
|
||||
protected abstract URI getNone();
|
||||
|
||||
/*
|
||||
* Faults
|
||||
@@ -321,4 +346,8 @@ public abstract class AbstractWsAddressingVersion extends TransformerObjectSuppo
|
||||
|
||||
/** Returns the reason of the fault that indicates that a header is invalid. */
|
||||
protected abstract String getInvalidAddressingHeaderFaultReason();
|
||||
|
||||
public String toString() {
|
||||
return getNamespaceUri();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents a set of Message Addressing Properties, as defined in the WS-Addressing specification.
|
||||
* <p/>
|
||||
* In earlier versions of the spec, these properties were called Message Information Headers.
|
||||
* Represents an Endpoint Reference, as defined in the WS-Addressing specification.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-core/#eprs">Endpoint References</a>
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class EndpointReference {
|
||||
|
||||
private final String address;
|
||||
private final URI address;
|
||||
|
||||
private final List referenceProperties;
|
||||
|
||||
@@ -45,7 +45,7 @@ public final class EndpointReference {
|
||||
*
|
||||
* @param address the endpoint address
|
||||
*/
|
||||
public EndpointReference(String address) {
|
||||
public EndpointReference(URI address) {
|
||||
Assert.notNull(address, "address must not be null");
|
||||
this.address = address;
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
@@ -60,7 +60,7 @@ public final class EndpointReference {
|
||||
* @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) {
|
||||
public EndpointReference(URI address, List referenceProperties, List referenceParameters) {
|
||||
Assert.notNull(address, "address must not be null");
|
||||
Assert.notNull(referenceProperties, "referenceProperties must not be null");
|
||||
Assert.notNull(referenceParameters, "referenceParameters must not be null");
|
||||
@@ -70,7 +70,7 @@ public final class EndpointReference {
|
||||
}
|
||||
|
||||
/** Returns the address of the endpoint. */
|
||||
public String getAddress() {
|
||||
public URI getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,6 @@ public final class EndpointReference {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "EndpointReference[" + address + ']';
|
||||
return address.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents a set of Message Addressing Properties, as defined in the WS-Addressing specification.
|
||||
* <p/>
|
||||
@@ -28,11 +27,11 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-core/#msgaddrprops">Message Addressing Properties</a>
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class MessageAddressingProperties {
|
||||
|
||||
private final String to;
|
||||
private final URI to;
|
||||
|
||||
private final EndpointReference from;
|
||||
|
||||
@@ -40,11 +39,11 @@ public final class MessageAddressingProperties {
|
||||
|
||||
private final EndpointReference faultTo;
|
||||
|
||||
private final String action;
|
||||
private final URI action;
|
||||
|
||||
private final String messageId;
|
||||
private final URI messageId;
|
||||
|
||||
private final String relatesTo;
|
||||
private final URI relatesTo;
|
||||
|
||||
private final List referenceProperties;
|
||||
|
||||
@@ -60,12 +59,12 @@ public final class MessageAddressingProperties {
|
||||
* @param action the value of the action property
|
||||
* @param messageId the value of the message id property
|
||||
*/
|
||||
public MessageAddressingProperties(String to,
|
||||
public MessageAddressingProperties(URI to,
|
||||
EndpointReference from,
|
||||
EndpointReference replyTo,
|
||||
EndpointReference faultTo,
|
||||
String action,
|
||||
String messageId) {
|
||||
URI action,
|
||||
URI messageId) {
|
||||
this.to = to;
|
||||
this.from = from;
|
||||
this.replyTo = replyTo;
|
||||
@@ -77,7 +76,7 @@ public final class MessageAddressingProperties {
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
private MessageAddressingProperties(EndpointReference epr, String action, String messageId, String relatesTo) {
|
||||
private MessageAddressingProperties(EndpointReference epr, URI action, URI messageId, URI relatesTo) {
|
||||
this.to = epr.getAddress();
|
||||
this.action = action;
|
||||
this.messageId = messageId;
|
||||
@@ -90,7 +89,7 @@ public final class MessageAddressingProperties {
|
||||
}
|
||||
|
||||
/** Returns the value of the destination property. */
|
||||
public String getTo() {
|
||||
public URI getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
@@ -104,23 +103,23 @@ public final class MessageAddressingProperties {
|
||||
return replyTo;
|
||||
}
|
||||
|
||||
/** Returns the value of the fault endpoint property. Defaults to {@link #getReplyTo()} if no fault endpoint is set. */
|
||||
/** Returns the value of the fault endpoint property. */
|
||||
public EndpointReference getFaultTo() {
|
||||
return faultTo != null ? faultTo : getReplyTo();
|
||||
return faultTo;
|
||||
}
|
||||
|
||||
/** Returns the value of the action property. */
|
||||
public String getAction() {
|
||||
public URI getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/** Returns the value of the message id property. */
|
||||
public String getMessageId() {
|
||||
public URI getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
/** Returns the value of the relationship property. */
|
||||
public String getRelatesTo() {
|
||||
public URI getRelatesTo() {
|
||||
return relatesTo;
|
||||
}
|
||||
|
||||
@@ -135,18 +134,26 @@ public final class MessageAddressingProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether is {@link MessageAddressingProperties} is valid, i.e. whether all required elements are listed.
|
||||
* Returns <code>true</code> if the destination and action properties have been set, and if a reply or fault
|
||||
* endpoint has been set, also checks for the message id.
|
||||
* Indicates whether is {@link MessageAddressingProperties} is valid, i.e. whether all required elements are
|
||||
* listed.
|
||||
* <p/>
|
||||
* Returns <code>true</code> if the to and action properties have been set, and - if a reply or fault endpoint has
|
||||
* been set - also checks for the message id.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return StringUtils.hasLength(to) && StringUtils.hasLength(action) &&
|
||||
!(replyTo != null && !StringUtils.hasLength(messageId)) &&
|
||||
!(faultTo != null && !StringUtils.hasLength(messageId));
|
||||
|
||||
if (to == null) {
|
||||
return false;
|
||||
}
|
||||
if (action == null) {
|
||||
return false;
|
||||
}
|
||||
if (replyTo != null || faultTo != null) {
|
||||
return messageId != null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public MessageAddressingProperties getResponseProperties(EndpointReference epr, String action, String messageId) {
|
||||
public MessageAddressingProperties getReplyProperties(EndpointReference epr, URI action, URI messageId) {
|
||||
return new MessageAddressingProperties(epr, action, messageId, this.messageId);
|
||||
}
|
||||
|
||||
@@ -156,8 +163,16 @@ public final class MessageAddressingProperties {
|
||||
* checks for the message id.
|
||||
*/
|
||||
public boolean hasRequiredProperties() {
|
||||
return StringUtils.hasLength(to) && StringUtils.hasLength(action) &&
|
||||
!(replyTo != null && !StringUtils.hasLength(messageId)) &&
|
||||
!(faultTo != null && !StringUtils.hasLength(messageId));
|
||||
// TODO: make sure this is handled according to the spec
|
||||
if (to == null) {
|
||||
return false;
|
||||
}
|
||||
if (action == null) {
|
||||
return false;
|
||||
}
|
||||
if (replyTo != null || faultTo != null) {
|
||||
return messageId != null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.net.URI;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
@@ -26,14 +27,14 @@ import org.springframework.xml.namespace.QNameUtils;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://msdn.microsoft.com/ws/2004/08/ws-addressing/">Web Services Addressing, August 2004</a>
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class WsAddressing200408 extends AbstractWsAddressingVersion {
|
||||
|
||||
private static final String NAMESPACE_URI = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
|
||||
|
||||
protected final String getAnonymousUri() {
|
||||
return NAMESPACE_URI + "/role/anonymous";
|
||||
protected final URI getAnonymous() {
|
||||
return URI.create(NAMESPACE_URI + "/role/anonymous");
|
||||
}
|
||||
|
||||
protected final String getInvalidAddressingHeaderFaultReason() {
|
||||
@@ -56,7 +57,11 @@ public class WsAddressing200408 extends AbstractWsAddressingVersion {
|
||||
return NAMESPACE_URI;
|
||||
}
|
||||
|
||||
protected final String getNoneUri() {
|
||||
protected EndpointReference getDefaultReplyTo(EndpointReference from) {
|
||||
return from;
|
||||
}
|
||||
|
||||
protected final URI getNone() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.net.URI;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
@@ -26,7 +27,7 @@ import org.springframework.xml.namespace.QNameUtils;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://www.w3.org/TR/2006/REC-ws-addr-core-20060509">Web Services Addressing, August 2004</a>
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
|
||||
public class WsAddressing200605 extends AbstractWsAddressingVersion {
|
||||
@@ -41,12 +42,16 @@ public class WsAddressing200605 extends AbstractWsAddressingVersion {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final String getAnonymousUri() {
|
||||
return NAMESPACE_URI + "/anonymous";
|
||||
protected EndpointReference getDefaultReplyTo(EndpointReference from) {
|
||||
return new EndpointReference(getAnonymous());
|
||||
}
|
||||
|
||||
protected final String getNoneUri() {
|
||||
return NAMESPACE_URI + "/none";
|
||||
protected final URI getAnonymous() {
|
||||
return URI.create(NAMESPACE_URI + "/anonymous");
|
||||
}
|
||||
|
||||
protected final URI getNone() {
|
||||
return URI.create(NAMESPACE_URI + "/none");
|
||||
}
|
||||
|
||||
protected final QName getMessageAddressingHeaderRequiredFaultSubcode() {
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
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.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInterceptor;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
|
||||
/**
|
||||
* {@link SoapEndpointInterceptor} implementation that deals with WS-Addressing headers. Stateful, and instatiated by
|
||||
* the {@link AbstractWsAddressingMapping}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class WsAddressingEndpointInterceptor implements SoapEndpointInterceptor {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(WsAddressingEndpointInterceptor.class);
|
||||
|
||||
private final WsAddressingVersion version;
|
||||
|
||||
private final MessageIdStrategy messageIdStrategy;
|
||||
|
||||
private final WebServiceMessageSender[] messageSenders;
|
||||
|
||||
WsAddressingEndpointInterceptor(WsAddressingVersion version,
|
||||
MessageIdStrategy messageIdStrategy,
|
||||
WebServiceMessageSender[] messageSenders) {
|
||||
Assert.notNull(version, "version must not be null");
|
||||
Assert.notNull(messageIdStrategy, "messageIdStrategy must not be null");
|
||||
Assert.notNull(messageSenders, "messageSenders must not be null");
|
||||
this.version = version;
|
||||
this.messageIdStrategy = messageIdStrategy;
|
||||
this.messageSenders = messageSenders;
|
||||
}
|
||||
|
||||
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest());
|
||||
SoapMessage request = (SoapMessage) messageContext.getRequest();
|
||||
MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request);
|
||||
if (!requestMap.hasRequiredProperties()) {
|
||||
version.addMessageAddressingHeaderRequiredFault((SoapMessage) messageContext.getResponse());
|
||||
return false;
|
||||
}
|
||||
if (!requestMap.isValid() || messageIdStrategy.isDuplicate(requestMap.getMessageId())) {
|
||||
version.addInvalidAddressingHeaderFault((SoapMessage) messageContext.getResponse());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
return handleResponseOrFault(messageContext, false);
|
||||
}
|
||||
|
||||
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
return handleResponseOrFault(messageContext, true);
|
||||
}
|
||||
|
||||
private boolean handleResponseOrFault(MessageContext messageContext, boolean isFault) throws Exception {
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest());
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse());
|
||||
SoapMessage request = (SoapMessage) messageContext.getRequest();
|
||||
MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request);
|
||||
EndpointReference replyEpr = isFault ? requestMap.getFaultTo() : requestMap.getReplyTo();
|
||||
if (handleNoneAddress(messageContext, replyEpr)) {
|
||||
return false;
|
||||
}
|
||||
URI responseMessageId = getMessageId(messageContext);
|
||||
MessageAddressingProperties replyMap = requestMap.getReplyProperties(replyEpr, null, responseMessageId);
|
||||
version.addAddressingHeaders((SoapMessage) messageContext.getResponse(), replyMap);
|
||||
if (handleAnonymousAddress(messageContext, replyEpr)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
sendOutOfBand(messageContext, replyEpr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleNoneAddress(MessageContext messageContext, EndpointReference replyEpr) {
|
||||
if (replyEpr == null || version.hasNoneAddress(replyEpr)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr +
|
||||
"] reply address; reply [" + messageContext.getResponse() + "] discarded");
|
||||
}
|
||||
messageContext.clearResponse();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean handleAnonymousAddress(MessageContext messageContext, EndpointReference replyEpr) {
|
||||
if (version.hasAnonymousAddress(replyEpr)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr +
|
||||
"] reply address; sending in-band reply [" + messageContext.getResponse() + "]");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void sendOutOfBand(MessageContext messageContext, EndpointReference replyEpr) throws IOException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr +
|
||||
"] reply address; sending out-of-band reply [" + messageContext.getResponse() + "]");
|
||||
}
|
||||
|
||||
boolean supported = false;
|
||||
for (int i = 0; i < messageSenders.length; i++) {
|
||||
if (messageSenders[i].supports(replyEpr.getAddress())) {
|
||||
supported = true;
|
||||
WebServiceConnection connection = null;
|
||||
try {
|
||||
connection = messageSenders[i].createConnection(replyEpr.getAddress());
|
||||
connection.send(messageContext.getResponse());
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
messageContext.clearResponse();
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!supported) {
|
||||
logger.warn("Could not send out-of-band response to [" + replyEpr.getAddress() + "]. " +
|
||||
"Configure WebServiceMessageSenders which support this uri.");
|
||||
}
|
||||
}
|
||||
|
||||
private URI getMessageId(MessageContext messageContext) {
|
||||
URI responseMessageId = messageIdStrategy.newMessageId(messageContext);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Generated reply MessageID [" + responseMessageId + "] for [" + messageContext + "]");
|
||||
}
|
||||
return responseMessageId;
|
||||
}
|
||||
|
||||
public boolean understands(SoapHeaderElement header) {
|
||||
return version.understands(header);
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,10 @@ package org.springframework.ws.soap.addressing;
|
||||
import org.springframework.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* Exception thrown in cases on WS-Addressing errors.
|
||||
* Exception thrown in case on WS-Addressing errors.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class WsAddressingException extends WebServiceException {
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.ws.soap.SoapMessage;
|
||||
* Defines the contract for a specific version of the WS-Addressing specification.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface WsAddressingVersion {
|
||||
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing.messageid;
|
||||
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
|
||||
/**
|
||||
* Strategy interface that encapsulates the creation and validation of WS-Addressing <code>MessageID</code>s.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface MessageIdStrategy {
|
||||
|
||||
@@ -32,14 +34,14 @@ public interface MessageIdStrategy {
|
||||
* @param messageId the message id
|
||||
* @return <code>true</code> if a duplicate; <code>false</code> otherwise
|
||||
*/
|
||||
boolean isDuplicate(String messageId);
|
||||
boolean isDuplicate(URI messageId);
|
||||
|
||||
/**
|
||||
* Returns a new WS-Addressing <code>MessageID</code> for the given message.
|
||||
* Returns a new WS-Addressing <code>MessageID</code> for the {@link MessageContext#getResponse() response} in the
|
||||
* given message context.
|
||||
*
|
||||
* @param message the SOAP message to create a new message id for
|
||||
* @return the new message id
|
||||
*/
|
||||
String newMessageId(SoapMessage message);
|
||||
URI newMessageId(MessageContext messageContext);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2002-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.messageid;
|
||||
|
||||
/*
|
||||
* RandomGUID from http://www.javaexchange.com/aboutRandomGUID.html
|
||||
* @version 1.2.1 11/05/02 @author Marc A. Mnich
|
||||
*
|
||||
* From www.JavaExchange.com, Open Software licensing
|
||||
*
|
||||
* 11/05/02 -- Performance enhancement from Mike Dubman. Moved InetAddr.getLocal to static block. Mike has measured a 10
|
||||
* fold improvement in run time. 01/29/02 -- Bug fix: Improper seeding of nonsecure Random object caused duplicate GUIDs
|
||||
* to be produced. Random object is now only created once per JVM. 01/19/02 -- Modified random seeding and added new
|
||||
* constructor to allow secure random feature. 01/14/02 -- Added random function seeding with JVM run time
|
||||
*/
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Globally unique identifier generator.
|
||||
* <p/>
|
||||
* In the multitude of java GUID generators, I found none that guaranteed randomness. GUIDs are guaranteed to be
|
||||
* globally unique by using ethernet MACs, IP addresses, time elements, and sequential numbers. GUIDs are not expected
|
||||
* to be random and most often are easy/possible to guess given a sample from a given generator. SQL Server, for example
|
||||
* generates GUID that are unique but sequencial within a given instance.
|
||||
* <p/>
|
||||
* GUIDs can be used as security devices to hide things such as files within a filesystem where listings are unavailable
|
||||
* (e.g. files that are served up from a Web server with indexing turned off). This may be desirable in cases where
|
||||
* standard authentication is not appropriate. In this scenario, the RandomGuids are used as directories. Another
|
||||
* example is the use of GUIDs for primary keys in a database where you want to ensure that the keys are secret. Random
|
||||
* GUIDs can then be used in a URL to prevent hackers (or users) from accessing records by guessing or simply by
|
||||
* incrementing sequential numbers.
|
||||
* <p/>
|
||||
* There are many other possibilities of using GUIDs in the realm of security and encryption where the element of
|
||||
* randomness is important. This class was written for these purposes but can also be used as a general purpose GUID
|
||||
* generator as well.
|
||||
* <p/>
|
||||
* RandomGuid generates truly random GUIDs by using the system's IP address (name/IP), system time in milliseconds (as
|
||||
* an integer), and a very large random number joined together in a single String that is passed through an MD5 hash.
|
||||
* The IP address and system time make the MD5 seed globally unique and the random number guarantees that the generated
|
||||
* GUIDs will have no discernible pattern and cannot be guessed given any number of previously generated GUIDs. It is
|
||||
* generally not possible to access the seed information (IP, time, random number) from the resulting GUIDs as the MD5
|
||||
* hash algorithm provides one way encryption.
|
||||
* <p/>
|
||||
* <b>Security of RandomGuid</b>: RandomGuid can be called one of two ways -- with the basic java Random number
|
||||
* generator or a cryptographically strong random generator (SecureRandom). The choice is offered because the secure
|
||||
* random generator takes about 3.5 times longer to generate its random numbers and this performance hit may not be
|
||||
* worth the added security especially considering the basic generator is seeded with a cryptographically strong random
|
||||
* seed.
|
||||
* <p/>
|
||||
* Seeding the basic generator in this way effectively decouples the random numbers from the time component making it
|
||||
* virtually impossible to predict the random number component even if one had absolute knowledge of the System time.
|
||||
* Thanks to Ashutosh Narhari for the suggestion of using the static method to prime the basic random generator.
|
||||
* <p/>
|
||||
* Using the secure random option, this class complies with the statistical random number generator tests specified in
|
||||
* FIPS 140-2, Security Requirements for Cryptographic Modules, section 4.9.1.
|
||||
* <p/>
|
||||
* I converted all the pieces of the seed to a String before handing it over to the MD5 hash so that you could print it
|
||||
* out to make sure it contains the data you expect to see and to give a nice warm fuzzy. If you need better
|
||||
* performance, you may want to stick to byte[] arrays.
|
||||
* <p/>
|
||||
* I believe that it is important that the algorithm for generating random GUIDs be open for inspection and
|
||||
* modification. This class is free for all uses.
|
||||
*
|
||||
* @author Marc A. Mnich
|
||||
* @version 1.2.1 11/05/02
|
||||
*/
|
||||
public class RandomGuid {
|
||||
|
||||
private static Random random;
|
||||
|
||||
private static SecureRandom secureRandom;
|
||||
|
||||
private static String id;
|
||||
|
||||
private String guid;
|
||||
|
||||
/*
|
||||
* Static block to take care of one time secureRandom seed. It takes a few seconds to initialize SecureRandom. You
|
||||
* might want to consider removing this static block or replacing it with a "time since first loaded" seed to reduce
|
||||
* this time. This block will run only once per JVM instance.
|
||||
*/
|
||||
static {
|
||||
secureRandom = new SecureRandom();
|
||||
long secureInitializer = secureRandom.nextLong();
|
||||
random = new Random(secureInitializer);
|
||||
try {
|
||||
id = InetAddress.getLocalHost().toString();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor. With no specification of security option, this constructor defaults to lower security, high
|
||||
* performance.
|
||||
*/
|
||||
public RandomGuid() {
|
||||
getRandomGuid(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with security option. Setting secure true enables each random number generated to be
|
||||
* cryptographically strong. Secure false defaults to the standard Random function seeded with a single
|
||||
* cryptographically strong random number.
|
||||
*/
|
||||
public RandomGuid(boolean secure) {
|
||||
getRandomGuid(secure);
|
||||
}
|
||||
|
||||
/** Method to generate the random GUID. */
|
||||
private void getRandomGuid(boolean secure) {
|
||||
MessageDigest md5 = null;
|
||||
StringBuffer sbValueBeforeMD5 = new StringBuffer();
|
||||
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
long rand = 0;
|
||||
|
||||
if (secure) {
|
||||
rand = secureRandom.nextLong();
|
||||
}
|
||||
else {
|
||||
rand = random.nextLong();
|
||||
}
|
||||
|
||||
// This StringBuffer can be as long as you need; the MD5
|
||||
// hash will always return 128 bits. You can change
|
||||
// the seed to include anything you want here.
|
||||
// You could even stream a file through the MD5 making
|
||||
// the odds of guessing it at least as great as that
|
||||
// of guessing the contents of the file!
|
||||
sbValueBeforeMD5.append(id);
|
||||
sbValueBeforeMD5.append(":");
|
||||
sbValueBeforeMD5.append(Long.toString(time));
|
||||
sbValueBeforeMD5.append(":");
|
||||
sbValueBeforeMD5.append(Long.toString(rand));
|
||||
|
||||
String valueBeforeMD5 = sbValueBeforeMD5.toString();
|
||||
md5.update(valueBeforeMD5.getBytes());
|
||||
|
||||
byte[] array = md5.digest();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int j = 0; j < array.length; ++j) {
|
||||
int b = array[j] & 0xFF;
|
||||
if (b < 0x10) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(Integer.toHexString(b));
|
||||
}
|
||||
guid = sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to the standard format for GUID (Useful for SQL Server UniqueIdentifiers, etc). Example:
|
||||
* "C2FEEEAC-CFCD-11D1-8B05-00600806D9B6".
|
||||
*/
|
||||
public String toString() {
|
||||
String raw = guid.toUpperCase();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(raw.substring(0, 8));
|
||||
sb.append("-");
|
||||
sb.append(raw.substring(8, 12));
|
||||
sb.append("-");
|
||||
sb.append(raw.substring(12, 16));
|
||||
sb.append("-");
|
||||
sb.append(raw.substring(16, 20));
|
||||
sb.append("-");
|
||||
sb.append(raw.substring(20));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.messageid;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MessageIdStrategy} interface that uses a {@link RandomGuid} to generate a Message Id.
|
||||
* The GUID is prefixed by <code>urn:guid:</code>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class RandomGuidMessageIdStrategy implements MessageIdStrategy {
|
||||
|
||||
public static final String PREFIX = "urn:guid:";
|
||||
|
||||
private boolean secure;
|
||||
|
||||
/**
|
||||
* Sets whether or not the generated random numbers should be <i>secure</i>. If set to <code>true</code>, generated
|
||||
* GUIDs are cryptographically strong.
|
||||
*/
|
||||
public void setSecure(boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/** Returns <code>false</code>. */
|
||||
public boolean isDuplicate(URI messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public URI newMessageId(MessageContext messageContext) {
|
||||
return URI.create(PREFIX + new RandomGuid(secure).toString());
|
||||
}
|
||||
}
|
||||
@@ -16,28 +16,30 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing.messageid;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MessageIdStrategy} interface that uses a {@link UUID} to generate a Message Id. The UUID
|
||||
* is prefixed by <code>uuid:</code>.
|
||||
* is prefixed by <code>urn:uuid:</code>.
|
||||
* <p/>
|
||||
* Note that the {@link UUID} class is only available on Java 5 and above.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class UuidMessageIdStrategy implements MessageIdStrategy {
|
||||
|
||||
public static final String PREFIX = "uuid:";
|
||||
public static final String PREFIX = "urn:uuid:";
|
||||
|
||||
/** Returns <code>false</code>. */
|
||||
public boolean isDuplicate(String messageId) {
|
||||
public boolean isDuplicate(URI messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String newMessageId(SoapMessage message) {
|
||||
return PREFIX + UUID.randomUUID().toString();
|
||||
public URI newMessageId(MessageContext messageContext) {
|
||||
return URI.create(PREFIX + UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.ws.context.DefaultMessageContext;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
@@ -16,11 +19,9 @@ import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
|
||||
import org.easymock.MockControl;
|
||||
|
||||
public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWsAddressingTestCase {
|
||||
|
||||
protected WsAddressingInterceptor interceptor;
|
||||
private WsAddressingEndpointInterceptor interceptor;
|
||||
|
||||
private MockControl strategyControl;
|
||||
|
||||
@@ -30,7 +31,7 @@ public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWs
|
||||
strategyControl = MockControl.createControl(MessageIdStrategy.class);
|
||||
strategyMock = (MessageIdStrategy) strategyControl.getMock();
|
||||
strategyControl.expectAndDefaultReturn(strategyMock.isDuplicate(null), false);
|
||||
interceptor = new WsAddressingInterceptor(getVersion(), strategyMock, new WebServiceMessageSender[0]);
|
||||
interceptor = new WsAddressingEndpointInterceptor(getVersion(), strategyMock, new WebServiceMessageSender[0]);
|
||||
}
|
||||
|
||||
public void testUnderstands() throws Exception {
|
||||
@@ -45,7 +46,7 @@ public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWs
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleValidRequest() throws Exception {
|
||||
public void testValidRequest() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/valid.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
strategyControl.replay();
|
||||
@@ -55,49 +56,80 @@ public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWs
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleInvalidRequest() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/invalid.xml");
|
||||
public void testNoMessageId() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-no-message-id.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleRequest(context, null);
|
||||
assertFalse("Invalid request handled", result);
|
||||
assertFalse("Request with no MessageID 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 expectedResponse = loadSaajMessage(getTestPath() + "/response-no-message-id.xml");
|
||||
assertXMLEqual("Invalid response for message with no MessageID", expectedResponse,
|
||||
(SaajSoapMessage) context.getResponse());
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleAnonymousReplyTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/anonymous.xml");
|
||||
public void testNoReplyTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-no-reply-to.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
SaajSoapMessage response = (SaajSoapMessage) context.getResponse();
|
||||
String messageId = "uid:1234";
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(response), messageId);
|
||||
URI messageId = new URI("uid:1234");
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(context), messageId);
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleResponse(context, null);
|
||||
assertTrue("Anonymous request not handled", result);
|
||||
assertTrue("Request with no ReplyTo not handled", result);
|
||||
assertTrue("Message Context has no response", context.hasResponse());
|
||||
SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-anonymous.xml");
|
||||
assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse,
|
||||
(SaajSoapMessage) context.getResponse());
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleNoneReplyTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/none.xml");
|
||||
public void testAnonymousReplyTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-anonymous.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
URI messageId = new URI("uid:1234");
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(context), messageId);
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleResponse(context, null);
|
||||
assertTrue("Request with anonymous ReplyTo not handled", result);
|
||||
SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-anonymous.xml");
|
||||
assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse,
|
||||
(SaajSoapMessage) context.getResponse());
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testNoneReplyTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-none.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleResponse(context, null);
|
||||
assertFalse("None request handled", result);
|
||||
assertFalse("Message context has response", context.hasResponse());
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleOutOfBandReplyTo() throws Exception {
|
||||
public void testFaultTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-fault-to.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
SaajSoapMessage response = (SaajSoapMessage) context.getResponse();
|
||||
response.getSoapBody().addServerOrReceiverFault("Error", Locale.ENGLISH);
|
||||
URI messageId = new URI("uid:1234");
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(context), messageId);
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleFault(context, null);
|
||||
assertTrue("Request with anonymous FaultTo not handled", result);
|
||||
SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-fault-to.xml");
|
||||
assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse,
|
||||
(SaajSoapMessage) context.getResponse());
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testOutOfBandReplyTo() throws Exception {
|
||||
MockControl senderControl = MockControl.createControl(WebServiceMessageSender.class);
|
||||
WebServiceMessageSender senderMock = (WebServiceMessageSender) senderControl.getMock();
|
||||
|
||||
interceptor =
|
||||
new WsAddressingInterceptor(getVersion(), strategyMock, new WebServiceMessageSender[]{senderMock});
|
||||
interceptor = new WsAddressingEndpointInterceptor(getVersion(), strategyMock,
|
||||
new WebServiceMessageSender[]{senderMock});
|
||||
|
||||
MockControl connectionControl = MockControl.createControl(WebServiceConnection.class);
|
||||
WebServiceConnection connectionMock = (WebServiceConnection) connectionControl.getMock();
|
||||
@@ -106,8 +138,8 @@ public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWs
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
SaajSoapMessage response = (SaajSoapMessage) context.getResponse();
|
||||
|
||||
String messageId = "uid:1234";
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(response), messageId);
|
||||
URI messageId = new URI("uid:1234");
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(context), messageId);
|
||||
|
||||
URI uri = new URI("http://example.com/business/client1");
|
||||
senderControl.expectAndReturn(senderMock.supports(uri), true);
|
||||
@@ -121,6 +153,7 @@ public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWs
|
||||
|
||||
boolean result = interceptor.handleResponse(context, null);
|
||||
assertFalse("Out of Band request handled", result);
|
||||
assertFalse("Message context has response", context.hasResponse());
|
||||
|
||||
strategyControl.verify();
|
||||
senderControl.verify();
|
||||
|
||||
@@ -14,7 +14,7 @@ public class WsAddressingInterceptor200408Test extends AbstractWsAddressingInter
|
||||
return "200408";
|
||||
}
|
||||
|
||||
public void testHandleNoneReplyTo() throws Exception {
|
||||
public void testNoneReplyTo() throws Exception {
|
||||
// This version of the spec does not have none addresses
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ public class WsAddressingInterceptor200605Test extends AbstractWsAddressingInter
|
||||
}
|
||||
|
||||
protected String getTestPath() {
|
||||
return "200508";
|
||||
return "200605";
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing.messageid;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public abstract class AbstractMessageIdStrategyTestCase extends TestCase {
|
||||
|
||||
@@ -17,11 +18,11 @@ public abstract class AbstractMessageIdStrategyTestCase extends TestCase {
|
||||
|
||||
protected abstract MessageIdStrategy createProvider();
|
||||
|
||||
public void testProvider() {
|
||||
String messageId1 = strategy.newMessageId(null);
|
||||
assertTrue("Empty messageId", StringUtils.hasLength(messageId1));
|
||||
String messageId2 = strategy.newMessageId(null);
|
||||
assertTrue("Empty messageId", StringUtils.hasLength(messageId2));
|
||||
public void testStrategy() {
|
||||
URI messageId1 = strategy.newMessageId(null);
|
||||
assertNotNull("Empty messageId", messageId1);
|
||||
URI messageId2 = strategy.newMessageId(null);
|
||||
assertNotNull("Empty messageId", messageId2);
|
||||
assertFalse("Equal messageIds", messageId1.equals(messageId2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing.messageid;
|
||||
|
||||
public class UidMessageIdStrategyTest extends AbstractMessageIdStrategyTestCase {
|
||||
public class RandomGuidMessageIdStrategyTest extends AbstractMessageIdStrategyTestCase {
|
||||
|
||||
protected MessageIdStrategy createProvider() {
|
||||
return new UidMessageIdStrategy();
|
||||
return new RandomGuidMessageIdStrategy();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To S:mustUnderstand="1">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:To S:mustUnderstand="true">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
@@ -0,0 +1,20 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||
xmlns:f123="http://www.fabrikam123.example/svc53">
|
||||
<S:Header>
|
||||
<wsa:MessageID>uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff</wsa:MessageID>
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://example.com/business/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:FaultTo>
|
||||
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
|
||||
</wsa:FaultTo>
|
||||
<wsa:To S:mustUnderstand="true">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f123:Delete>
|
||||
<maxCount>42</maxCount>
|
||||
</f123:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -6,7 +6,7 @@
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://business456.example/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To S:mustUnderstand="1">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:To S:mustUnderstand="true">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
@@ -0,0 +1,17 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||
xmlns:f123="http://www.fabrikam123.example/svc53">
|
||||
<S:Header>
|
||||
<wsa:MessageID>uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff</wsa:MessageID>
|
||||
<wsa:To S:mustUnderstand="true">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:From>
|
||||
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
|
||||
</wsa:From>
|
||||
<wsa:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f123:Delete>
|
||||
<maxCount>42</maxCount>
|
||||
</f123:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -0,0 +1,18 @@
|
||||
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<env:Header>
|
||||
<wsa:MessageID>uid:1234</wsa:MessageID>
|
||||
<wsa:RelatesTo>uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff</wsa:RelatesTo>
|
||||
<wsa:To env:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
</env:Header>
|
||||
<env:Body>
|
||||
<env:Fault>
|
||||
<env:Code>
|
||||
<env:Value>env:Receiver</env:Value>
|
||||
</env:Code>
|
||||
<env:Reason>
|
||||
<env:Text xml:lang="en">Error</env:Text>
|
||||
</env:Reason>
|
||||
</env:Fault>
|
||||
</env:Body>
|
||||
</env:Envelope>
|
||||
@@ -6,7 +6,7 @@
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://example.com/business/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To S:mustUnderstand="1">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:To S:mustUnderstand="true">mailto:joe@fabrikam123.example</wsa:To>
|
||||
<wsa:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To>mailto:fabrikam@example.com</wsa:To>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<maxCount>42</maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -0,0 +1,18 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://example.com/business/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:FaultTo>
|
||||
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
|
||||
</wsa:FaultTo>
|
||||
<wsa:To>mailto:fabrikam@example.com</wsa:To>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<maxCount>42</maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -0,0 +1,15 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<!--<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>-->
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://example.com/business/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To>mailto:fabrikam@example.com</wsa:To>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<maxCount>42</maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -0,0 +1,12 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>
|
||||
<wsa:To>mailto:fabrikam@example.com</wsa:To>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<maxCount>42</maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -0,0 +1,15 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://www.w3.org/2005/08/addressing/none</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To>mailto:fabrikam@example.com</wsa:To>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<maxCount>42</maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -0,0 +1,8 @@
|
||||
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<env:Header>
|
||||
<wsa:MessageID>uid:1234</wsa:MessageID>
|
||||
<wsa:RelatesTo>http://example.com/someuniquestring</wsa:RelatesTo>
|
||||
<wsa:To env:mustUnderstand="true">http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
|
||||
</env:Header>
|
||||
<env:Body/>
|
||||
</env:Envelope>
|
||||
@@ -0,0 +1,17 @@
|
||||
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<env:Header>
|
||||
<wsa:MessageID>uid:1234</wsa:MessageID>
|
||||
<wsa:RelatesTo>http://example.com/someuniquestring</wsa:RelatesTo>
|
||||
<wsa:To env:mustUnderstand="true">http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
|
||||
</env:Header>
|
||||
<env:Body>
|
||||
<env:Fault>
|
||||
<env:Code>
|
||||
<env:Value>env:Receiver</env:Value>
|
||||
</env:Code>
|
||||
<env:Reason>
|
||||
<env:Text xml:lang="en">Error</env:Text>
|
||||
</env:Reason>
|
||||
</env:Fault>
|
||||
</env:Body>
|
||||
</env:Envelope>
|
||||
@@ -0,0 +1,19 @@
|
||||
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<env:Header/>
|
||||
<env:Body>
|
||||
<env:Fault>
|
||||
<env:Code>
|
||||
<env:Value>env:Sender</env:Value>
|
||||
<env:Subcode>
|
||||
<env:Value>wsa:MessageAddressingHeaderRequired</env:Value>
|
||||
</env:Subcode>
|
||||
</env:Code>
|
||||
<env:Reason>
|
||||
<env:Text xml:lang="en">
|
||||
A required header representing a Message Addressing Property is not present
|
||||
</env:Text>
|
||||
</env:Reason>
|
||||
</env:Fault>
|
||||
</env:Body>
|
||||
</env:Envelope>
|
||||
@@ -0,0 +1,15 @@
|
||||
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
||||
<S:Header>
|
||||
<wsa:MessageID>http://example.com/someuniquestring</wsa:MessageID>
|
||||
<wsa:ReplyTo>
|
||||
<wsa:Address>http://example.com/business/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To>mailto:fabrikam@example.com</wsa:To>
|
||||
<wsa:Action>http://example.com/fabrikam/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f:Delete xmlns:f="http://example.com/fabrikam">
|
||||
<maxCount>42</maxCount>
|
||||
</f:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
Reference in New Issue
Block a user