From ac154dd40b938c65ec8036d67e309a11882dee0d Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Sun, 7 Oct 2007 12:20:57 +0000 Subject: [PATCH] Working on WS-Addressing --- ...ctVersionBasedWsAddressingInterceptor.java | 0 .../AbstractWsAddressingInterceptor.java | 0 .../AbstractWsAddressingMapping.java | 182 ++++++++++ .../AbstractWsAddressingVersion.java | 0 .../ws/addressing/EndpointReference.java | 104 ++++++ .../MessageAddressingProperties.java | 166 ++++++++++ .../WsAddressing200408Interceptor.java | 0 .../WsAddressing200508Interceptor.java | 0 .../ws/addressing/package.html | 5 + .../AbstractWsAddressingMapping.java | 83 ++--- .../ws/soap/addressing/EndpointReference.java | 1 + .../MessageAddressingProperties.java | 69 ++-- .../addressing/WsAddressingException.java | 20 ++ .../addressing/WsAddressingInterceptor.java | 126 +++++++ .../soap/addressing/WsAddressingVersion.java | 115 ------- ...IdProvider.java => MessageIdStrategy.java} | 22 +- ...rovider.java => UidMessageIdStrategy.java} | 11 +- ...ovider.java => UuidMessageIdStrategy.java} | 11 +- .../ws/soap/addressing/messageid/package.html | 5 + .../version/AbstractWsAddressingVersion.java | 310 ++++++++++++++++++ .../version/WsAddressing200408.java | 44 +++ .../version/WsAddressing200605.java | 49 +++ .../version/WsAddressingVersion.java | 80 +++++ .../ws/soap/addressing/version/package.html | 5 + ...stractWsAddressingInterceptorTestCase.java | 103 ++++++ .../AbstractWsAddressingTestCase.java | 62 ++++ .../WsAddressing200408InterceptorTest.java | 0 .../WsAddressing200508InterceptorTest.java | 0 ...stractWsAddressingInterceptorTestCase.java | 72 ++-- .../WsAddressingInterceptor200408Test.java | 19 ++ .../WsAddressingInterceptor200605Test.java | 15 + ...=> AbstractMessageIdStrategyTestCase.java} | 12 +- ...est.java => UidMessageIdStrategyTest.java} | 6 +- ...st.java => UuidMessageIdStrategyTest.java} | 6 +- .../ws/soap/addressing/200408/anonymous.xml | 17 - .../ws/soap/addressing/200408/invalid.xml | 17 - .../addressing/200408/response-anonymous.xml | 9 - .../addressing/200408/response-invalid.xml | 19 -- .../ws/soap/addressing/200408/valid.xml | 17 - .../ws/soap/addressing/200508/anonymous.xml | 15 - .../ws/soap/addressing/200508/invalid.xml | 15 - .../ws/soap/addressing/200508/none.xml | 15 - .../addressing/200508/response-anonymous.xml | 8 - .../addressing/200508/response-invalid.xml | 19 -- .../ws/soap/addressing/200508/valid.xml | 15 - .../ws/soap/addressing/request-200408.xml | 24 -- 46 files changed, 1468 insertions(+), 425 deletions(-) rename sandbox/src/main/java/org/springframework/ws/{soap => }/addressing/AbstractVersionBasedWsAddressingInterceptor.java (100%) rename sandbox/src/main/java/org/springframework/ws/{soap => }/addressing/AbstractWsAddressingInterceptor.java (100%) create mode 100644 sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingMapping.java rename sandbox/src/main/java/org/springframework/ws/{soap => }/addressing/AbstractWsAddressingVersion.java (100%) create mode 100644 sandbox/src/main/java/org/springframework/ws/addressing/EndpointReference.java create mode 100644 sandbox/src/main/java/org/springframework/ws/addressing/MessageAddressingProperties.java rename sandbox/src/main/java/org/springframework/ws/{soap => }/addressing/WsAddressing200408Interceptor.java (100%) rename sandbox/src/main/java/org/springframework/ws/{soap => }/addressing/WsAddressing200508Interceptor.java (100%) create mode 100644 sandbox/src/main/java/org/springframework/ws/addressing/package.html create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingException.java create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor.java delete mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java rename sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/{MessageIdProvider.java => MessageIdStrategy.java} (52%) rename sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/{UidMessageIdProvider.java => UidMessageIdStrategy.java} (76%) rename sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/{UuidMessageIdProvider.java => UuidMessageIdStrategy.java} (78%) create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/package.html create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/version/AbstractWsAddressingVersion.java create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200408.java create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200605.java create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressingVersion.java create mode 100644 sandbox/src/main/java/org/springframework/ws/soap/addressing/version/package.html create mode 100644 sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingInterceptorTestCase.java create mode 100644 sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingTestCase.java rename sandbox/src/test/java/org/springframework/ws/{soap => }/addressing/WsAddressing200408InterceptorTest.java (100%) rename sandbox/src/test/java/org/springframework/ws/{soap => }/addressing/WsAddressing200508InterceptorTest.java (100%) create mode 100644 sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200408Test.java create mode 100644 sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200605Test.java rename sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/{AbstractMessageIdProviderTestCase.java => AbstractMessageIdStrategyTestCase.java} (77%) rename sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/{UidMessageIdProviderTest.java => UidMessageIdStrategyTest.java} (79%) rename sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/{UuidMessageIdProviderTest.java => UuidMessageIdStrategyTest.java} (79%) delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/invalid.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-anonymous.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-invalid.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/valid.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/anonymous.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/invalid.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/none.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-anonymous.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-invalid.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/valid.xml delete mode 100644 sandbox/src/test/resources/org/springframework/ws/soap/addressing/request-200408.xml diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractVersionBasedWsAddressingInterceptor.java b/sandbox/src/main/java/org/springframework/ws/addressing/AbstractVersionBasedWsAddressingInterceptor.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractVersionBasedWsAddressingInterceptor.java rename to sandbox/src/main/java/org/springframework/ws/addressing/AbstractVersionBasedWsAddressingInterceptor.java diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptor.java b/sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingInterceptor.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptor.java rename to sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingInterceptor.java diff --git a/sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingMapping.java b/sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingMapping.java new file mode 100644 index 00000000..337d6115 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingMapping.java @@ -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. + * XwsSecurityInterceptor. + */ + public final void setPreInterceptors(EndpointInterceptor[] preInterceptors) { + this.preInterceptors = preInterceptors; + } + + /** + * Set additional interceptors to be applied after the implicit WS-Addressing interceptor, e.g. + * PayloadLoggingInterceptor. + */ + public final void setPostInterceptors(EndpointInterceptor[] postInterceptors) { + this.postInterceptors = postInterceptors; + } + + /** + * Sets the message id provider used for creating WS-Addressing MessageIds. + *

+ * 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. + *

+ * 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 null if no specific + * one is found. This template method is called by {@link #getEndpoint(MessageContext)}. + * + * @param map the message addressing properties + * @return the endpoint, or null + */ + protected abstract Object getEndpointInternal(MessageAddressingProperties map); + + +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingVersion.java b/sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingVersion.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingVersion.java rename to sandbox/src/main/java/org/springframework/ws/addressing/AbstractWsAddressingVersion.java diff --git a/sandbox/src/main/java/org/springframework/ws/addressing/EndpointReference.java b/sandbox/src/main/java/org/springframework/ws/addressing/EndpointReference.java new file mode 100644 index 00000000..be18e9bf --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/addressing/EndpointReference.java @@ -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. + *

