Working on WS-Addressing
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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.transform.TransformerException;
|
||||
|
||||
import org.springframework.core.JdkVersion;
|
||||
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;
|
||||
import org.springframework.ws.soap.addressing.messageid.UuidMessageIdProvider;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
|
||||
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 {
|
||||
|
||||
private String[] actorsOrRoles;
|
||||
|
||||
private boolean isUltimateReceiver = true;
|
||||
|
||||
private MessageIdProvider messageIdProvider;
|
||||
|
||||
private AbstractWsAddressingInterceptor[] addressingInterceptors;
|
||||
|
||||
private EndpointInterceptor[] preInterceptors;
|
||||
|
||||
private EndpointInterceptor[] postInterceptors;
|
||||
|
||||
/** Protected constructor */
|
||||
protected AbstractWsAddressingMapping() {
|
||||
addressingInterceptors = new AbstractWsAddressingInterceptor[]{new WsAddressing200408Interceptor(),
|
||||
new WsAddressing200508Interceptor()};
|
||||
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
|
||||
messageIdProvider = new UuidMessageIdProvider();
|
||||
}
|
||||
else {
|
||||
messageIdProvider = new UidMessageIdProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public final void setActorOrRole(String actorOrRole) {
|
||||
Assert.notNull(actorOrRole, "actorOrRole must not be null");
|
||||
actorsOrRoles = new String[]{actorOrRole};
|
||||
}
|
||||
|
||||
public final void setActorsOrRoles(String[] actorsOrRoles) {
|
||||
Assert.notEmpty(actorsOrRoles, "actorsOrRoles must not be empty");
|
||||
this.actorsOrRoles = actorsOrRoles;
|
||||
}
|
||||
|
||||
public final void setUltimateReceiver(boolean ultimateReceiver) {
|
||||
this.isUltimateReceiver = ultimateReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set additional interceptors to be applied before the implicit WS-Addressing interceptor, e.g.
|
||||
* <code>XwsSecurityInterceptor</code>.
|
||||
*/
|
||||
public final void setPreInterceptors(EndpointInterceptor[] preInterceptors) {
|
||||
this.preInterceptors = preInterceptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set additional interceptors to be applied after the implicit WS-Addressing interceptor, e.g.
|
||||
* <code>PayloadLoggingInterceptor</code>.
|
||||
*/
|
||||
public final void setPostInterceptors(EndpointInterceptor[] postInterceptors) {
|
||||
this.postInterceptors = postInterceptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the message id provider used for creating WS-Addressing MessageIds.
|
||||
* <p/>
|
||||
* By default, the {@link UuidMessageIdProvider} is used on Java 5 and higher, and the {@link UidMessageIdProvider}
|
||||
* on Java 1.4 and lower.
|
||||
*/
|
||||
public final void setMessageIdProvider(MessageIdProvider messageIdProvider) {
|
||||
this.messageIdProvider = messageIdProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the WS-Addressing interceptors to be supported by this mapping.
|
||||
* <p/>
|
||||
* By default, this includes the {@link WsAddressing200408Interceptor}, and the {@link
|
||||
* WsAddressing200508Interceptor}.
|
||||
*/
|
||||
public final void setAddressingInterceptors(AbstractWsAddressingInterceptor[] addressingInterceptors) {
|
||||
Assert.notEmpty(addressingInterceptors, "'addressingInterceptors' must not be empty");
|
||||
this.addressingInterceptors = addressingInterceptors;
|
||||
}
|
||||
|
||||
public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws TransformerException {
|
||||
Assert.isTrue(messageContext.getResponse() instanceof SoapMessage,
|
||||
"WsAddressingMapping requires a SoapMessage request");
|
||||
SoapMessage request = (SoapMessage) messageContext.getRequest();
|
||||
for (int i = 0; i < addressingInterceptors.length; i++) {
|
||||
AbstractWsAddressingInterceptor interceptor = addressingInterceptors[i];
|
||||
if (!understands(interceptor, request)) {
|
||||
continue;
|
||||
}
|
||||
MessageAddressingProperties requestMap = interceptor.getMessageAddressingProperties(request);
|
||||
if (requestMap == null) {
|
||||
return null;
|
||||
}
|
||||
Object endpoint = getEndpointInternal(requestMap);
|
||||
if (endpoint == null) {
|
||||
return null;
|
||||
}
|
||||
return new SoapEndpointInvocationChain(endpoint, getAllEndpointInterceptors(interceptor), actorsOrRoles,
|
||||
isUltimateReceiver);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean understands(AbstractWsAddressingInterceptor interceptor, SoapMessage request) {
|
||||
SoapHeader header = request.getSoapHeader();
|
||||
if (header != null) {
|
||||
for (Iterator iterator = header.examineAllHeaderElements(); iterator.hasNext();) {
|
||||
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
|
||||
if (interceptor.understands(headerElement)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected EndpointInterceptor[] getAllEndpointInterceptors(AbstractWsAddressingInterceptor interceptor) {
|
||||
if (preInterceptors == null) {
|
||||
preInterceptors = new EndpointInterceptor[0];
|
||||
}
|
||||
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] = interceptor;
|
||||
System.arraycopy(postInterceptors, 0, interceptors, preInterceptors.length + 1, postInterceptors.length);
|
||||
return interceptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup an endpoint for the given {@link MessageAddressingProperties}, returning <code>null</code> 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 <code>null</code>
|
||||
*/
|
||||
protected abstract Object getEndpointInternal(MessageAddressingProperties map);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-core/#eprs">Endpoint References</a>
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public final class EndpointReference {
|
||||
|
||||
private final String address;
|
||||
|
||||
private final List referenceProperties;
|
||||
|
||||
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");
|
||||
Assert.notNull(referenceParameters, "referenceParameters must not be null");
|
||||
this.address = address;
|
||||
this.referenceProperties = referenceProperties;
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o != null && o instanceof EndpointReference) {
|
||||
EndpointReference other = (EndpointReference) o;
|
||||
return address.equals(other.address);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return address.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "EndpointReference[" + address + ']';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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.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/>
|
||||
* In earlier versions of the spec, these properties were called Message Information Headers.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-core/#msgaddrprops">Message Addressing Properties</a>
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public final class MessageAddressingProperties {
|
||||
|
||||
private final String to;
|
||||
|
||||
private final EndpointReference from;
|
||||
|
||||
private final EndpointReference replyTo;
|
||||
|
||||
private final EndpointReference faultTo;
|
||||
|
||||
private final String action;
|
||||
|
||||
private final String messageId;
|
||||
|
||||
private final String relatesTo;
|
||||
|
||||
private final List referenceProperties;
|
||||
|
||||
private final List referenceParameters;
|
||||
|
||||
/*
|
||||
public MessageAddressingProperties(String to, EndpointReference replyTo, String action, String messageId) {
|
||||
this.to = to;
|
||||
this.replyTo = replyTo;
|
||||
this.action = action;
|
||||
this.messageId = messageId;
|
||||
this.from = null;
|
||||
this.faultTo = null;
|
||||
this.relatesTo = null;
|
||||
this.referenceProperties = Collections.EMPTY_LIST;
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
}
|
||||
*/
|
||||
|
||||
public MessageAddressingProperties(String to,
|
||||
EndpointReference from,
|
||||
EndpointReference replyTo,
|
||||
EndpointReference faultTo,
|
||||
String action,
|
||||
String messageId) {
|
||||
this.to = to;
|
||||
this.from = from;
|
||||
this.replyTo = replyTo;
|
||||
this.faultTo = faultTo;
|
||||
this.action = action;
|
||||
this.messageId = messageId;
|
||||
this.relatesTo = null;
|
||||
this.referenceProperties = Collections.EMPTY_LIST;
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/*
|
||||
private MessageAddressingProperties(String to,
|
||||
String action,
|
||||
String messageId,
|
||||
String relatesTo,
|
||||
List referenceProperties,
|
||||
List referenceParameters) {
|
||||
this.to = to;
|
||||
this.action = action;
|
||||
this.messageId = messageId;
|
||||
this.relatesTo = relatesTo;
|
||||
this.referenceProperties = referenceProperties;
|
||||
this.referenceParameters = referenceParameters;
|
||||
this.from = null;
|
||||
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;
|
||||
}
|
||||
|
||||
public EndpointReference getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public EndpointReference getReplyTo() {
|
||||
return replyTo != null ? replyTo : getFrom();
|
||||
}
|
||||
|
||||
public EndpointReference getFaultTo() {
|
||||
return faultTo != null ? faultTo : getReplyTo();
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public String getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
public String getRelatesTo() {
|
||||
return relatesTo;
|
||||
}
|
||||
|
||||
public List getReferenceProperties() {
|
||||
return Collections.unmodifiableList(referenceProperties);
|
||||
}
|
||||
|
||||
public List getReferenceParameters() {
|
||||
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)) &&
|
||||
!(faultTo != null && !StringUtils.hasLength(messageId));
|
||||
|
||||
}
|
||||
|
||||
public MessageAddressingProperties getResponseProperties(EndpointReference epr, String action, String messageId) {
|
||||
return new MessageAddressingProperties(epr, action, messageId, this.messageId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Provides WS-Addressing implementation classes.
|
||||
</body>
|
||||
</html>
|
||||
@@ -28,11 +28,15 @@ 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;
|
||||
import org.springframework.ws.soap.addressing.messageid.UuidMessageIdProvider;
|
||||
import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.messageid.UidMessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.messageid.UuidMessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressing200408;
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressing200605;
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressingVersion;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
|
||||
import org.springframework.ws.soap.server.SoapEndpointMapping;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
|
||||
/**
|
||||
@@ -47,23 +51,24 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
|
||||
private boolean isUltimateReceiver = true;
|
||||
|
||||
private MessageIdProvider messageIdProvider;
|
||||
private MessageIdStrategy messageIdStrategy;
|
||||
|
||||
private AbstractWsAddressingInterceptor[] addressingInterceptors;
|
||||
private WebServiceMessageSender[] messageSenders;
|
||||
|
||||
private WsAddressingVersion[] versions;
|
||||
|
||||
private EndpointInterceptor[] preInterceptors;
|
||||
|
||||
private EndpointInterceptor[] postInterceptors;
|
||||
|
||||
/** Protected constructor */
|
||||
/** Protected constructor. Initializes the default settings. */
|
||||
protected AbstractWsAddressingMapping() {
|
||||
addressingInterceptors = new AbstractWsAddressingInterceptor[]{new WsAddressing200408Interceptor(),
|
||||
new WsAddressing200508Interceptor()};
|
||||
this.versions = new WsAddressingVersion[]{new WsAddressing200408(), new WsAddressing200605()};
|
||||
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
|
||||
messageIdProvider = new UuidMessageIdProvider();
|
||||
messageIdStrategy = new UuidMessageIdStrategy();
|
||||
}
|
||||
else {
|
||||
messageIdProvider = new UidMessageIdProvider();
|
||||
messageIdStrategy = new UidMessageIdStrategy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,53 +105,54 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
/**
|
||||
* Sets the message id provider used for creating WS-Addressing MessageIds.
|
||||
* <p/>
|
||||
* By default, the {@link UuidMessageIdProvider} is used on Java 5 and higher, and the {@link UidMessageIdProvider}
|
||||
* By default, the {@link UuidMessageIdStrategy} is used on Java 5 and higher, and the {@link UidMessageIdStrategy}
|
||||
* on Java 1.4 and lower.
|
||||
*/
|
||||
public final void setMessageIdProvider(MessageIdProvider messageIdProvider) {
|
||||
this.messageIdProvider = messageIdProvider;
|
||||
public final void setMessageIdProvider(MessageIdStrategy messageIdStrategy) {
|
||||
this.messageIdStrategy = messageIdStrategy;
|
||||
}
|
||||
|
||||
public final void setMessageSenders(WebServiceMessageSender[] messageSenders) {
|
||||
this.messageSenders = messageSenders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the WS-Addressing interceptors to be supported by this mapping.
|
||||
* Sets the WS-Addressing versions to be supported by this mapping.
|
||||
* <p/>
|
||||
* By default, this includes the {@link WsAddressing200408Interceptor}, and the {@link
|
||||
* WsAddressing200508Interceptor}.
|
||||
* By default, this array is set to support {@link WsAddressing200408 the August 2004} and the {@link
|
||||
* WsAddressing200605 May 2006} versions of the specification.
|
||||
*/
|
||||
public final void setAddressingInterceptors(AbstractWsAddressingInterceptor[] addressingInterceptors) {
|
||||
Assert.notEmpty(addressingInterceptors, "'addressingInterceptors' must not be empty");
|
||||
this.addressingInterceptors = addressingInterceptors;
|
||||
public final void setVersions(WsAddressingVersion[] versions) {
|
||||
this.versions = versions;
|
||||
}
|
||||
|
||||
public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws TransformerException {
|
||||
Assert.isTrue(messageContext.getResponse() instanceof SoapMessage,
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse(),
|
||||
"WsAddressingMapping requires a SoapMessage request");
|
||||
SoapMessage request = (SoapMessage) messageContext.getRequest();
|
||||
for (int i = 0; i < addressingInterceptors.length; i++) {
|
||||
AbstractWsAddressingInterceptor interceptor = addressingInterceptors[i];
|
||||
if (!understands(interceptor, request)) {
|
||||
continue;
|
||||
for (int i = 0; i < versions.length; i++) {
|
||||
if (supports(versions[i], request)) {
|
||||
MessageAddressingProperties requestMap = versions[i].getMessageAddressingProperties(request);
|
||||
if (requestMap == null) {
|
||||
return null;
|
||||
}
|
||||
Object endpoint = getEndpointInternal(requestMap);
|
||||
if (endpoint == null) {
|
||||
return null;
|
||||
}
|
||||
return new SoapEndpointInvocationChain(endpoint, getAllEndpointInterceptors(versions[i]), actorsOrRoles,
|
||||
isUltimateReceiver);
|
||||
}
|
||||
MessageAddressingProperties requestMap = interceptor.getMessageAddressingProperties(request);
|
||||
if (requestMap == null) {
|
||||
return null;
|
||||
}
|
||||
Object endpoint = getEndpointInternal(requestMap);
|
||||
if (endpoint == null) {
|
||||
return null;
|
||||
}
|
||||
return new SoapEndpointInvocationChain(endpoint, getAllEndpointInterceptors(interceptor), actorsOrRoles,
|
||||
isUltimateReceiver);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean understands(AbstractWsAddressingInterceptor interceptor, SoapMessage request) {
|
||||
private boolean supports(WsAddressingVersion version, SoapMessage request) {
|
||||
SoapHeader header = request.getSoapHeader();
|
||||
if (header != null) {
|
||||
for (Iterator iterator = header.examineAllHeaderElements(); iterator.hasNext();) {
|
||||
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
|
||||
if (interceptor.understands(headerElement)) {
|
||||
if (version.understands(headerElement)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -154,7 +160,7 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
return false;
|
||||
}
|
||||
|
||||
protected EndpointInterceptor[] getAllEndpointInterceptors(AbstractWsAddressingInterceptor interceptor) {
|
||||
private EndpointInterceptor[] getAllEndpointInterceptors(WsAddressingVersion version) {
|
||||
if (preInterceptors == null) {
|
||||
preInterceptors = new EndpointInterceptor[0];
|
||||
}
|
||||
@@ -164,7 +170,7 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
EndpointInterceptor[] interceptors =
|
||||
new EndpointInterceptor[preInterceptors.length + postInterceptors.length + 1];
|
||||
System.arraycopy(preInterceptors, 0, interceptors, 0, preInterceptors.length);
|
||||
interceptors[preInterceptors.length] = interceptor;
|
||||
interceptors[preInterceptors.length] = new WsAddressingInterceptor(version, messageIdStrategy, messageSenders);
|
||||
System.arraycopy(postInterceptors, 0, interceptors, preInterceptors.length + 1, postInterceptors.length);
|
||||
return interceptors;
|
||||
}
|
||||
@@ -178,5 +184,4 @@ public abstract class AbstractWsAddressingMapping extends TransformerObjectSuppo
|
||||
*/
|
||||
protected abstract Object getEndpointInternal(MessageAddressingProperties map);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ public final class EndpointReference {
|
||||
* @param address the endpoint address
|
||||
*/
|
||||
public EndpointReference(String address) {
|
||||
Assert.notNull(address, "address must not be null");
|
||||
this.address = address;
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
this.referenceProperties = Collections.EMPTY_LIST;
|
||||
|
||||
@@ -50,20 +50,16 @@ public final class MessageAddressingProperties {
|
||||
|
||||
private final List referenceParameters;
|
||||
|
||||
/*
|
||||
public MessageAddressingProperties(String to, EndpointReference replyTo, String action, String messageId) {
|
||||
this.to = to;
|
||||
this.replyTo = replyTo;
|
||||
this.action = action;
|
||||
this.messageId = messageId;
|
||||
this.from = null;
|
||||
this.faultTo = null;
|
||||
this.relatesTo = null;
|
||||
this.referenceProperties = Collections.EMPTY_LIST;
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MessageAddressingProperties} with the given parameters.
|
||||
*
|
||||
* @param to the value of the destination property
|
||||
* @param from the value of the source endpoint property
|
||||
* @param replyTo the value of the reply endpoint property
|
||||
* @param faultTo the value of the fault endpoint property
|
||||
* @param action the value of the action property
|
||||
* @param messageId the value of the message id property
|
||||
*/
|
||||
public MessageAddressingProperties(String to,
|
||||
EndpointReference from,
|
||||
EndpointReference replyTo,
|
||||
@@ -81,25 +77,6 @@ public final class MessageAddressingProperties {
|
||||
this.referenceParameters = Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/*
|
||||
private MessageAddressingProperties(String to,
|
||||
String action,
|
||||
String messageId,
|
||||
String relatesTo,
|
||||
List referenceProperties,
|
||||
List referenceParameters) {
|
||||
this.to = to;
|
||||
this.action = action;
|
||||
this.messageId = messageId;
|
||||
this.relatesTo = relatesTo;
|
||||
this.referenceProperties = referenceProperties;
|
||||
this.referenceParameters = referenceParameters;
|
||||
this.from = null;
|
||||
this.replyTo = null;
|
||||
this.faultTo = null;
|
||||
}
|
||||
*/
|
||||
|
||||
private MessageAddressingProperties(EndpointReference epr, String action, String messageId, String relatesTo) {
|
||||
this.to = epr.getAddress();
|
||||
this.action = action;
|
||||
@@ -112,45 +89,55 @@ public final class MessageAddressingProperties {
|
||||
this.faultTo = null;
|
||||
}
|
||||
|
||||
/** Returns the value of the destination property. */
|
||||
public String getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
/** Returns the value of the source endpoint property. */
|
||||
public EndpointReference getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
/** Returns the value of the reply endpoint property. */
|
||||
public EndpointReference getReplyTo() {
|
||||
return replyTo != null ? replyTo : getFrom();
|
||||
return replyTo;
|
||||
}
|
||||
|
||||
/** Returns the value of the fault endpoint property. Defaults to {@link #getReplyTo()} if no fault endpoint is set. */
|
||||
public EndpointReference getFaultTo() {
|
||||
return faultTo != null ? faultTo : getReplyTo();
|
||||
}
|
||||
|
||||
/** Returns the value of the action property. */
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/** Returns the value of the message id property. */
|
||||
public String getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
/** Returns the value of the relationship property. */
|
||||
public String getRelatesTo() {
|
||||
return relatesTo;
|
||||
}
|
||||
|
||||
/** Returns the endpoint properties. Returns an empty list of none are set. */
|
||||
public List getReferenceProperties() {
|
||||
return Collections.unmodifiableList(referenceProperties);
|
||||
}
|
||||
|
||||
/** Returns the endpoint parameters. Returns an empty list of none are set. */
|
||||
public List getReferenceParameters() {
|
||||
return Collections.unmodifiableList(referenceParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the given {@link MessageAddressingProperties} are valid, i.e. whether all required elements are
|
||||
* listed.
|
||||
* 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.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return StringUtils.hasLength(to) && StringUtils.hasLength(action) &&
|
||||
@@ -163,4 +150,14 @@ public final class MessageAddressingProperties {
|
||||
return new MessageAddressingProperties(epr, action, messageId, this.messageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether is {@link MessageAddressingProperties} has all required properties. 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.
|
||||
*/
|
||||
public boolean hasRequiredProperties() {
|
||||
return StringUtils.hasLength(to) && StringUtils.hasLength(action) &&
|
||||
!(replyTo != null && !StringUtils.hasLength(messageId)) &&
|
||||
!(faultTo != null && !StringUtils.hasLength(messageId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import org.springframework.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* Exception thrown in cases on WS-Addressing errors.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class WsAddressingException extends WebServiceException {
|
||||
|
||||
public WsAddressingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public WsAddressingException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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.addressing.version.WsAddressingVersion;
|
||||
import org.springframework.ws.soap.server.SoapEndpointInterceptor;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
|
||||
/**
|
||||
* {@link SoapEndpointInterceptor} implementation that u
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class WsAddressingInterceptor implements SoapEndpointInterceptor {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(WsAddressingInterceptor.class);
|
||||
|
||||
private final WsAddressingVersion version;
|
||||
|
||||
private final MessageIdStrategy messageIdStrategy;
|
||||
|
||||
private final WebServiceMessageSender[] messageSenders;
|
||||
|
||||
WsAddressingInterceptor(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(),
|
||||
"WsAddressingInterceptor requires a SoapMessage request");
|
||||
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);
|
||||
}
|
||||
|
||||
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
|
||||
return handleResponseOrFault(messageContext);
|
||||
}
|
||||
|
||||
private boolean handleResponseOrFault(MessageContext messageContext) throws Exception {
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest(),
|
||||
"WsAddressingInterceptor requires a SoapMessage request");
|
||||
Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse(),
|
||||
"WsAddressingInterceptor requires a SoapMessage response");
|
||||
SoapMessage request = (SoapMessage) messageContext.getRequest();
|
||||
MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request);
|
||||
SoapMessage response = (SoapMessage) messageContext.getResponse();
|
||||
EndpointReference responseEpr = response.hasFault() ? requestMap.getFaultTo() : requestMap.getReplyTo();
|
||||
if (responseEpr == null || version.hasNoneAddress(responseEpr)) {
|
||||
logger.debug("Request has none reply address");
|
||||
return false;
|
||||
}
|
||||
String responseMessageId = messageIdStrategy.newMessageId(response);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Generated reply MessageID [" + responseMessageId + "]");
|
||||
}
|
||||
MessageAddressingProperties replyMap = requestMap.getResponseProperties(responseEpr, null, responseMessageId);
|
||||
version.addAddressingHeaders(response, replyMap);
|
||||
if (version.hasAnonymousAddress(responseEpr)) {
|
||||
logger.debug("Sending in-band reply");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Sending out-of-band 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) {
|
||||
logger.warn("Could not send out-of-band response to [" + uri + "]. " +
|
||||
"Configure WebServiceMessageSenders which support this uri.");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean understands(SoapHeaderElement header) {
|
||||
return version.understands(header);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +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;
|
||||
|
||||
/**
|
||||
* Defines the contract for a specific version of the WS-Addressing specification.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public interface WsAddressingVersion {
|
||||
|
||||
/** Returns the WS-Addressing namespace handled by this specification. */
|
||||
String getNamespaceUri();
|
||||
|
||||
/** Returns the prefix associated with the WS-Addressing namespace handled by this specification. */
|
||||
String getNamespacePrefix();
|
||||
|
||||
/*
|
||||
* Message addressing properties
|
||||
*/
|
||||
|
||||
/** Returns the qualified name of the <code>To</code> addressing header. */
|
||||
QName getToName();
|
||||
|
||||
/** Returns the qualified name of the <code>From</code> addressing header. */
|
||||
QName getFromName();
|
||||
|
||||
/** Returns the qualified name of the <code>ReplyTo</code> addressing header. */
|
||||
QName getReplyToName();
|
||||
|
||||
/** Returns the qualified name of the <code>FaultTo</code> addressing header. */
|
||||
QName getFaultToName();
|
||||
|
||||
/** Returns the qualified name of the <code>Action</code> addressing header. */
|
||||
QName getActionName();
|
||||
|
||||
/** Returns the qualified name of the <code>MessageID</code> addressing header. */
|
||||
QName getMessageIdName();
|
||||
|
||||
/** Returns the qualified name of the <code>RelatesTo</code> addressing header. */
|
||||
QName getRelatesToName();
|
||||
|
||||
/**
|
||||
* Returns the qualified name of the <code>Relationship</code> addressing attribute.
|
||||
*
|
||||
* @see #getRelationshipReply()
|
||||
*/
|
||||
QName getRelationshipTypeName();
|
||||
|
||||
/**
|
||||
* Returns the value of the <code>RelationshipType</code> attribute indicating a reply to the related message.
|
||||
*
|
||||
* @see #getRelationshipTypeName()
|
||||
*/
|
||||
String getRelationshipReply();
|
||||
|
||||
/**
|
||||
* Returns the qualified name of the <code>ReferenceProperties</code> in the endpoint reference. Returns
|
||||
* <code>null</code> when reference properties are not supported by this version of the spec.
|
||||
*/
|
||||
QName getReferencePropertiesName();
|
||||
|
||||
/**
|
||||
* Returns the qualified name of the <code>ReferenceParameters</code> in the endpoint reference. Returns
|
||||
* <code>null</code> when reference parameters are not supported by this version of the spec.
|
||||
*/
|
||||
QName getReferenceParametersName();
|
||||
|
||||
/*
|
||||
* Endpoint Reference
|
||||
*/
|
||||
|
||||
/** The qualified name of the <code>Address</code> in <code>EndpointReference</code>. */
|
||||
QName getAddressName();
|
||||
|
||||
/** The qualified name of the <code>Metadata</code> in <code>EndpointReference</code>. */
|
||||
QName getMetadataName();
|
||||
|
||||
/*
|
||||
* Address URIs
|
||||
*/
|
||||
|
||||
/** Returns the anonymous URI. */
|
||||
String getAnonymousUri();
|
||||
|
||||
/** Returns the none URI, or <code>null</code> 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 getMessageAddressingHeaderRequiredFaultSubcode();
|
||||
|
||||
/** Returns the reason of the fault that indicates that a header is missing. */
|
||||
String getMessageAddressingHeaderRequiredFaultReason();
|
||||
|
||||
}
|
||||
@@ -19,13 +19,27 @@ package org.springframework.ws.soap.addressing.messageid;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
/**
|
||||
* Declares the contract for classes that provide WS-Addressing MessageIds, either by generation or otherwise.
|
||||
* Strategy interface that encapsulates the creation and validation of WS-Addressing <code>MessageID</code>s.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface MessageIdProvider {
|
||||
public interface MessageIdStrategy {
|
||||
|
||||
/** Returns a WS-Addressing Message Id for the given message. */
|
||||
String getMessageId(SoapMessage message);
|
||||
/**
|
||||
* Indicates whether the given <code>MessageID</code> value is a duplicate or not
|
||||
*
|
||||
* @param messageId the message id
|
||||
* @return <code>true</code> if a duplicate; <code>false</code> otherwise
|
||||
*/
|
||||
boolean isDuplicate(String messageId);
|
||||
|
||||
/**
|
||||
* Returns a new WS-Addressing <code>MessageID</code> for the given message.
|
||||
*
|
||||
* @param message the SOAP message to create a new message id for
|
||||
* @return the new message id
|
||||
*/
|
||||
String newMessageId(SoapMessage message);
|
||||
|
||||
}
|
||||
@@ -21,16 +21,21 @@ import java.rmi.server.UID;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MessageIdProvider} interface that uses a {@link UID} to generate a Message Id. The UID
|
||||
* Implementation of the {@link MessageIdStrategy} interface that uses a {@link UID} to generate a Message Id. The UID
|
||||
* is prefixed by <code>uid:</code>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class UidMessageIdProvider implements MessageIdProvider {
|
||||
public class UidMessageIdStrategy implements MessageIdStrategy {
|
||||
|
||||
public static final String PREFIX = "uid:";
|
||||
|
||||
public String getMessageId(SoapMessage message) {
|
||||
/** Returns <code>false</code>. */
|
||||
public boolean isDuplicate(String messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String newMessageId(SoapMessage message) {
|
||||
return PREFIX + new UID().toString();
|
||||
}
|
||||
}
|
||||
@@ -21,18 +21,23 @@ import java.util.UUID;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MessageIdProvider} interface that uses a {@link UUID} to generate a Message Id. The UUID
|
||||
* Implementation of the {@link MessageIdStrategy} interface that uses a {@link UUID} to generate a Message Id. The UUID
|
||||
* is prefixed by <code>uuid:</code>.
|
||||
* <p/>
|
||||
* Note that the {@link UUID} class is only available on Java 5 and above.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class UuidMessageIdProvider implements MessageIdProvider {
|
||||
public class UuidMessageIdStrategy implements MessageIdStrategy {
|
||||
|
||||
public static final String PREFIX = "uuid:";
|
||||
|
||||
public String getMessageId(SoapMessage message) {
|
||||
/** Returns <code>false</code>. */
|
||||
public boolean isDuplicate(String messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String newMessageId(SoapMessage message) {
|
||||
return PREFIX + UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Contains various strategies for generating WS-Addressing MessageIDs.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,310 @@
|
||||
package org.springframework.ws.soap.addressing.version;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.soap.SoapFault;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.addressing.EndpointReference;
|
||||
import org.springframework.ws.soap.addressing.MessageAddressingProperties;
|
||||
import org.springframework.ws.soap.addressing.WsAddressingException;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link WsAddressingVersion} implementations. Uses {@link XPathExpression}s to retrieve
|
||||
* addressing information.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public abstract class AbstractWsAddressingVersion extends TransformerObjectSupport implements WsAddressingVersion {
|
||||
|
||||
private final XPathExpression toExpression;
|
||||
|
||||
private final XPathExpression actionExpression;
|
||||
|
||||
private final XPathExpression messageIdExpression;
|
||||
|
||||
private final XPathExpression fromExpression;
|
||||
|
||||
private final XPathExpression replyToExpression;
|
||||
|
||||
private final XPathExpression faultToExpression;
|
||||
|
||||
private final XPathExpression addressExpression;
|
||||
|
||||
private final XPathExpression referencePropertiesExpression;
|
||||
|
||||
private final XPathExpression referenceParametersExpression;
|
||||
|
||||
protected AbstractWsAddressingVersion() {
|
||||
Properties namespaces = new Properties();
|
||||
namespaces.setProperty(getNamespacePrefix(), getNamespaceUri());
|
||||
toExpression = createNormalizedExpression(getToName(), namespaces);
|
||||
actionExpression = createNormalizedExpression(getActionName(), namespaces);
|
||||
messageIdExpression = createNormalizedExpression(getMessageIdName(), namespaces);
|
||||
fromExpression = createExpression(getFromName(), namespaces);
|
||||
replyToExpression = createExpression(getReplyToName(), namespaces);
|
||||
faultToExpression = createExpression(getFaultToName(), namespaces);
|
||||
addressExpression = createNormalizedExpression(getAddressName(), namespaces);
|
||||
if (getReferencePropertiesName() != null) {
|
||||
referencePropertiesExpression = createChildrenExpression(getReferencePropertiesName(), namespaces);
|
||||
}
|
||||
else {
|
||||
referencePropertiesExpression = null;
|
||||
}
|
||||
if (getReferenceParametersName() != null) {
|
||||
referenceParametersExpression = createChildrenExpression(getReferenceParametersName(), namespaces);
|
||||
}
|
||||
else {
|
||||
referenceParametersExpression = null;
|
||||
}
|
||||
}
|
||||
|
||||
private XPathExpression createExpression(QName name, Properties namespaces) {
|
||||
String expression = name.getPrefix() + ":" + name.getLocalPart();
|
||||
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
|
||||
}
|
||||
|
||||
private XPathExpression createNormalizedExpression(QName name, Properties namespaces) {
|
||||
String expression = "normalize-space(" + name.getPrefix() + ":" + name.getLocalPart() + ")";
|
||||
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
|
||||
}
|
||||
|
||||
private XPathExpression createChildrenExpression(QName name, Properties namespaces) {
|
||||
String expression = name.getPrefix() + ":" + name.getLocalPart() + "/*";
|
||||
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
|
||||
}
|
||||
|
||||
public MessageAddressingProperties getMessageAddressingProperties(SoapMessage message) {
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
try {
|
||||
DOMResult domResult = new DOMResult();
|
||||
transform(header.getSource(), domResult);
|
||||
Document document = (Document) domResult.getNode();
|
||||
return document.getDocumentElement();
|
||||
}
|
||||
catch (TransformerException ex) {
|
||||
throw new WsAddressingException("Could not transform SoapHeader to Document", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 final boolean understands(SoapHeaderElement headerElement) {
|
||||
return getNamespaceUri().equals(headerElement.getName().getNamespaceURI());
|
||||
}
|
||||
|
||||
public final void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map) {
|
||||
SoapHeader header = message.getSoapHeader();
|
||||
SoapHeaderElement messageId = header.addHeaderElement(getMessageIdName());
|
||||
messageId.setText(map.getMessageId());
|
||||
SoapHeaderElement relatesTo = header.addHeaderElement(getRelatesToName());
|
||||
relatesTo.setText(map.getRelatesTo());
|
||||
SoapHeaderElement to = header.addHeaderElement(getToName());
|
||||
to.setText(map.getTo());
|
||||
to.setMustUnderstand(true);
|
||||
try {
|
||||
Transformer transformer = createTransformer();
|
||||
for (Iterator iterator = map.getReferenceParameters().iterator(); iterator.hasNext();) {
|
||||
Node node = (Node) iterator.next();
|
||||
DOMSource source = new DOMSource(node);
|
||||
transformer.transform(source, header.getResult());
|
||||
}
|
||||
for (Iterator iterator = map.getReferenceProperties().iterator(); iterator.hasNext();) {
|
||||
Node node = (Node) iterator.next();
|
||||
DOMSource source = new DOMSource(node);
|
||||
transformer.transform(source, header.getResult());
|
||||
}
|
||||
}
|
||||
catch (TransformerException ex) {
|
||||
throw new WsAddressingException("Could not add reference properties/parameters to message", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public final SoapFault addInvalidAddressingHeaderFault(SoapMessage message) {
|
||||
return addAddressingFault(message, getInvalidAddressingHeaderFaultSubcode(),
|
||||
getInvalidAddressingHeaderFaultReason());
|
||||
}
|
||||
|
||||
public final SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message) {
|
||||
return addAddressingFault(message, getMessageAddressingHeaderRequiredFaultSubcode(),
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Address URIs
|
||||
*/
|
||||
|
||||
public final boolean hasAnonymousAddress(EndpointReference epr) {
|
||||
String anonymous = getAnonymousUri();
|
||||
return anonymous != null && anonymous.equals(epr.getAddress());
|
||||
}
|
||||
|
||||
public final boolean hasNoneAddress(EndpointReference epr) {
|
||||
String none = getNoneUri();
|
||||
return none != null && none.equals(epr.getAddress());
|
||||
}
|
||||
|
||||
/** Returns the prefix associated with the WS-Addressing namespace handled by this specification. */
|
||||
protected String getNamespacePrefix() {
|
||||
return "wsa";
|
||||
}
|
||||
|
||||
/** Returns the WS-Addressing namespace handled by this specification. */
|
||||
protected abstract String getNamespaceUri();
|
||||
|
||||
/*
|
||||
* Message addressing properties
|
||||
*/
|
||||
|
||||
/** Returns the qualified name of the <code>To</code> addressing header. */
|
||||
protected QName getToName() {
|
||||
return new QName(getNamespaceUri(), "To", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the qualified name of the <code>From</code> addressing header. */
|
||||
protected QName getFromName() {
|
||||
return new QName(getNamespaceUri(), "From", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the qualified name of the <code>ReplyTo</code> addressing header. */
|
||||
protected QName getReplyToName() {
|
||||
return new QName(getNamespaceUri(), "ReplyTo", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the qualified name of the <code>FaultTo</code> addressing header. */
|
||||
protected QName getFaultToName() {
|
||||
return new QName(getNamespaceUri(), "FaultTo", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the qualified name of the <code>Action</code> addressing header. */
|
||||
protected QName getActionName() {
|
||||
return new QName(getNamespaceUri(), "Action", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the qualified name of the <code>MessageID</code> addressing header. */
|
||||
protected QName getMessageIdName() {
|
||||
return new QName(getNamespaceUri(), "MessageID", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/** Returns the qualified name of the <code>RelatesTo</code> addressing header. */
|
||||
protected QName getRelatesToName() {
|
||||
return new QName(getNamespaceUri(), "RelatesTo", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the qualified name of the <code>ReferenceProperties</code> in the endpoint reference. Returns
|
||||
* <code>null</code> when reference properties are not supported by this version of the spec.
|
||||
*/
|
||||
protected QName getReferencePropertiesName() {
|
||||
return new QName(getNamespaceUri(), "ReferenceProperties", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the qualified name of the <code>ReferenceParameters</code> in the endpoint reference. Returns
|
||||
* <code>null</code> when reference parameters are not supported by this version of the spec.
|
||||
*/
|
||||
protected QName getReferenceParametersName() {
|
||||
return new QName(getNamespaceUri(), "ReferenceParameters", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/*
|
||||
* Endpoint Reference
|
||||
*/
|
||||
|
||||
/** The qualified name of the <code>Address</code> in <code>EndpointReference</code>. */
|
||||
protected QName getAddressName() {
|
||||
return new QName(getNamespaceUri(), "Address", getNamespacePrefix());
|
||||
}
|
||||
|
||||
/*
|
||||
* Address URIs
|
||||
*/
|
||||
|
||||
/** Returns the anonymous URI. */
|
||||
protected abstract String getAnonymousUri();
|
||||
|
||||
/** Returns the none URI, or <code>null</code> if the spec does not define it. */
|
||||
protected abstract String getNoneUri();
|
||||
|
||||
/*
|
||||
* Faults
|
||||
*/
|
||||
|
||||
/** Returns the qualified name of the fault subcode that indicates that a header is missing. */
|
||||
protected abstract QName getMessageAddressingHeaderRequiredFaultSubcode();
|
||||
|
||||
/** Returns the reason of the fault that indicates that a header is missing. */
|
||||
protected abstract String getMessageAddressingHeaderRequiredFaultReason();
|
||||
|
||||
/** Returns the qualified name of the fault subcode that indicates that a header is invalid. */
|
||||
protected abstract QName getInvalidAddressingHeaderFaultSubcode();
|
||||
|
||||
/** Returns the reason of the fault that indicates that a header is invalid. */
|
||||
protected abstract String getInvalidAddressingHeaderFaultReason();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.springframework.ws.soap.addressing.version;
|
||||
|
||||
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, and supported by Axis 1 and 2, and XFire.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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 String getInvalidAddressingHeaderFaultReason() {
|
||||
return "A message information header is not valid and the message cannot be processed.";
|
||||
}
|
||||
|
||||
protected final QName getInvalidAddressingHeaderFaultSubcode() {
|
||||
return new QName(NAMESPACE_URI, "InvalidMessageInformationHeader", getNamespacePrefix());
|
||||
}
|
||||
|
||||
protected final String getMessageAddressingHeaderRequiredFaultReason() {
|
||||
return "A required message information header, To, MessageID, or Action, is not present.";
|
||||
}
|
||||
|
||||
protected final QName getMessageAddressingHeaderRequiredFaultSubcode() {
|
||||
return new QName(NAMESPACE_URI, "MessageInformationHeaderRequired", getNamespacePrefix());
|
||||
}
|
||||
|
||||
protected final String getNamespaceUri() {
|
||||
return NAMESPACE_URI;
|
||||
}
|
||||
|
||||
protected final String getNoneUri() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.ws.soap.addressing.version;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
/**
|
||||
* Implements the May 2006 edition of the WS-Addressing specification. This version of the specification is used by
|
||||
* Microsoft's Windows Communication Foundation (WCF), and supported by Axis 1 and 2.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
public class WsAddressing200605 extends AbstractWsAddressingVersion {
|
||||
|
||||
private static final String NAMESPACE_URI = "http://www.w3.org/2005/08/addressing";
|
||||
|
||||
protected String getNamespaceUri() {
|
||||
return NAMESPACE_URI;
|
||||
}
|
||||
|
||||
protected QName getReferencePropertiesName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final String getAnonymousUri() {
|
||||
return NAMESPACE_URI + "/anonymous";
|
||||
}
|
||||
|
||||
protected final String getNoneUri() {
|
||||
return NAMESPACE_URI + "/none";
|
||||
}
|
||||
|
||||
protected final QName getMessageAddressingHeaderRequiredFaultSubcode() {
|
||||
return new QName(NAMESPACE_URI, "MessageAddressingHeaderRequired", getNamespacePrefix());
|
||||
}
|
||||
|
||||
protected final String getMessageAddressingHeaderRequiredFaultReason() {
|
||||
return "A required header representing a Message Addressing Property is not present";
|
||||
}
|
||||
|
||||
protected QName getInvalidAddressingHeaderFaultSubcode() {
|
||||
return new QName(NAMESPACE_URI, "InvalidAddressingHeader", getNamespacePrefix());
|
||||
}
|
||||
|
||||
protected String getInvalidAddressingHeaderFaultReason() {
|
||||
return "A header representing a Message Addressing Property is not valid and the message cannot be processed";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.springframework.ws.soap.addressing.version;
|
||||
|
||||
import org.springframework.ws.soap.SoapFault;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.addressing.EndpointReference;
|
||||
import org.springframework.ws.soap.addressing.MessageAddressingProperties;
|
||||
|
||||
/**
|
||||
* Defines the contract for a specific version of the WS-Addressing specification.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public interface WsAddressingVersion {
|
||||
|
||||
/**
|
||||
* Returns the {@link MessageAddressingProperties} for the given message.
|
||||
*
|
||||
* @param message the message to find the map for
|
||||
* @return the message addressing properties
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-core/#msgaddrprops">Message Addressing Properties</a>
|
||||
*/
|
||||
MessageAddressingProperties getMessageAddressingProperties(SoapMessage message);
|
||||
|
||||
/**
|
||||
* Adds addressing SOAP headers to the given message, using the given {@link MessageAddressingProperties}.
|
||||
*
|
||||
* @param message the message to add the headers to
|
||||
* @param map the message addressing properties
|
||||
*/
|
||||
void addAddressingHeaders(SoapMessage message, MessageAddressingProperties map);
|
||||
|
||||
/**
|
||||
* Given a <code>SoapHeaderElement</code>, return whether or not this version understands it.
|
||||
*
|
||||
* @param headerElement the header
|
||||
* @return <code>true</code> if understood, <code>false</code> otherwise
|
||||
*/
|
||||
boolean understands(SoapHeaderElement headerElement);
|
||||
|
||||
/*
|
||||
* Address URIs
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 <a href="http://www.w3.org/TR/ws-addr-core/#formreplymsg">Formulating a Reply Message</a>
|
||||
*/
|
||||
boolean hasAnonymousAddress(EndpointReference epr);
|
||||
|
||||
/**
|
||||
* Indicates whether the given endpoint reference has a None address. Messages to be sent to this address will not
|
||||
* be sent.
|
||||
*
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-core/#sendmsgepr">Sending a Message to an EPR</a>
|
||||
*/
|
||||
boolean hasNoneAddress(EndpointReference epr);
|
||||
|
||||
/*
|
||||
* Faults
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds a Invalid Addressing Header fault to the given message.
|
||||
*
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-soap/#invalidmapfault">Invalid Addressing Header</a>
|
||||
*/
|
||||
SoapFault addInvalidAddressingHeaderFault(SoapMessage message);
|
||||
|
||||
/**
|
||||
* Adds a Message Addressing Header Required fault to the given message.
|
||||
*
|
||||
* @see <a href="http://www.w3.org/TR/ws-addr-soap/#missingmapfault">Message Addressing Header Required</a>
|
||||
*/
|
||||
SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Contains various implementations of the WS-Addressing specification.
|
||||
</body>
|
||||
</html>
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.io.InputStream;
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.soap.MimeHeaders;
|
||||
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;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
protected void onSetUp() throws Exception {
|
||||
}
|
||||
|
||||
protected SaajSoapMessage loadSaajMessage(String fileName) throws SOAPException, IOException {
|
||||
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));
|
||||
}
|
||||
finally {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -6,58 +6,61 @@ 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.addressing.messageid.MessageIdStrategy;
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressingVersion;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessage;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
|
||||
public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWsAddressingTestCase {
|
||||
|
||||
protected AbstractWsAddressingInterceptor interceptor;
|
||||
protected WsAddressingInterceptor interceptor;
|
||||
|
||||
private MockControl providerControl;
|
||||
private MockControl strategyControl;
|
||||
|
||||
private MessageIdProvider providerMock;
|
||||
private MessageIdStrategy strategyMock;
|
||||
|
||||
protected final void onSetUp() throws Exception {
|
||||
providerControl = MockControl.createControl(MessageIdProvider.class);
|
||||
providerMock = (MessageIdProvider) providerControl.getMock();
|
||||
interceptor = createInterceptor();
|
||||
interceptor.setMessageIdProvider(providerMock);
|
||||
strategyControl = MockControl.createControl(MessageIdStrategy.class);
|
||||
strategyMock = (MessageIdStrategy) strategyControl.getMock();
|
||||
strategyControl.expectAndDefaultReturn(strategyMock.isDuplicate(null), false);
|
||||
interceptor = new WsAddressingInterceptor(getVersion(), strategyMock, new WebServiceMessageSender[0]);
|
||||
}
|
||||
|
||||
public void testUnderstands() throws Exception {
|
||||
SaajSoapMessage validRequest = loadSaajMessage(getTestPath() + "/valid.xml");
|
||||
Iterator iterator = validRequest.getSoapHeader().examineAllHeaderElements();
|
||||
providerControl.replay();
|
||||
strategyControl.replay();
|
||||
while (iterator.hasNext()) {
|
||||
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
|
||||
assertTrue("Header [" + headerElement.getName() + " not understood",
|
||||
interceptor.understands(headerElement));
|
||||
}
|
||||
providerControl.verify();
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleValidRequest() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/valid.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
providerControl.replay();
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleRequest(context, null);
|
||||
assertTrue("Valid request not handled", result);
|
||||
assertFalse("Message Context has response", context.hasResponse());
|
||||
providerControl.verify();
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleInvalidRequest() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/invalid.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
providerControl.replay();
|
||||
strategyControl.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();
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleAnonymousReplyTo() throws Exception {
|
||||
@@ -65,38 +68,61 @@ public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWs
|
||||
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();
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(response), messageId);
|
||||
strategyControl.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();
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleNoneReplyTo() throws Exception {
|
||||
SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/none.xml");
|
||||
MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory));
|
||||
providerControl.replay();
|
||||
strategyControl.replay();
|
||||
boolean result = interceptor.handleResponse(context, null);
|
||||
assertFalse("None request handled", result);
|
||||
providerControl.verify();
|
||||
strategyControl.verify();
|
||||
}
|
||||
|
||||
public void testHandleOutOfBandReplyTo() throws Exception {
|
||||
MockControl senderControl = MockControl.createControl(WebServiceMessageSender.class);
|
||||
WebServiceMessageSender senderMock = (WebServiceMessageSender) senderControl.getMock();
|
||||
|
||||
interceptor =
|
||||
new WsAddressingInterceptor(getVersion(), strategyMock, new WebServiceMessageSender[]{senderMock});
|
||||
|
||||
MockControl connectionControl = MockControl.createControl(WebServiceConnection.class);
|
||||
WebServiceConnection connectionMock = (WebServiceConnection) connectionControl.getMock();
|
||||
|
||||
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();
|
||||
strategyControl.expectAndReturn(strategyMock.newMessageId(response), messageId);
|
||||
|
||||
String uri = "http://example.com/business/client1";
|
||||
senderControl.expectAndReturn(senderMock.supports(uri), true);
|
||||
senderControl.expectAndReturn(senderMock.createConnection(uri), connectionMock);
|
||||
connectionMock.send(response);
|
||||
connectionMock.close();
|
||||
|
||||
strategyControl.replay();
|
||||
senderControl.replay();
|
||||
connectionControl.replay();
|
||||
|
||||
boolean result = interceptor.handleResponse(context, null);
|
||||
assertFalse("Out of Band request handled", result);
|
||||
providerControl.verify();
|
||||
|
||||
strategyControl.verify();
|
||||
senderControl.verify();
|
||||
connectionControl.verify();
|
||||
}
|
||||
|
||||
protected abstract AbstractWsAddressingInterceptor createInterceptor();
|
||||
protected abstract WsAddressingVersion getVersion();
|
||||
|
||||
protected abstract String getTestPath();
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressing200408;
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressingVersion;
|
||||
|
||||
public class WsAddressingInterceptor200408Test extends AbstractWsAddressingInterceptorTestCase {
|
||||
|
||||
protected WsAddressingVersion getVersion() {
|
||||
return new WsAddressing200408();
|
||||
}
|
||||
|
||||
protected String getTestPath() {
|
||||
return "200408";
|
||||
}
|
||||
|
||||
public void testHandleNoneReplyTo() throws Exception {
|
||||
// This version of the spec does not have none addresses
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.ws.soap.addressing;
|
||||
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressing200605;
|
||||
import org.springframework.ws.soap.addressing.version.WsAddressingVersion;
|
||||
|
||||
public class WsAddressingInterceptor200605Test extends AbstractWsAddressingInterceptorTestCase {
|
||||
|
||||
protected WsAddressingVersion getVersion() {
|
||||
return new WsAddressing200605();
|
||||
}
|
||||
|
||||
protected String getTestPath() {
|
||||
return "200508";
|
||||
}
|
||||
}
|
||||
@@ -19,20 +19,20 @@ package org.springframework.ws.soap.addressing.messageid;
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public abstract class AbstractMessageIdProviderTestCase extends TestCase {
|
||||
public abstract class AbstractMessageIdStrategyTestCase extends TestCase {
|
||||
|
||||
private MessageIdProvider provider;
|
||||
private MessageIdStrategy strategy;
|
||||
|
||||
protected final void setUp() throws Exception {
|
||||
provider = createProvider();
|
||||
strategy = createProvider();
|
||||
}
|
||||
|
||||
protected abstract MessageIdProvider createProvider();
|
||||
protected abstract MessageIdStrategy createProvider();
|
||||
|
||||
public void testProvider() {
|
||||
String messageId1 = provider.getMessageId(null);
|
||||
String messageId1 = strategy.newMessageId(null);
|
||||
assertTrue("Empty messageId", StringUtils.hasLength(messageId1));
|
||||
String messageId2 = provider.getMessageId(null);
|
||||
String messageId2 = strategy.newMessageId(null);
|
||||
assertTrue("Empty messageId", StringUtils.hasLength(messageId2));
|
||||
assertFalse("Equal messageIds", messageId1.equals(messageId2));
|
||||
}
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing.messageid;
|
||||
|
||||
public class UidMessageIdProviderTest extends AbstractMessageIdProviderTestCase {
|
||||
public class UidMessageIdStrategyTest extends AbstractMessageIdStrategyTestCase {
|
||||
|
||||
protected MessageIdProvider createProvider() {
|
||||
return new UidMessageIdProvider();
|
||||
protected MessageIdStrategy createProvider() {
|
||||
return new UidMessageIdStrategy();
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.springframework.ws.soap.addressing.messageid;
|
||||
|
||||
public class UuidMessageIdProviderTest extends AbstractMessageIdProviderTestCase {
|
||||
public class UuidMessageIdStrategyTest extends AbstractMessageIdStrategyTestCase {
|
||||
|
||||
protected MessageIdProvider createProvider() {
|
||||
return new UuidMessageIdProvider();
|
||||
protected MessageIdStrategy createProvider() {
|
||||
return new UuidMessageIdStrategy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<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://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:Action>http://fabrikam123.example/mail/Delete</wsa:Action>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<f123:Delete>
|
||||
<maxCount>42</maxCount>
|
||||
</f123:Delete>
|
||||
</S:Body>
|
||||
</S:Envelope>
|
||||
@@ -1,17 +0,0 @@
|
||||
<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://business456.example/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To S:mustUnderstand="1">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>
|
||||
@@ -1,9 +0,0 @@
|
||||
<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:Envelope>
|
||||
@@ -1,19 +0,0 @@
|
||||
<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:MessageInformationHeaderRequired</env:Value>
|
||||
</env:Subcode>
|
||||
</env:Code>
|
||||
<env:Reason>
|
||||
<env:Text xml:lang="en">
|
||||
A required message information header, To, MessageID, or Action, is not present.
|
||||
</env:Text>
|
||||
</env:Reason>
|
||||
</env:Fault>
|
||||
</env:Body>
|
||||
</env:Envelope>
|
||||
@@ -1,17 +0,0 @@
|
||||
<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://business456.example/client1</wsa:Address>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To S:mustUnderstand="1">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>
|
||||
@@ -1,15 +0,0 @@
|
||||
<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>
|
||||
@@ -1,15 +0,0 @@
|
||||
<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>
|
||||
@@ -1,15 +0,0 @@
|
||||
<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>
|
||||
@@ -1,8 +0,0 @@
|
||||
<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>
|
||||
@@ -1,19 +0,0 @@
|
||||
<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>
|
||||
@@ -1,15 +0,0 @@
|
||||
<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>
|
||||
@@ -1,24 +0,0 @@
|
||||
<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://business456.example/client1</wsa:Address>
|
||||
<wsa:ReferenceProperties>
|
||||
<f123:CustomerKey>123456789</f123:CustomerKey>
|
||||
</wsa:ReferenceProperties>
|
||||
<wsa:ReferenceParameters>
|
||||
<f123:ShoppingCart>ABCDEFG</f123:ShoppingCart>
|
||||
</wsa:ReferenceParameters>
|
||||
</wsa:ReplyTo>
|
||||
<wsa:To S:mustUnderstand="1">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>
|
||||
Reference in New Issue
Block a user