From edabca8a5ba9cb70c204decd918f7807efaa7614 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Tue, 26 Feb 2008 01:22:04 +0000 Subject: [PATCH] SWS-298 (SWS-84) --- .../addressing/client/ActionCallback.java | 193 ++++++++++++++++++ .../AbstractActionCallbackTestCase.java | 120 +++++++++++ .../client/ActionCallback10Test.java | 31 +++ .../client/ActionCallback200408Test.java | 31 +++ 4 files changed, 375 insertions(+) create mode 100644 core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java create mode 100644 core/src/test/java/org/springframework/ws/soap/addressing/client/AbstractActionCallbackTestCase.java create mode 100644 core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback10Test.java create mode 100644 core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback200408Test.java diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java b/core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java new file mode 100644 index 00000000..754d948e --- /dev/null +++ b/core/src/main/java/org/springframework/ws/soap/addressing/client/ActionCallback.java @@ -0,0 +1,193 @@ +/* + * Copyright 2008 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.client; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import javax.xml.transform.TransformerException; + +import org.springframework.core.JdkVersion; +import org.springframework.util.Assert; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.client.core.WebServiceMessageCallback; +import org.springframework.ws.soap.SoapMessage; +import org.springframework.ws.soap.addressing.core.EndpointReference; +import org.springframework.ws.soap.addressing.core.MessageAddressingProperties; +import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy; +import org.springframework.ws.soap.addressing.messageid.RandomGuidMessageIdStrategy; +import org.springframework.ws.soap.addressing.messageid.UuidMessageIdStrategy; +import org.springframework.ws.soap.addressing.version.Addressing10; +import org.springframework.ws.soap.addressing.version.AddressingVersion; +import org.springframework.ws.transport.context.TransportContext; +import org.springframework.ws.transport.context.TransportContextHolder; + +/** + * {@link WebServiceMessageCallback} implementation that sets the WS-Addressing Action header on the + * message. + *

+ * A usage example with {@link org.springframework.ws.client.core.WebServiceTemplate}: + *

+ * WebServiceTemplate template = new WebServiceTemplate(messageFactory);
+ * Result result = new DOMResult();
+ * template.sendSourceAndReceiveToResult(
+ *     new StringSource("<content xmlns=\"http://tempuri.org\"/>"),
+ *     new ActionCallback(new URI("http://tempuri.org/Action")),
+ *     result);
+ * 
+ * + * @author Arjen Poutsma + * @since 1.0.0 + */ +public class ActionCallback implements WebServiceMessageCallback { + + private final AddressingVersion version; + + private final URI action; + + private final URI to; + + private MessageIdStrategy messageIdStrategy; + + private EndpointReference from; + + private EndpointReference replyTo; + + private EndpointReference faultTo; + + /** + * Create a new ActionCallback with the given Action. + *

+ * The To header of the outgoing message will reflect the {@link org.springframework.ws.transport.WebServiceConnection#getUri() + * connection URI}. + *

+ * The {@link AddressingVersion} is set to {@link Addressing10}. + * + * @param action the value of the action property to set + */ + public ActionCallback(String action) throws URISyntaxException { + this(new URI(action), new Addressing10(), null); + } + + /** + * Create a new ActionCallback with the given Action. + *

+ * The To header of the outgoing message will reflect the {@link org.springframework.ws.transport.WebServiceConnection#getUri() + * connection URI}. + *

+ * The {@link AddressingVersion} is set to {@link Addressing10}. + * + * @param action the value of the action property to set + */ + public ActionCallback(URI action) { + this(action, new Addressing10(), null); + } + + /** + * Create a new ActionCallback with the given version and Action. + *

+ * The To header of the outgoing message will reflect the {@link org.springframework.ws.transport.WebServiceConnection#getUri() + * connection URI}. + * + * @param action the value of the action property to set + * @param version the WS-Addressing version to use + */ + public ActionCallback(URI action, AddressingVersion version) { + this(action, version, null); + } + + /** + * Create a new ActionCallback with the given version, Action, and optional + * To. + * + * @param action the value of the action property + * @param version the WS-Addressing version to use + * @param action the value of the destination property + */ + public ActionCallback(URI action, AddressingVersion version, URI to) { + Assert.notNull(action, "'action' must not be null"); + Assert.notNull(version, "'version' must not be null"); + this.action = action; + this.version = version; + this.to = to; + if (JdkVersion.isAtLeastJava15()) { + messageIdStrategy = new UuidMessageIdStrategy(); + } + else { + messageIdStrategy = new RandomGuidMessageIdStrategy(); + } + } + + /** + * Sets the message id strategy used for creating WS-Addressing MessageIds. + *

+ * By default, the {@link UuidMessageIdStrategy} is used on Java 5 and higher, and the {@link + * RandomGuidMessageIdStrategy} on Java 1.4. + */ + public void setMessageIdStrategy(MessageIdStrategy messageIdStrategy) { + Assert.notNull(messageIdStrategy, "'messageIdStrategy' must not be null"); + this.messageIdStrategy = messageIdStrategy; + } + + public void setFrom(EndpointReference from) { + this.from = from; + } + + public void setReplyTo(EndpointReference replyTo) { + this.replyTo = replyTo; + } + + public void setFaultTo(EndpointReference faultTo) { + this.faultTo = faultTo; + } + + /** + * Returns the Destination for outgoing messages. + *

+ * Defaults to the {@link org.springframework.ws.transport.WebServiceConnection#getUri() connection URI} if no + * destination was set. + */ + protected URI getTo() { + if (to == null) { + TransportContext transportContext = TransportContextHolder.getTransportContext(); + if (transportContext != null && transportContext.getConnection() != null) { + try { + return transportContext.getConnection().getUri(); + } + catch (URISyntaxException ex) { + // ignore + } + } + throw new IllegalStateException("Could not obtain connection URI from Transport Context"); + } + else { + return to; + } + } + + public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException { + Assert.isInstanceOf(SoapMessage.class, message); + SoapMessage soapMessage = (SoapMessage) message; + URI to = getTo(); + URI messageId = messageIdStrategy.newMessageId(soapMessage); + MessageAddressingProperties map = + new MessageAddressingProperties(to, from, replyTo, faultTo, action, messageId); + version.addAddressingHeaders(soapMessage, map); + } + + +} diff --git a/core/src/test/java/org/springframework/ws/soap/addressing/client/AbstractActionCallbackTestCase.java b/core/src/test/java/org/springframework/ws/soap/addressing/client/AbstractActionCallbackTestCase.java new file mode 100644 index 00000000..9ad1fa2d --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/addressing/client/AbstractActionCallbackTestCase.java @@ -0,0 +1,120 @@ +/* + * Copyright ${YEAR} 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.client; + +import java.net.URI; +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPBodyElement; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; + +import org.easymock.MockControl; + +import org.springframework.ws.soap.addressing.AbstractWsAddressingTestCase; +import org.springframework.ws.soap.addressing.core.EndpointReference; +import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy; +import org.springframework.ws.soap.addressing.version.AddressingVersion; +import org.springframework.ws.soap.saaj.SaajSoapMessage; +import org.springframework.ws.transport.WebServiceConnection; +import org.springframework.ws.transport.context.DefaultTransportContext; +import org.springframework.ws.transport.context.TransportContext; +import org.springframework.ws.transport.context.TransportContextHolder; + +public abstract class AbstractActionCallbackTestCase extends AbstractWsAddressingTestCase { + + private ActionCallback callback; + + private MockControl strategyControl; + + private MessageIdStrategy strategyMock; + + private MockControl connectionControl; + + private WebServiceConnection connectionMock; + + protected final void onSetUp() throws Exception { + strategyControl = MockControl.createControl(MessageIdStrategy.class); + strategyMock = (MessageIdStrategy) strategyControl.getMock(); + + connectionControl = MockControl.createControl(WebServiceConnection.class); + connectionMock = (WebServiceConnection) connectionControl.getMock(); + TransportContext transportContext = new DefaultTransportContext(connectionMock); + TransportContextHolder.setTransportContext(transportContext); + } + + protected void tearDown() throws Exception { + TransportContextHolder.setTransportContext(null); + } + + public void testValid() throws Exception { + URI action = new URI("http://example.com/fabrikam/mail/Delete"); + URI to = new URI("mailto:fabrikam@example.com"); + callback = new ActionCallback(action, getVersion(), to); + callback.setMessageIdStrategy(strategyMock); + SaajSoapMessage message = createDeleteMessage(); + strategyControl + .expectAndReturn(strategyMock.newMessageId(message), new URI("http://example.com/someuniquestring")); + callback.setReplyTo(new EndpointReference(new URI("http://example.com/business/client1"))); + strategyControl.replay(); + connectionControl.replay(); + + callback.doWithMessage(message); + + SaajSoapMessage expected = loadSaajMessage(getTestPath() + "/valid.xml"); + assertXMLEqual("Invalid message", expected, message); + strategyControl.verify(); + connectionControl.verify(); + } + + public void testDefaults() throws Exception { + URI action = new URI("http://example.com/fabrikam/mail/Delete"); + URI connectionUri = new URI("mailto:fabrikam@example.com"); + callback = new ActionCallback(action, getVersion()); + callback.setMessageIdStrategy(strategyMock); + connectionControl.expectAndReturn(connectionMock.getUri(), connectionUri); + connectionControl.replay(); + + SaajSoapMessage message = createDeleteMessage(); + strategyControl + .expectAndReturn(strategyMock.newMessageId(message), new URI("http://example.com/someuniquestring")); + callback.setReplyTo(new EndpointReference(new URI("http://example.com/business/client1"))); + strategyControl.replay(); + + callback.doWithMessage(message); + + SaajSoapMessage expected = loadSaajMessage(getTestPath() + "/valid.xml"); + assertXMLEqual("Invalid message", expected, message); + strategyControl.verify(); + connectionControl.verify(); + } + + private SaajSoapMessage createDeleteMessage() throws SOAPException { + SOAPMessage saajMessage = messageFactory.createMessage(); + SOAPBody saajBody = saajMessage.getSOAPBody(); + SOAPBodyElement delete = saajBody.addBodyElement(new QName("http://example.com/fabrikam", "Delete")); + SOAPElement maxCount = delete.addChildElement(new QName("maxCount")); + maxCount.setTextContent("42"); + return new SaajSoapMessage(saajMessage); + } + + protected abstract AddressingVersion getVersion(); + + protected abstract String getTestPath(); + +} \ No newline at end of file diff --git a/core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback10Test.java b/core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback10Test.java new file mode 100644 index 00000000..465f44eb --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback10Test.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008 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.client; + +import org.springframework.ws.soap.addressing.version.Addressing10; +import org.springframework.ws.soap.addressing.version.AddressingVersion; + +public class ActionCallback10Test extends AbstractActionCallbackTestCase { + + protected AddressingVersion getVersion() { + return new Addressing10(); + } + + protected String getTestPath() { + return "10"; + } +} diff --git a/core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback200408Test.java b/core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback200408Test.java new file mode 100644 index 00000000..0b6fc7af --- /dev/null +++ b/core/src/test/java/org/springframework/ws/soap/addressing/client/ActionCallback200408Test.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008 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.client; + +import org.springframework.ws.soap.addressing.version.Addressing200408; +import org.springframework.ws.soap.addressing.version.AddressingVersion; + +public class ActionCallback200408Test extends AbstractActionCallbackTestCase { + + protected AddressingVersion getVersion() { + return new Addressing200408(); + } + + protected String getTestPath() { + return "200408"; + } +} \ No newline at end of file