+ * In earlier versions of the spec, these properties were called Message Information Headers. + * + * @author Arjen Poutsma + * @see Endpoint References + * @since 1.1.0 + */ +public final class EndpointReference { + + private final String address; + + 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 + ']'; + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/addressing/MessageAddressingProperties.java b/sandbox/src/main/java/org/springframework/ws/addressing/MessageAddressingProperties.java new file mode 100644 index 00000000..ee281281 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/addressing/MessageAddressingProperties.java @@ -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. + *

+ * In earlier versions of the spec, these properties were called Message Information Headers. + * + * @author Arjen Poutsma + * @see Message Addressing Properties + * @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); + } + +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408Interceptor.java b/sandbox/src/main/java/org/springframework/ws/addressing/WsAddressing200408Interceptor.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200408Interceptor.java rename to sandbox/src/main/java/org/springframework/ws/addressing/WsAddressing200408Interceptor.java diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200508Interceptor.java b/sandbox/src/main/java/org/springframework/ws/addressing/WsAddressing200508Interceptor.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressing200508Interceptor.java rename to sandbox/src/main/java/org/springframework/ws/addressing/WsAddressing200508Interceptor.java diff --git a/sandbox/src/main/java/org/springframework/ws/addressing/package.html b/sandbox/src/main/java/org/springframework/ws/addressing/package.html new file mode 100644 index 00000000..b859632d --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/addressing/package.html @@ -0,0 +1,5 @@ + + +Provides WS-Addressing implementation classes. + + \ No newline at end of file diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java index 337d6115..2c40c8c1 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/AbstractWsAddressingMapping.java @@ -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. *

- * 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. *

- * 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); - } diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java index be18e9bf..8681f4e2 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/EndpointReference.java @@ -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; diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java index ee281281..a6b10daf 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/MessageAddressingProperties.java @@ -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 true 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 true + * 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)); + } } diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingException.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingException.java new file mode 100644 index 00000000..ae5b3b97 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingException.java @@ -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); + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor.java new file mode 100644 index 00000000..7b143605 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor.java @@ -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); + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java deleted file mode 100644 index 5d7b5430..00000000 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/WsAddressingVersion.java +++ /dev/null @@ -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 To addressing header. */ - QName getToName(); - - /** Returns the qualified name of the From addressing header. */ - QName getFromName(); - - /** Returns the qualified name of the ReplyTo addressing header. */ - QName getReplyToName(); - - /** Returns the qualified name of the FaultTo addressing header. */ - QName getFaultToName(); - - /** Returns the qualified name of the Action addressing header. */ - QName getActionName(); - - /** Returns the qualified name of the MessageID addressing header. */ - QName getMessageIdName(); - - /** Returns the qualified name of the RelatesTo addressing header. */ - QName getRelatesToName(); - - /** - * Returns the qualified name of the Relationship addressing attribute. - * - * @see #getRelationshipReply() - */ - QName getRelationshipTypeName(); - - /** - * Returns the value of the RelationshipType attribute indicating a reply to the related message. - * - * @see #getRelationshipTypeName() - */ - String getRelationshipReply(); - - /** - * Returns the qualified name of the ReferenceProperties in the endpoint reference. Returns - * null when reference properties are not supported by this version of the spec. - */ - QName getReferencePropertiesName(); - - /** - * Returns the qualified name of the ReferenceParameters in the endpoint reference. Returns - * null when reference parameters are not supported by this version of the spec. - */ - QName getReferenceParametersName(); - - /* - * Endpoint Reference - */ - - /** The qualified name of the Address in EndpointReference. */ - QName getAddressName(); - - /** The qualified name of the Metadata in EndpointReference. */ - QName getMetadataName(); - - /* - * Address URIs - */ - - /** Returns the anonymous URI. */ - String getAnonymousUri(); - - /** Returns the none URI, or null if the spec does not define it. */ - String getNoneUri(); - - /* - * Faults - */ - - /** Returns the qualified name of the fault subcode that indicates that a header is missing. */ - QName getMessageAddressingHeaderRequiredFaultSubcode(); - - /** Returns the reason of the fault that indicates that a header is missing. */ - String getMessageAddressingHeaderRequiredFaultReason(); - -} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdProvider.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java similarity index 52% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdProvider.java rename to sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java index 32301331..c42d4ac9 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdProvider.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/MessageIdStrategy.java @@ -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 MessageIDs. * * @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 MessageID value is a duplicate or not + * + * @param messageId the message id + * @return true if a duplicate; false otherwise + */ + boolean isDuplicate(String messageId); + + /** + * Returns a new WS-Addressing MessageID 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); } diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdProvider.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdStrategy.java similarity index 76% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdProvider.java rename to sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdStrategy.java index 1ba88e3a..48b15d7f 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdProvider.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdStrategy.java @@ -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 uid:. * * @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 false. */ + public boolean isDuplicate(String messageId) { + return false; + } + + public String newMessageId(SoapMessage message) { return PREFIX + new UID().toString(); } } diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java similarity index 78% rename from sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java rename to sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java index 82d6b9ed..40ce94a2 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProvider.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategy.java @@ -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 uuid:. *

* 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 false. */ + public boolean isDuplicate(String messageId) { + return false; + } + + public String newMessageId(SoapMessage message) { return PREFIX + UUID.randomUUID().toString(); } } \ No newline at end of file diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/package.html b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/package.html new file mode 100644 index 00000000..672410ae --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/messageid/package.html @@ -0,0 +1,5 @@ + + +Contains various strategies for generating WS-Addressing MessageIDs. + + \ No newline at end of file diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/AbstractWsAddressingVersion.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/AbstractWsAddressingVersion.java new file mode 100644 index 00000000..d23b6507 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/AbstractWsAddressingVersion.java @@ -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 To addressing header. */ + protected QName getToName() { + return new QName(getNamespaceUri(), "To", getNamespacePrefix()); + } + + /** Returns the qualified name of the From addressing header. */ + protected QName getFromName() { + return new QName(getNamespaceUri(), "From", getNamespacePrefix()); + } + + /** Returns the qualified name of the ReplyTo addressing header. */ + protected QName getReplyToName() { + return new QName(getNamespaceUri(), "ReplyTo", getNamespacePrefix()); + } + + /** Returns the qualified name of the FaultTo addressing header. */ + protected QName getFaultToName() { + return new QName(getNamespaceUri(), "FaultTo", getNamespacePrefix()); + } + + /** Returns the qualified name of the Action addressing header. */ + protected QName getActionName() { + return new QName(getNamespaceUri(), "Action", getNamespacePrefix()); + } + + /** Returns the qualified name of the MessageID addressing header. */ + protected QName getMessageIdName() { + return new QName(getNamespaceUri(), "MessageID", getNamespacePrefix()); + } + + /** Returns the qualified name of the RelatesTo addressing header. */ + protected QName getRelatesToName() { + return new QName(getNamespaceUri(), "RelatesTo", getNamespacePrefix()); + } + + /** + * Returns the qualified name of the ReferenceProperties in the endpoint reference. Returns + * null 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 ReferenceParameters in the endpoint reference. Returns + * null 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 Address in EndpointReference. */ + protected QName getAddressName() { + return new QName(getNamespaceUri(), "Address", getNamespacePrefix()); + } + + /* + * Address URIs + */ + + /** Returns the anonymous URI. */ + protected abstract String getAnonymousUri(); + + /** Returns the none URI, or null 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(); +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200408.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200408.java new file mode 100644 index 00000000..611b7613 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200408.java @@ -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 Web Services Addressing, August 2004 + * @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; + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200605.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200605.java new file mode 100644 index 00000000..bacebae8 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressing200605.java @@ -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 Web Services Addressing, August 2004 + * @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"; + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressingVersion.java b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressingVersion.java new file mode 100644 index 00000000..1c128bcf --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/WsAddressingVersion.java @@ -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 Message Addressing Properties + */ + 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 SoapHeaderElement, return whether or not this version understands it. + * + * @param headerElement the header + * @return true if understood, false 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 Formulating a Reply Message + */ + 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 Sending a Message to an EPR + */ + boolean hasNoneAddress(EndpointReference epr); + + /* + * Faults + */ + + /** + * Adds a Invalid Addressing Header fault to the given message. + * + * @see Invalid Addressing Header + */ + SoapFault addInvalidAddressingHeaderFault(SoapMessage message); + + /** + * Adds a Message Addressing Header Required fault to the given message. + * + * @see Message Addressing Header Required + */ + SoapFault addMessageAddressingHeaderRequiredFault(SoapMessage message); + +} diff --git a/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/package.html b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/package.html new file mode 100644 index 00000000..6ed08533 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/soap/addressing/version/package.html @@ -0,0 +1,5 @@ + + +Contains various implementations of the WS-Addressing specification. + + \ No newline at end of file diff --git a/sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingInterceptorTestCase.java b/sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingInterceptorTestCase.java new file mode 100644 index 00000000..d97107d3 --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingInterceptorTestCase.java @@ -0,0 +1,103 @@ +package org.springframework.ws.soap.addressing; + +import java.util.Iterator; + +import org.easymock.MockControl; +import org.springframework.ws.context.DefaultMessageContext; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.soap.SoapHeaderElement; +import org.springframework.ws.soap.addressing.messageid.MessageIdProvider; +import org.springframework.ws.soap.saaj.SaajSoapMessage; +import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; + +public abstract class AbstractWsAddressingInterceptorTestCase extends AbstractWsAddressingTestCase { + + protected AbstractWsAddressingInterceptor interceptor; + + private MockControl providerControl; + + private MessageIdProvider providerMock; + + protected final void onSetUp() throws Exception { + providerControl = MockControl.createControl(MessageIdProvider.class); + providerMock = (MessageIdProvider) providerControl.getMock(); + interceptor = createInterceptor(); + interceptor.setMessageIdProvider(providerMock); + } + + public void testUnderstands() throws Exception { + SaajSoapMessage validRequest = loadSaajMessage(getTestPath() + "/valid.xml"); + Iterator iterator = validRequest.getSoapHeader().examineAllHeaderElements(); + providerControl.replay(); + while (iterator.hasNext()) { + SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next(); + assertTrue("Header [" + headerElement.getName() + " not understood", + interceptor.understands(headerElement)); + } + providerControl.verify(); + } + + public void testHandleValidRequest() throws Exception { + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/valid.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory)); + providerControl.replay(); + boolean result = interceptor.handleRequest(context, null); + assertTrue("Valid request not handled", result); + assertFalse("Message Context has response", context.hasResponse()); + providerControl.verify(); + } + + public void testHandleInvalidRequest() throws Exception { + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/invalid.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory)); + providerControl.replay(); + boolean result = interceptor.handleRequest(context, null); + assertFalse("Invalid request handled", result); + assertTrue("Message Context has no response", context.hasResponse()); + SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-invalid.xml"); + assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse, + (SaajSoapMessage) context.getResponse()); + providerControl.verify(); + } + + public void testHandleAnonymousReplyTo() throws Exception { + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/anonymous.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory)); + SaajSoapMessage response = (SaajSoapMessage) context.getResponse(); + String messageId = "uid:1234"; + providerControl.expectAndReturn(providerMock.getMessageId(response), messageId); + providerControl.replay(); + boolean result = interceptor.handleResponse(context, null); + assertTrue("Anonymous request not handled", result); + SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-anonymous.xml"); + assertXMLEqual("Invalid response for message with invalid MAP", expectedResponse, + (SaajSoapMessage) context.getResponse()); + providerControl.verify(); + } + + public void testHandleNoneReplyTo() throws Exception { + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/none.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory)); + providerControl.replay(); + boolean result = interceptor.handleResponse(context, null); + assertFalse("None request handled", result); + providerControl.verify(); + } + + public void testHandleOutOfBandReplyTo() throws Exception { + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/valid.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(messageFactory)); + SaajSoapMessage response = (SaajSoapMessage) context.getResponse(); + String messageId = "uid:1234"; + providerControl.expectAndReturn(providerMock.getMessageId(response), messageId); + providerControl.replay(); + boolean result = interceptor.handleResponse(context, null); + assertFalse("Out of Band request handled", result); + providerControl.verify(); + } + + protected abstract AbstractWsAddressingInterceptor createInterceptor(); + + protected abstract String getTestPath(); + +} diff --git a/sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingTestCase.java b/sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingTestCase.java new file mode 100644 index 00000000..f8ee36e9 --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/addressing/AbstractWsAddressingTestCase.java @@ -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); + } +} diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200408InterceptorTest.java b/sandbox/src/test/java/org/springframework/ws/addressing/WsAddressing200408InterceptorTest.java similarity index 100% rename from sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200408InterceptorTest.java rename to sandbox/src/test/java/org/springframework/ws/addressing/WsAddressing200408InterceptorTest.java diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200508InterceptorTest.java b/sandbox/src/test/java/org/springframework/ws/addressing/WsAddressing200508InterceptorTest.java similarity index 100% rename from sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressing200508InterceptorTest.java rename to sandbox/src/test/java/org/springframework/ws/addressing/WsAddressing200508InterceptorTest.java diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java index d97107d3..9107f5b7 100644 --- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java +++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/AbstractWsAddressingInterceptorTestCase.java @@ -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(); diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200408Test.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200408Test.java new file mode 100644 index 00000000..21b50d9d --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200408Test.java @@ -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 + } +} diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200605Test.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200605Test.java new file mode 100644 index 00000000..f305615a --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/WsAddressingInterceptor200605Test.java @@ -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"; + } +} \ No newline at end of file diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdStrategyTestCase.java similarity index 77% rename from sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java rename to sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdStrategyTestCase.java index 50bc7b6a..0bfef2aa 100644 --- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdProviderTestCase.java +++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/AbstractMessageIdStrategyTestCase.java @@ -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)); } diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdProviderTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdStrategyTest.java similarity index 79% rename from sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdProviderTest.java rename to sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdStrategyTest.java index eb3d719d..eabcab3e 100644 --- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdProviderTest.java +++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UidMessageIdStrategyTest.java @@ -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(); } } \ No newline at end of file diff --git a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProviderTest.java b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategyTest.java similarity index 79% rename from sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProviderTest.java rename to sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategyTest.java index 78376c7c..8ab89be0 100644 --- a/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdProviderTest.java +++ b/sandbox/src/test/java/org/springframework/ws/soap/addressing/messageid/UuidMessageIdStrategyTest.java @@ -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(); } } \ No newline at end of file diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml deleted file mode 100644 index 6db3c331..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/anonymous.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff - - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - mailto:joe@fabrikam123.example - http://fabrikam123.example/mail/Delete - - - - 42 - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/invalid.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/invalid.xml deleted file mode 100644 index 4c82991b..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/invalid.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - http://business456.example/client1 - - mailto:joe@fabrikam123.example - http://fabrikam123.example/mail/Delete - - - - 42 - - - \ No newline at end of file diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-anonymous.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-anonymous.xml deleted file mode 100644 index 8dde1531..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-anonymous.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - uid:1234 - uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff - http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-invalid.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-invalid.xml deleted file mode 100644 index 67f8ce2f..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/response-invalid.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - env:Sender - - wsa:MessageInformationHeaderRequired - - - - - A required message information header, To, MessageID, or Action, is not present. - - - - - \ No newline at end of file diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/valid.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/valid.xml deleted file mode 100644 index db78bf46..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200408/valid.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff - - http://business456.example/client1 - - mailto:joe@fabrikam123.example - http://fabrikam123.example/mail/Delete - - - - 42 - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/anonymous.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/anonymous.xml deleted file mode 100644 index e32c0293..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/anonymous.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - http://example.com/someuniquestring - - http://www.w3.org/2005/08/addressing/anonymous - - mailto:fabrikam@example.com - http://example.com/fabrikam/mail/Delete - - - - 42 - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/invalid.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/invalid.xml deleted file mode 100644 index 8a74f50f..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/invalid.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - http://example.com/business/client1 - - mailto:fabrikam@example.com - http://example.com/fabrikam/mail/Delete - - - - 42 - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/none.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/none.xml deleted file mode 100644 index 17c0a7e4..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/none.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - http://example.com/someuniquestring - - http://www.w3.org/2005/08/addressing/none - - mailto:fabrikam@example.com - http://example.com/fabrikam/mail/Delete - - - - 42 - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-anonymous.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-anonymous.xml deleted file mode 100644 index f7588230..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-anonymous.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - uid:1234 - http://example.com/someuniquestring - http://www.w3.org/2005/08/addressing/anonymous - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-invalid.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-invalid.xml deleted file mode 100644 index 8312a243..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/response-invalid.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - env:Sender - - wsa:MessageAddressingHeaderRequired - - - - - A required header representing a Message Addressing Property is not present - - - - - \ No newline at end of file diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/valid.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/valid.xml deleted file mode 100644 index d25307b6..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/200508/valid.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - http://example.com/someuniquestring - - http://example.com/business/client1 - - mailto:fabrikam@example.com - http://example.com/fabrikam/mail/Delete - - - - 42 - - - diff --git a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/request-200408.xml b/sandbox/src/test/resources/org/springframework/ws/soap/addressing/request-200408.xml deleted file mode 100644 index cdcf14db..00000000 --- a/sandbox/src/test/resources/org/springframework/ws/soap/addressing/request-200408.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff - - - http://business456.example/client1 - - 123456789 - - - ABCDEFG - - - mailto:joe@fabrikam123.example - http://fabrikam123.example/mail/Delete - - - - 42 - - - \ No newline at end of file