diff --git a/core/src/main/java/org/springframework/ws/WebServiceMessage.java b/core/src/main/java/org/springframework/ws/WebServiceMessage.java
index ddde8ffe..0acab316 100644
--- a/core/src/main/java/org/springframework/ws/WebServiceMessage.java
+++ b/core/src/main/java/org/springframework/ws/WebServiceMessage.java
@@ -47,7 +47,9 @@ public interface WebServiceMessage {
Result getPayloadResult();
/**
- * Writes the entire message to the given output stream.
+ * Writes the entire message to the given output stream. If the given stream is an instance of {@link
+ * org.springframework.ws.transport.TransportOutputStream TransportOutputStream}, the corresponding headers will be
+ * writen as well.
*
* @param outputStream the stream to write to
* @throws IOException if an I/O exception occurs
diff --git a/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java b/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java
new file mode 100644
index 00000000..c66610e4
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * The WebServiceMessageFactory serves as factory for {@link org.springframework.ws.WebServiceMessage
+ * WebServiceMessages}. Allows creation of empty messages, or messages based on InputStreams.
+ *
+ * @author Arjen Poutsma
+ * @see org.springframework.ws.WebServiceMessage
+ */
+public interface WebServiceMessageFactory {
+
+ /**
+ * Creates a new, empty {@link WebServiceMessage}.
+ *
+ * @return the empty message
+ */
+ WebServiceMessage createWebServiceMessage();
+
+ /**
+ * Reads {@link WebServiceMessage} from the given input stream.
+ *
MessageContext interface. Contains functionality to set and remove
- * properties.
- *
- * @author Arjen Poutsma
- */
-public abstract class AbstractMessageContext implements MessageContext {
-
- private WebServiceMessage request;
-
- private WebServiceMessage response;
-
- private final TransportRequest transportRequest;
-
- /**
- * Keys are Strings, values are Objects. Lazily initalized by
- * getProperties().
- */
- private Map properties;
-
- /**
- * Construct a new instance of the AbstractMessageContext with the given request message and
- * transportRequest.
- */
- protected AbstractMessageContext(WebServiceMessage request, TransportRequest transportRequest) {
- Assert.notNull(request, "No request given");
- Assert.notNull(transportRequest, "No transport request given");
- this.request = request;
- this.transportRequest = transportRequest;
- }
-
- public final WebServiceMessage getRequest() {
- return request;
- }
-
- /**
- * Protected method that sets the request message directly.
- */
- protected final void setRequest(WebServiceMessage request) {
- Assert.notNull(request);
- this.request = request;
- }
-
- public final WebServiceMessage getResponse() {
- if (response == null) {
- response = createResponseMessage();
- }
- return response;
- }
-
- public final boolean hasResponse() {
- return response != null;
- }
-
- public final TransportRequest getTransportRequest() {
- return transportRequest;
- }
-
- /**
- * Protected method that sets the response message directly.
- */
- protected final void setResponse(WebServiceMessage response) {
- Assert.notNull(response);
- this.response = response;
- }
-
- private Map getProperties() {
- if (properties == null) {
- properties = new HashMap();
- }
- return properties;
- }
-
- public boolean containsProperty(String name) {
- return getProperties().containsKey(name);
- }
-
- public Object getProperty(String name) {
- return getProperties().get(name);
- }
-
- public String[] getPropertyNames() {
- return (String[]) getProperties().keySet().toArray(new String[getProperties().size()]);
- }
-
- public void removeProperty(String name) {
- getProperties().remove(name);
- }
-
- public void setProperty(String name, Object value) {
- getProperties().put(name, value);
- }
-
- /**
- * Abstract template method that creates a new WebServiceMessage.
- */
- protected abstract WebServiceMessage createResponseMessage();
-}
diff --git a/core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java b/core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java
new file mode 100644
index 00000000..df2ea32a
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2006 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.context;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.util.Assert;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+
+/**
+ * Simple implementation of MessageContext.
+ *
+ * @author Arjen Poutsma
+ */
+public class DefaultMessageContext implements MessageContext {
+
+ private final WebServiceMessageFactory messageFactory;
+
+ /**
+ * Keys are Strings, values are Objects. Lazily initalized by
+ * getProperties().
+ */
+ private Map properties;
+
+ private WebServiceMessage request;
+
+ private WebServiceMessage response;
+
+ /**
+ * Construct a new, empty instance of the DefaultMessageContext with the given message factory.
+ */
+ public DefaultMessageContext(WebServiceMessageFactory messageFactory) {
+ this(messageFactory.createWebServiceMessage(), messageFactory);
+ }
+
+ /**
+ * Construct a new instance of the DefaultMessageContext with the given request message and message
+ * factory.
+ */
+ public DefaultMessageContext(WebServiceMessage request, WebServiceMessageFactory messageFactory) {
+ Assert.notNull(request, "No request given");
+ Assert.notNull(messageFactory, "messageFactory must not be null");
+ this.request = request;
+ this.messageFactory = messageFactory;
+ }
+
+ private Map getProperties() {
+ if (properties == null) {
+ properties = new HashMap();
+ }
+ return properties;
+ }
+
+ /**
+ * Returns the request message.
+ *
+ * @return the request message
+ */
+ public WebServiceMessage getRequest() {
+ return request;
+ }
+
+ /**
+ * Returns the response message. Creates a new response if no response is present.
+ *
+ * @return the response message
+ * @see #hasResponse()
+ */
+ public WebServiceMessage getResponse() {
+ if (response == null) {
+ response = messageFactory.createWebServiceMessage();
+ }
+ return response;
+ }
+
+ /**
+ * Check if this message context contains a property with the given name.
+ *
+ * @param name the name of the property to look fo
+ * @return true if the MessageContext contains the property; false otherwise
+ */
+ public boolean containsProperty(String name) {
+ return getProperties().containsKey(name);
+ }
+
+ /**
+ * Gets the value of a specific property from the MessageContext.
+ *
+ * @param name name of the property whose value is to be retrieved
+ * @return value of the property
+ */
+ public Object getProperty(String name) {
+ return getProperties().get(name);
+ }
+
+ /**
+ * Return the names of all properties in this MessageContext.
+ *
+ * @return the names of all properties in this context, or an empty array if none defined
+ */
+ public String[] getPropertyNames() {
+ return (String[]) getProperties().keySet().toArray(new String[getProperties().size()]);
+ }
+
+ /**
+ * Indicates whether this context has a resonse.
+ *
+ * @return true if this context has a response; false otherwise
+ */
+ public boolean hasResponse() {
+ return response != null;
+ }
+
+ /**
+ * Removes a property from the MessageContext.
+ *
+ * @param name name of the property to be removed
+ */
+ public void removeProperty(String name) {
+ getProperties().remove(name);
+ }
+
+ /**
+ * Sets the name and value of a property associated with the MessageContext. If the
+ * MessageContext contains a value of the same property, the old value is replaced.
+ *
+ * @param name name of the property associated with the value
+ * @param value value of the property
+ */
+ public void setProperty(String name, Object value) {
+ getProperties().put(name, value);
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/context/MessageContext.java b/core/src/main/java/org/springframework/ws/context/MessageContext.java
index b5071f8b..86bc51aa 100644
--- a/core/src/main/java/org/springframework/ws/context/MessageContext.java
+++ b/core/src/main/java/org/springframework/ws/context/MessageContext.java
@@ -16,21 +16,13 @@
package org.springframework.ws.context;
-import java.io.IOException;
-
import org.springframework.ws.WebServiceMessage;
-import org.springframework.ws.transport.TransportRequest;
-import org.springframework.ws.transport.TransportResponse;
/**
* Context holder for message requests. Contains both the message request as well as the response. Response message are
* usually lazily created.
- *
- * MessageContext implementations are constructed using a MessageContextFactory, taking a
- * TransportContext as a parameter.
*
* @author Arjen Poutsma
- * @see MessageContextFactory#createContext(org.springframework.ws.transport.TransportContext)
*/
public interface MessageContext {
@@ -56,21 +48,6 @@ public interface MessageContext {
*/
boolean hasResponse();
- /**
- * Returns the transport request used to create this context. Call be used for URL-based message routing.
- *
- * @return the transport request
- */
- TransportRequest getTransportRequest();
-
- /**
- * Sends the response to the given transport response.
- *
- * @param transportResponse the transport used for sending
- * @throws IOException if an I/O exception occurs
- */
- void sendResponse(TransportResponse transportResponse) throws IOException;
-
/**
* Sets the name and value of a property associated with the MessageContext. If the
* MessageContext contains a value of the same property, the old value is replaced.
diff --git a/core/src/main/java/org/springframework/ws/context/MessageContextFactory.java b/core/src/main/java/org/springframework/ws/context/MessageContextFactory.java
deleted file mode 100644
index 2b17f279..00000000
--- a/core/src/main/java/org/springframework/ws/context/MessageContextFactory.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2005 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.context;
-
-import java.io.IOException;
-
-import org.springframework.ws.transport.TransportContext;
-
-/**
- * The MessageContextFactory serves as factory for MessageContexts. Allows creation of
- * contexts based on TransportRequest.
- *
- * @author Arjen Poutsma
- */
-public interface MessageContextFactory {
-
- /**
- * Creates a MessageContext based on the given transport context. Implementations use the context
- * request's input stream to create a request message, and possibly copy the request headers to the message.
- *
- * Implementations are free to store the transport context for later reference. For instance, streaming
- * implementations of MessageContextFactory might use the transport response to directly write a
- * response message.
- *
- * @param transportContext the transport context which contains the request
- * @return the created message context
- * @throws IOException if an I/O exception occurs
- */
- MessageContext createContext(TransportContext transportContext) throws IOException;
-
-}
diff --git a/core/src/main/java/org/springframework/ws/endpoint/interceptor/AbstractValidatingInterceptor.java b/core/src/main/java/org/springframework/ws/endpoint/interceptor/AbstractValidatingInterceptor.java
index 78c7a59b..a9acc4a3 100644
--- a/core/src/main/java/org/springframework/ws/endpoint/interceptor/AbstractValidatingInterceptor.java
+++ b/core/src/main/java/org/springframework/ws/endpoint/interceptor/AbstractValidatingInterceptor.java
@@ -37,7 +37,7 @@ import org.springframework.ws.soap.SoapBody;
import org.springframework.ws.soap.SoapFault;
import org.springframework.ws.soap.SoapFaultDetail;
import org.springframework.ws.soap.SoapFaultDetailElement;
-import org.springframework.ws.soap.context.SoapMessageContext;
+import org.springframework.ws.soap.SoapMessage;
import org.springframework.xml.namespace.QNameUtils;
import org.springframework.xml.validation.XmlValidator;
import org.springframework.xml.validation.XmlValidatorFactory;
@@ -239,8 +239,8 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
for (int i = 0; i < errors.length; i++) {
logger.warn("XML validation error on request: " + errors[i].getMessage());
}
- if (messageContext instanceof SoapMessageContext) {
- createRequestValidationFault((SoapMessageContext) messageContext, errors);
+ if (messageContext.getResponse() instanceof SoapMessage) {
+ createRequestValidationFault((SoapMessage) messageContext.getResponse(), errors);
}
return false;
}
@@ -296,9 +296,9 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
/**
* Creates a response soap message containing a SoapFault that descibes the validation errors.
*/
- protected void createRequestValidationFault(SoapMessageContext context, SAXParseException[] errors)
+ protected void createRequestValidationFault(SoapMessage response, SAXParseException[] errors)
throws TransformerException {
- SoapBody body = context.getSoapResponse().getSoapBody();
+ SoapBody body = response.getSoapBody();
SoapFault fault = body.addClientOrSenderFault(getFaultStringOrReason(), getFaultStringOrReasonLocale());
if (getAddValidationErrorDetail()) {
SoapFaultDetail detail = fault.addFaultDetail();
diff --git a/core/src/main/java/org/springframework/ws/pox/context/AbstractPoxMessageContext.java b/core/src/main/java/org/springframework/ws/pox/context/AbstractPoxMessageContext.java
deleted file mode 100644
index e75910fc..00000000
--- a/core/src/main/java/org/springframework/ws/pox/context/AbstractPoxMessageContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2006 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.pox.context;
-
-import org.springframework.ws.WebServiceMessage;
-import org.springframework.ws.context.AbstractMessageContext;
-import org.springframework.ws.pox.PoxMessage;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * Abstract implementation of the PoxMessageContext interface. Implements base MessageContext
- * methods by delegating to PoxMessageContext functionality.
- *
- * @author Arjen Poutsma
- */
-public abstract class AbstractPoxMessageContext extends AbstractMessageContext implements PoxMessageContext {
-
- protected AbstractPoxMessageContext(PoxMessage request, TransportRequest transportRequest) {
- super(request, transportRequest);
- }
-
- public final PoxMessage getPoxResponse() {
- return (PoxMessage) getResponse();
- }
-
- public final PoxMessage getPoxRequest() {
- return (PoxMessage) getRequest();
- }
-
- protected final WebServiceMessage createResponseMessage() {
- return createResponsePoxMessage();
- }
-
- protected abstract PoxMessage createResponsePoxMessage();
-}
diff --git a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java
index c40f273b..289c8c7f 100644
--- a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java
+++ b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessage.java
@@ -27,6 +27,7 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.springframework.ws.pox.PoxMessage;
+import org.springframework.ws.transport.TransportOutputStream;
import org.w3c.dom.Document;
/**
@@ -37,6 +38,8 @@ import org.w3c.dom.Document;
*/
public class DomPoxMessage implements PoxMessage {
+ private static final String CONTENT_TYPE = "text/xml";
+
private final Document document;
private Transformer transformer;
@@ -68,10 +71,14 @@ public class DomPoxMessage implements PoxMessage {
public void writeTo(OutputStream outputStream) throws IOException {
try {
+ if (outputStream instanceof TransportOutputStream) {
+ TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
+ transportOutputStream.addHeader("Content-Type", CONTENT_TYPE);
+ }
transformer.transform(getPayloadSource(), new StreamResult(outputStream));
}
catch (TransformerException ex) {
- throw new DomPoxMessageException("Could not create transformer", ex);
+ throw new DomPoxMessageException("Could write document: " + ex.getMessage(), ex);
}
}
}
diff --git a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageContext.java b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageContext.java
deleted file mode 100644
index 5a5bbd23..00000000
--- a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageContext.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2006 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.pox.dom;
-
-import java.io.IOException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.transform.Transformer;
-
-import org.springframework.util.Assert;
-import org.springframework.ws.pox.PoxMessage;
-import org.springframework.ws.pox.context.AbstractPoxMessageContext;
-import org.springframework.ws.transport.TransportRequest;
-import org.springframework.ws.transport.TransportResponse;
-import org.w3c.dom.Document;
-
-/**
- * Implementation of the MessageContext that contains a DomPoxMessage.
- *
- * @author Arjen Poutsma
- * @see DomPoxMessage
- */
-public class DomPoxMessageContext extends AbstractPoxMessageContext {
-
- private DocumentBuilder documentBuilder;
-
- private Transformer transformer;
-
- /**
- * Creates a new DomPoxMessageContext with the given parameters.
- */
- public DomPoxMessageContext(Document request,
- TransportRequest transportRequest,
- DocumentBuilder documentBuilder,
- Transformer transformer) {
- super(new DomPoxMessage(request, transformer), transportRequest);
- Assert.notNull(documentBuilder, "documentBuilder must not be null");
- Assert.notNull(transformer, "transformer must not be null");
- this.documentBuilder = documentBuilder;
- this.transformer = transformer;
- }
-
- protected PoxMessage createResponsePoxMessage() {
- Document document = documentBuilder.newDocument();
- return new DomPoxMessage(document, transformer);
- }
-
- public void sendResponse(TransportResponse transportResponse) throws IOException {
- if (hasResponse()) {
- transportResponse.addHeader("Content-Type", "text/xml");
- getResponse().writeTo(transportResponse.getOutputStream());
- }
- }
-}
diff --git a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageContextFactory.java b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageFactory.java
similarity index 66%
rename from core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageContextFactory.java
rename to core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageFactory.java
index 0a2cf0a0..b12d5aee 100644
--- a/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageContextFactory.java
+++ b/core/src/main/java/org/springframework/ws/pox/dom/DomPoxMessageFactory.java
@@ -17,6 +17,7 @@
package org.springframework.ws.pox.dom;
import java.io.IOException;
+import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -24,20 +25,19 @@ import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.context.MessageContextFactory;
-import org.springframework.ws.transport.TransportContext;
-import org.springframework.ws.transport.TransportRequest;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/**
- * Implementation of the MessageContextFactory interface that creates a DOM
+ * Implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory} interinterface
+ * that creates a DOM PoxMessage.
*
* @author Arjen Poutsma
- * @see DomPoxMessageContext
+ * @see org.springframework.ws.pox.dom.DomPoxMessage
*/
-public class DomPoxMessageContextFactory implements MessageContextFactory, InitializingBean {
+public class DomPoxMessageFactory implements WebServiceMessageFactory, InitializingBean {
private DocumentBuilderFactory documentBuilderFactory;
@@ -68,15 +68,25 @@ public class DomPoxMessageContextFactory implements MessageContextFactory, Initi
transformerFactory = TransformerFactory.newInstance();
}
- public MessageContext createContext(TransportContext transportContext) throws IOException {
- TransportRequest transportRequest = transportContext.getTransportRequest();
+ public WebServiceMessage createWebServiceMessage() {
try {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
- Document request = documentBuilder.parse(transportRequest.getInputStream());
- return new DomPoxMessageContext(request,
- transportRequest,
- documentBuilder,
- transformerFactory.newTransformer());
+ Document request = documentBuilder.newDocument();
+ return new DomPoxMessage(request, transformerFactory.newTransformer());
+ }
+ catch (ParserConfigurationException ex) {
+ throw new DomPoxMessageException("Could not create message context", ex);
+ }
+ catch (TransformerConfigurationException ex) {
+ throw new DomPoxMessageException("Could not create transormer", ex);
+ }
+ }
+
+ public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
+ try {
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document request = documentBuilder.parse(inputStream);
+ return new DomPoxMessage(request, transformerFactory.newTransformer());
}
catch (ParserConfigurationException ex) {
throw new DomPoxMessageException("Could not create message context", ex);
diff --git a/core/src/main/java/org/springframework/ws/soap/SoapMessageDispatcher.java b/core/src/main/java/org/springframework/ws/soap/SoapMessageDispatcher.java
index 459cc7e0..7d8df9ae 100644
--- a/core/src/main/java/org/springframework/ws/soap/SoapMessageDispatcher.java
+++ b/core/src/main/java/org/springframework/ws/soap/SoapMessageDispatcher.java
@@ -29,7 +29,6 @@ import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.EndpointInvocationChain;
import org.springframework.ws.MessageDispatcher;
import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.soap.context.SoapMessageContext;
import org.springframework.ws.soap.endpoint.SimpleSoapExceptionResolver;
import org.springframework.ws.soap.soap12.Soap12Header;
@@ -95,19 +94,19 @@ public class SoapMessageDispatcher extends MessageDispatcher {
* @see SoapHeader#examineMustUnderstandHeaderElements(String)
*/
protected boolean handleRequest(EndpointInvocationChain mappedEndpoint, MessageContext messageContext) {
- if (messageContext instanceof SoapMessageContext) {
- SoapMessageContext soapContext = (SoapMessageContext) messageContext;
- if (soapContext.getSoapRequest().getSoapHeader() == null) {
+ if (messageContext.getRequest() instanceof SoapMessage) {
+ SoapMessage soapRequest = (SoapMessage) messageContext.getRequest();
+ if (soapRequest.getSoapHeader() == null) {
// no headers to process
return true;
}
- String[] roles = getRoles(mappedEndpoint, soapContext.getSoapRequest().getVersion());
+ String[] roles = getRoles(mappedEndpoint, soapRequest.getVersion());
if (logger.isDebugEnabled()) {
logger.debug("Handling MustUnderstand headers for actors/roles [" +
StringUtils.arrayToCommaDelimitedString(roles));
}
for (int i = 0; i < roles.length; i++) {
- if (!handleRequestForRole(mappedEndpoint, soapContext, roles[i])) {
+ if (!handleRequestForRole(mappedEndpoint, messageContext, roles[i])) {
return false;
}
}
@@ -142,9 +141,9 @@ public class SoapMessageDispatcher extends MessageDispatcher {
* @see SoapEndpointInterceptor#understands(SoapHeaderElement)
*/
private boolean handleRequestForRole(EndpointInvocationChain mappedEndpoint,
- SoapMessageContext messageContext,
+ MessageContext messageContext,
String actorOrRole) {
- SoapHeader requestHeader = messageContext.getSoapRequest().getSoapHeader();
+ SoapHeader requestHeader = ((SoapMessage) messageContext.getRequest()).getSoapHeader();
List notUnderstoodHeaderNames = new ArrayList();
for (Iterator iterator = requestHeader.examineMustUnderstandHeaderElements(actorOrRole); iterator.hasNext();) {
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
@@ -174,10 +173,11 @@ public class SoapMessageDispatcher extends MessageDispatcher {
logger.warn("Could not handle mustUnderstand headers: " +
StringUtils.collectionToCommaDelimitedString(notUnderstoodHeaderNames) + ". Returning fault");
}
- SoapBody responseBody = messageContext.getSoapResponse().getSoapBody();
+ SoapMessage soapResponse = (SoapMessage) messageContext.getResponse();
+ SoapBody responseBody = soapResponse.getSoapBody();
SoapFault fault = responseBody.addMustUnderstandFault(mustUnderstandFault, mustUnderstandFaultLocale);
fault.setFaultActorOrRole(actorOrRole);
- SoapHeader header = messageContext.getSoapResponse().getSoapHeader();
+ SoapHeader header = soapResponse.getSoapHeader();
if (header instanceof Soap12Header) {
Soap12Header soap12Header = (Soap12Header) header;
for (Iterator iterator = notUnderstoodHeaderNames.iterator(); iterator.hasNext();) {
@@ -206,9 +206,9 @@ public class SoapMessageDispatcher extends MessageDispatcher {
if (mappedEndpoint != null && messageContext.hasResponse() &&
!ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
boolean hasFault = false;
- if (messageContext instanceof SoapMessageContext) {
- SoapMessageContext soapMessageContext = (SoapMessageContext) messageContext;
- hasFault = soapMessageContext.getSoapResponse().getSoapBody().hasFault();
+ if (messageContext.getResponse() instanceof SoapMessage) {
+ SoapMessage soapResponse = (SoapMessage) messageContext.getResponse();
+ hasFault = soapResponse.getSoapBody().hasFault();
}
boolean resume = true;
for (int i = interceptorIndex; resume && i >= 0; i--) {
diff --git a/core/src/main/java/org/springframework/ws/soap/SoapVersion.java b/core/src/main/java/org/springframework/ws/soap/SoapVersion.java
index 66312994..0efbcc39 100644
--- a/core/src/main/java/org/springframework/ws/soap/SoapVersion.java
+++ b/core/src/main/java/org/springframework/ws/soap/SoapVersion.java
@@ -41,25 +41,25 @@ public interface SoapVersion {
private static final String CONTENT_TYPE = "text/xml";
- private final QName ENVELOPE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Envelope");
+ private QName ENVELOPE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Envelope");
- private final QName HEADER_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Header");
+ private QName HEADER_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Header");
- private final QName BODY_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Body");
+ private QName BODY_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Body");
- private final QName FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Fault");
+ private QName FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Fault");
- private final QName MUST_UNDERSTAND_ATTRIBUTE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "mustUnderstand");
+ private QName MUST_UNDERSTAND_ATTRIBUTE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "mustUnderstand");
- private final QName ACTOR_NAME = new QName(ENVELOPE_NAMESPACE_URI, "actor");
+ private QName ACTOR_NAME = new QName(ENVELOPE_NAMESPACE_URI, "actor");
- private final QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Client");
+ private QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Client");
- private final QName SERVER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Server");
+ private QName SERVER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Server");
- private final QName MUST_UNDERSTAND_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "MustUnderstand");
+ private QName MUST_UNDERSTAND_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "MustUnderstand");
- private final QName VERSION_MISMATCH_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "VersionMismatch");
+ private QName VERSION_MISMATCH_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "VersionMismatch");
public QName getBodyName() {
return BODY_NAME;
@@ -143,25 +143,25 @@ public interface SoapVersion {
private static final String CONTENT_TYPE = "application/soap+xml";
- private final QName ENVELOPE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Envelope");
+ private QName ENVELOPE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Envelope");
- private final QName HEADER_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Header");
+ private QName HEADER_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Header");
- private final QName BODY_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Body");
+ private QName BODY_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Body");
- private final QName FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Fault");
+ private QName FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Fault");
- private final QName MUST_UNDERSTAND_ATTRIBUTE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "mustUnderstand");
+ private QName MUST_UNDERSTAND_ATTRIBUTE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "mustUnderstand");
- private final QName ROLE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "role");
+ private QName ROLE_NAME = new QName(ENVELOPE_NAMESPACE_URI, "role");
- private final QName SENDER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Sender");
+ private QName SENDER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Sender");
- private final QName RECEIVER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Receiver");
+ private QName RECEIVER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Receiver");
- private final QName MUST_UNDERSTAND_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "MustUnderstand");
+ private QName MUST_UNDERSTAND_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "MustUnderstand");
- private final QName VERSION_MISMATCH_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "VersionMismatch");
+ private QName VERSION_MISMATCH_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "VersionMismatch");
public QName getBodyName() {
return BODY_NAME;
diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java
index 9bcbf71e..86952092 100644
--- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java
+++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java
@@ -20,24 +20,24 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.Arrays;
import java.util.Iterator;
-import javax.mail.MessagingException;
-import javax.xml.stream.XMLStreamException;
import javax.activation.DataHandler;
+import javax.xml.stream.XMLStreamException;
import org.apache.axiom.attachments.Attachments;
-import org.apache.axiom.attachments.Part;
import org.apache.axiom.om.OMException;
+import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPMessage;
import org.apache.axiom.soap.SOAPProcessingException;
import org.springframework.core.io.InputStreamSource;
+import org.springframework.util.Assert;
import org.springframework.ws.soap.AbstractSoapMessage;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.soap.SoapEnvelope;
-import org.springframework.util.Assert;
+import org.springframework.ws.soap.SoapVersion;
+import org.springframework.ws.transport.TransportOutputStream;
/**
* AXIOM-specific implementation of the SoapMessage interface. Accessed via the
@@ -48,7 +48,6 @@ import org.springframework.util.Assert;
*
* @author Arjen Poutsma
* @see SOAPMessage
- * @see AxiomSoapMessageContext
*/
public class AxiomSoapMessage extends AbstractSoapMessage {
@@ -79,6 +78,19 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
* Create a new AxiomSoapMessage based on the given AXIOM SOAPMessage.
*
* @param soapMessage the AXIOM SOAPMessage
+ * @param payloadCaching whether the contents of the SOAP body should be cached or not
+ */
+ public AxiomSoapMessage(SOAPMessage soapMessage, boolean payloadCaching) {
+ axiomMessage = soapMessage;
+ axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory();
+ attachments = null;
+ this.payloadCaching = payloadCaching;
+ }
+
+ /**
+ * Create a new AxiomSoapMessage based on the given AXIOM SOAPMessage and attachments.
+ *
+ * @param soapMessage the AXIOM SOAPMessage
* @param attachments the attachments
* @param payloadCaching whether the contents of the SOAP body should be cached or not
*/
@@ -138,7 +150,18 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
public void writeTo(OutputStream outputStream) throws IOException {
try {
- axiomMessage.serialize(outputStream);
+ String charsetEncoding = axiomMessage.getCharsetEncoding();
+
+ OMOutputFormat format = new OMOutputFormat();
+ format.setCharSetEncoding(charsetEncoding);
+ format.setSOAP11(getVersion() == SoapVersion.SOAP_11);
+ if (outputStream instanceof TransportOutputStream) {
+ TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
+ String contentType = format.getContentType();
+ contentType += "; charset=\"" + charsetEncoding + "\"";
+ transportOutputStream.addHeader("Content-Type", contentType);
+ }
+ axiomMessage.serializeAndConsume(outputStream, format);
}
catch (XMLStreamException ex) {
throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageContext.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageContext.java
deleted file mode 100644
index 7e43aace..00000000
--- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageContext.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2006 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.axiom;
-
-import java.io.IOException;
-import javax.xml.stream.XMLStreamException;
-
-import org.apache.axiom.om.OMOutputFormat;
-import org.apache.axiom.soap.SOAPFactory;
-import org.apache.axiom.soap.SOAPMessage;
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.SoapVersion;
-import org.springframework.ws.soap.context.AbstractSoapMessageContext;
-import org.springframework.ws.transport.TransportRequest;
-import org.springframework.ws.transport.TransportResponse;
-
-/**
- * AXIOM-specific implementation of the SoapMessageContext interface. Created by the
- * AxiomSoapMessageContextFactory.
- *
- * @author Arjen Poutsma
- * @see AxiomSoapMessageContextFactory
- */
-public class AxiomSoapMessageContext extends AbstractSoapMessageContext {
-
- /**
- * Creates a new instance based on the given Axiom request message, and a SOAP factory.
- *
- * @param messageRequest the request message
- */
- public AxiomSoapMessageContext(AxiomSoapMessage messageRequest, TransportRequest transportRequest) {
- super(messageRequest, transportRequest);
- }
-
- protected SoapMessage createResponseSoapMessage() {
- SOAPFactory soapFactory = (SOAPFactory) getAxiomRequest().getSOAPEnvelope().getOMFactory();
- return new AxiomSoapMessage(soapFactory);
- }
-
- /**
- * Returns the request as an Axiom SOAP message.
- */
- public SOAPMessage getAxiomRequest() {
- return ((AxiomSoapMessage) getSoapRequest()).getAxiomMessage();
- }
-
- /**
- * Returns the response as an Axiom SOAP message.
- */
- public SOAPMessage getAxiomResponse() {
- return ((AxiomSoapMessage) getSoapResponse()).getAxiomMessage();
- }
-
- public void sendResponse(TransportResponse transportResponse) throws IOException {
- try {
- if (hasResponse()) {
- AxiomSoapMessage response = (AxiomSoapMessage) getSoapResponse();
- SOAPMessage axiomResponse = response.getAxiomMessage();
- String charsetEncoding = axiomResponse.getCharsetEncoding();
-
- OMOutputFormat format = new OMOutputFormat();
- format.setCharSetEncoding(charsetEncoding);
- format.setSOAP11(response.getVersion() == SoapVersion.SOAP_11);
- String contentType = format.getContentType();
- contentType += "; charset=\"" + charsetEncoding + "\"";
-
- transportResponse.addHeader("Content-Type", contentType);
- axiomResponse.serializeAndConsume(transportResponse.getOutputStream(), format);
- }
- }
- catch (XMLStreamException ex) {
- throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
- }
- }
-
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageContextFactory.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java
similarity index 64%
rename from core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageContextFactory.java
rename to core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java
index f4944c8a..17b3eea9 100644
--- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageContextFactory.java
+++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java
@@ -38,49 +38,49 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.context.MessageContextFactory;
-import org.springframework.ws.soap.SoapMessageCreationException;
-import org.springframework.ws.transport.TransportContext;
-import org.springframework.ws.transport.TransportRequest;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+import org.springframework.ws.transport.TransportInputStream;
/**
- * Axiom-specific implementation of the MessageContextFactory interface. Creates a
- * AxiomSoapMessageContext.
+ * Axiom-specific implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory}
+ * interface. Creates {@link org.springframework.ws.soap.axiom.AxiomSoapMessage AxiomSoapMessages}.
*
* To increase reading performance on the the SOAP request created by this message context factory, you can set the
* payloadCaching property to false (default is true). This this will read the
- * contents of the body directly from the TransportRequest. However, when this setting is enabled,
- * the payload can only be read once. This means that any endpoint mappings or interceptors which are based on
- * the message payload (such as the PayloadRootQNameEndpointMapping, the
- * PayloadValidatingInterceptor, or the PayloadLoggingInterceptor) cannot be used. Instead,
- * use an endpoint mapping that does not consume the payload (i.e. the SoapActionEndpointMapping).
+ * contents of the body directly from the stream. However, when this setting is enabled, the payload can only be
+ * read once. This means that any endpoint mappings or interceptors which are based on the message payload
+ * (such as the PayloadRootQNameEndpointMapping, the PayloadValidatingInterceptor, or the
+ * PayloadLoggingInterceptor) cannot be used. Instead, use an endpoint mapping that does not consume the
+ * payload (i.e. the SoapActionEndpointMapping).
*
* Mostly derived from org.apache.axis2.transport.http.HTTPTransportUtils and
* org.apache.axis2.transport.TransportUtils, which we cannot use since they are not part of the Axiom
* distribution.
*
* @author Arjen Poutsma
- * @see AxiomSoapMessageContext
+ * @see AxiomSoapMessage
* @see #setPayloadCaching(boolean)
*/
-public class AxiomSoapMessageContextFactory implements MessageContextFactory, InitializingBean {
-
- private static final Log logger = LogFactory.getLog(AxiomSoapMessageContextFactory.class);
+public class AxiomSoapMessageFactory implements WebServiceMessageFactory, InitializingBean {
private static final String CHAR_SET_ENCODING = "charset";
- private static final String DEFAULT_CHAR_SET_ENCODING = "UTF-8";
-
private static final String CONTENT_TYPE_HEADER = "Content-Type";
+ private static final String DEFAULT_CHAR_SET_ENCODING = "UTF-8";
+
private static final String MULTI_PART_RELATED_CONTENT_TYPE = "multipart/related";
+ private static final Log logger = LogFactory.getLog(AxiomSoapMessageFactory.class);
+
+ private XMLInputFactory inputFactory;
+
private boolean payloadCaching = true;
- private SOAP11Factory soap11Factory;
+ private SOAP11Factory soap11Factory = new SOAP11Factory();
- private SOAP12Factory soap12Factory;
+ private SOAP12Factory soap12Factory = new SOAP12Factory();
/**
* Indicates whether the SOAP Body payload should be cached or not. Default is true. Setting this to
@@ -91,54 +91,67 @@ public class AxiomSoapMessageContextFactory implements MessageContextFactory, In
this.payloadCaching = payloadCaching;
}
- private XMLInputFactory inputFactory;
-
public void afterPropertiesSet() throws Exception {
inputFactory = XMLInputFactory.newInstance();
- soap11Factory = new SOAP11Factory();
- soap12Factory = new SOAP12Factory();
if (logger.isInfoEnabled()) {
logger.info(payloadCaching ? "Enabled payload caching" : "Disabled payload caching");
}
}
- public MessageContext createContext(TransportContext transportContext) throws IOException {
- TransportRequest transportRequest = transportContext.getTransportRequest();
- Iterator iterator = transportRequest.getHeaders(CONTENT_TYPE_HEADER);
- Assert.isTrue(iterator.hasNext(), "No " + CONTENT_TYPE_HEADER + " header present of TransportRequest");
- String contentType = (String) iterator.next();
+ public WebServiceMessage createWebServiceMessage() {
+ return new AxiomSoapMessage(soap11Factory);
+ }
+
+ public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
+ String contentType = null;
+ if (inputStream instanceof TransportInputStream) {
+ TransportInputStream transportInputStream = (TransportInputStream) inputStream;
+ Iterator iterator = transportInputStream.getHeaders(CONTENT_TYPE_HEADER);
+ Assert.isTrue(iterator.hasNext(), "No " + CONTENT_TYPE_HEADER + " header present of TransportRequest");
+ contentType = (String) iterator.next();
+ }
Assert.hasLength(contentType, "No " + CONTENT_TYPE_HEADER + " header present of TransportRequest");
- InputStream inputStream = transportRequest.getInputStream();
try {
- AxiomSoapMessage requestMessage;
- if (contentType.indexOf(MULTI_PART_RELATED_CONTENT_TYPE) == -1) {
- XMLStreamReader reader =
- inputFactory.createXMLStreamReader(inputStream, getCharSetEncoding(contentType));
- SOAPFactory soapFactory = getSoapFactory(contentType);
- StAXSOAPModelBuilder builder =
- new StAXSOAPModelBuilder(reader, soapFactory, soapFactory.getSoapVersionURI());
- requestMessage = createAxiomSoapMessage(builder, null);
+ if (isMultiPartRelated(contentType)) {
+ return createMultiPartAxiomSoapMessage(inputStream, contentType);
}
else {
- requestMessage = createMultiPartAxiomSoapMessage(inputStream, contentType);
+ return createAxiomSoapMessage(inputStream, contentType);
}
- return new AxiomSoapMessageContext(requestMessage, transportRequest);
-
}
catch (XMLStreamException ex) {
- throw new SoapMessageCreationException("Could not create message: " + ex.getMessage(), ex);
+ throw new AxiomSoapMessageCreationException("Could not parse request: " + ex.getMessage(), ex);
}
catch (OMException ex) {
- throw new SoapMessageCreationException("Could not create message: " + ex.getMessage(), ex);
+ throw new AxiomSoapMessageCreationException("Could not create message: " + ex.getMessage(), ex);
}
}
+ private boolean isMultiPartRelated(String contentType) {
+ return contentType.indexOf(MULTI_PART_RELATED_CONTENT_TYPE) != -1;
+ }
+
+ /**
+ * Creates an AxiomSoapMessage without attachments.
+ */
+ private WebServiceMessage createAxiomSoapMessage(InputStream inputStream, String contentType)
+ throws XMLStreamException {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream, getCharSetEncoding(contentType));
+ SOAPFactory soapFactory = getSoapFactory(contentType);
+ StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(reader, soapFactory, soapFactory.getSoapVersionURI());
+ SOAPMessage soapMessage = builder.getSoapMessage();
+ return new AxiomSoapMessage(soapMessage, payloadCaching);
+ }
+
+ /**
+ * Creates an AxiomSoapMessage with attachments.
+ */
private AxiomSoapMessage createMultiPartAxiomSoapMessage(InputStream inputStream, String contentType)
throws XMLStreamException {
Attachments attachments = new Attachments(inputStream, contentType);
if (!(attachments.getAttachmentSpecType().equals(MTOMConstants.SWA_TYPE) ||
attachments.getAttachmentSpecType().equals(MTOMConstants.MTOM_TYPE))) {
- throw new SoapMessageCreationException(
+ throw new AxiomSoapMessageCreationException(
"Unknown attachment type: [" + attachments.getAttachmentSpecType() + "]");
}
XMLStreamReader reader = inputFactory.createXMLStreamReader(attachments.getSOAPPartInputStream(),
@@ -154,18 +167,6 @@ public class AxiomSoapMessageContextFactory implements MessageContextFactory, In
return new AxiomSoapMessage(builder.getSoapMessage(), attachments, payloadCaching);
}
- /**
- * Creates a new AxiomSoapMessage based on the given parameters.
- *
- * @param modelBuilder the builder used to optain the Axiom SOAPMessage
- * @param attachments the attachments, can be null
- * @return the created message
- */
- private AxiomSoapMessage createAxiomSoapMessage(StAXSOAPModelBuilder modelBuilder, Attachments attachments) {
- SOAPMessage soapMessage = modelBuilder.getSoapMessage();
- return new AxiomSoapMessage(soapMessage, attachments, payloadCaching);
- }
-
private SOAPFactory getSoapFactory(String contentType) {
if (contentType.indexOf(SOAP11Constants.SOAP_11_CONTENT_TYPE) != -1) {
return soap11Factory;
@@ -174,7 +175,7 @@ public class AxiomSoapMessageContextFactory implements MessageContextFactory, In
return soap12Factory;
}
else {
- throw new SoapMessageCreationException("Unknown content type '" + contentType + "'");
+ throw new AxiomSoapMessageCreationException("Unknown content type '" + contentType + "'");
}
}
@@ -209,4 +210,5 @@ public class AxiomSoapMessageContextFactory implements MessageContextFactory, In
return value.trim();
}
}
+
}
diff --git a/core/src/main/java/org/springframework/ws/soap/context/AbstractSoapMessageContext.java b/core/src/main/java/org/springframework/ws/soap/context/AbstractSoapMessageContext.java
deleted file mode 100644
index 7a32656d..00000000
--- a/core/src/main/java/org/springframework/ws/soap/context/AbstractSoapMessageContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2006 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.context;
-
-import org.springframework.ws.WebServiceMessage;
-import org.springframework.ws.context.AbstractMessageContext;
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * Abstract implementation of the SoapMessageContext interface. Implements base MessageContext
- * methods by delegating to SoapMessageContext functionality.
- *
- * @author Arjen Poutsma
- */
-public abstract class AbstractSoapMessageContext extends AbstractMessageContext implements SoapMessageContext {
-
- protected AbstractSoapMessageContext(SoapMessage request, TransportRequest transportRequest) {
- super(request, transportRequest);
- }
-
- public final SoapMessage getSoapResponse() {
- return (SoapMessage) getResponse();
- }
-
- public final SoapMessage getSoapRequest() {
- return (SoapMessage) getRequest();
- }
-
- protected final WebServiceMessage createResponseMessage() {
- return createResponseSoapMessage();
- }
-
- protected abstract SoapMessage createResponseSoapMessage();
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/context/SoapMessageContext.java b/core/src/main/java/org/springframework/ws/soap/context/SoapMessageContext.java
deleted file mode 100644
index a5161271..00000000
--- a/core/src/main/java/org/springframework/ws/soap/context/SoapMessageContext.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2006 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.context;
-
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.soap.SoapMessage;
-
-/**
- * SOAP-specific extension of the MessageContext interface. Contains methods to obtain
- * SoapMessages instead of WebServiceMessages.
- *
- * @author Arjen Poutsma
- */
-public interface SoapMessageContext extends MessageContext {
-
- /**
- * Returns the request SOAP message.
- *
- * @return the request message
- */
- SoapMessage getSoapRequest();
-
- /**
- * Returns the response message, if created. Returns null if no response message was created so far.
- *
- * @return the response message, or null if none was created
- * @see #hasResponse()
- */
- SoapMessage getSoapResponse();
-
-
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/context/package.html b/core/src/main/java/org/springframework/ws/soap/context/package.html
deleted file mode 100644
index 7f5e8b44..00000000
--- a/core/src/main/java/org/springframework/ws/soap/context/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-Contains the SoapMessageContext interface.
-
-
diff --git a/core/src/main/java/org/springframework/ws/soap/endpoint/SimpleSoapExceptionResolver.java b/core/src/main/java/org/springframework/ws/soap/endpoint/SimpleSoapExceptionResolver.java
index bfa2ea64..453f5aec 100644
--- a/core/src/main/java/org/springframework/ws/soap/endpoint/SimpleSoapExceptionResolver.java
+++ b/core/src/main/java/org/springframework/ws/soap/endpoint/SimpleSoapExceptionResolver.java
@@ -2,11 +2,12 @@ package org.springframework.ws.soap.endpoint;
import java.util.Locale;
+import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.endpoint.AbstractEndpointExceptionResolver;
import org.springframework.ws.soap.SoapBody;
-import org.springframework.ws.soap.context.SoapMessageContext;
+import org.springframework.ws.soap.SoapMessage;
/**
* Simple, SOAP-specific implementation of the EndpointExceptionResolver that stores the exception's
@@ -26,12 +27,11 @@ public class SimpleSoapExceptionResolver extends AbstractEndpointExceptionResolv
}
protected boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex) {
- if (!(messageContext instanceof SoapMessageContext)) {
- throw new IllegalArgumentException("SimpleSoapExceptionResolver requires a SoapMessageContext");
- }
+ Assert.isTrue(messageContext.getResponse() instanceof SoapMessage,
+ "SimpleSoapExceptionResolver requires a SoapMessage");
+ SoapMessage response = (SoapMessage) messageContext.getResponse();
String faultString = StringUtils.hasLength(ex.getMessage()) ? ex.getMessage() : ex.toString();
- SoapMessageContext soapContext = (SoapMessageContext) messageContext;
- SoapBody body = soapContext.getSoapResponse().getSoapBody();
+ SoapBody body = response.getSoapBody();
body.addServerOrReceiverFault(faultString, locale);
return true;
}
diff --git a/core/src/main/java/org/springframework/ws/soap/endpoint/SoapFaultMappingExceptionResolver.java b/core/src/main/java/org/springframework/ws/soap/endpoint/SoapFaultMappingExceptionResolver.java
index 8219215d..5234e1fe 100644
--- a/core/src/main/java/org/springframework/ws/soap/endpoint/SoapFaultMappingExceptionResolver.java
+++ b/core/src/main/java/org/springframework/ws/soap/endpoint/SoapFaultMappingExceptionResolver.java
@@ -19,11 +19,11 @@ package org.springframework.ws.soap.endpoint;
import java.util.Enumeration;
import java.util.Properties;
+import org.springframework.util.Assert;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.endpoint.AbstractEndpointExceptionResolver;
import org.springframework.ws.soap.SoapBody;
import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.context.SoapMessageContext;
import org.springframework.ws.soap.soap11.Soap11Body;
/**
@@ -63,16 +63,15 @@ public class SoapFaultMappingExceptionResolver extends AbstractEndpointException
}
protected boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex) {
- if (!(messageContext instanceof SoapMessageContext)) {
- throw new IllegalArgumentException("SoapFaultMappingExceptionResolver requires a SoapMessageContext");
- }
+ Assert.isTrue(messageContext.getResponse() instanceof SoapMessage,
+ "SimpleSoapExceptionResolver requires a SoapMessage");
+
SoapFaultDefinition definition = getFaultDefinition(ex);
if (definition == null) {
return false;
}
- SoapMessageContext soapContext = (SoapMessageContext) messageContext;
- SoapMessage response = soapContext.getSoapResponse();
- SoapBody soapBody = response.getSoapBody();
+ SoapMessage soapResponse = (SoapMessage) messageContext.getResponse();
+ SoapBody soapBody = soapResponse.getSoapBody();
if (SoapFaultDefinition.SERVER.equals(definition.getFaultCode()) ||
SoapFaultDefinition.RECEIVER.equals(definition.getFaultCode())) {
diff --git a/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java b/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java
index cd354fa7..a3594fa7 100644
--- a/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java
+++ b/core/src/main/java/org/springframework/ws/soap/endpoint/mapping/SoapActionEndpointMapping.java
@@ -26,6 +26,8 @@ import org.springframework.ws.context.MessageContext;
import org.springframework.ws.endpoint.mapping.AbstractMapBasedEndpointMapping;
import org.springframework.ws.soap.SoapEndpointInvocationChain;
import org.springframework.ws.soap.SoapEndpointMapping;
+import org.springframework.ws.transport.TransportContext;
+import org.springframework.ws.transport.TransportContextHolder;
/**
* Implementation of the EndpointMapping interface to map from SOAPAction headers to endpoint
@@ -85,7 +87,10 @@ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping i
}
protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception {
- Iterator iterator = messageContext.getTransportRequest().getHeaders(SOAP_ACTION_HEADER);
+ TransportContext transportContext = TransportContextHolder.getTransportContext();
+ Assert.notNull(transportContext,
+ "No TransportContext associated with current thread, cannot read SOAPAction header");
+ Iterator iterator = transportContext.getTransportInputStream().getHeaders(SOAP_ACTION_HEADER);
String soapAction = "";
if (iterator.hasNext()) {
soapAction = (String) iterator.next();
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java
index ab3c0433..1eb56e24 100644
--- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java
@@ -26,6 +26,7 @@ import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.xml.soap.AttachmentPart;
+import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
@@ -34,12 +35,12 @@ import javax.xml.soap.SOAPMessage;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
import org.springframework.ws.soap.AbstractSoapMessage;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.soap.AttachmentException;
import org.springframework.ws.soap.SoapEnvelope;
-import org.springframework.ws.soap.SoapVersion;
-import org.springframework.ws.soap.saaj.support.SaajUtils;
+import org.springframework.ws.transport.TransportOutputStream;
/**
* SAAJ-specific implementation of the SoapMessage interface. Accessed via the
@@ -47,11 +48,10 @@ import org.springframework.ws.soap.saaj.support.SaajUtils;
*
* @author Arjen Poutsma
* @see javax.xml.soap.SOAPMessage
- * @see SaajSoapMessageContext
*/
public abstract class SaajSoapMessage extends AbstractSoapMessage {
- private final SOAPMessage saajMessage;
+ private SOAPMessage saajMessage;
private SoapEnvelope envelope;
@@ -61,6 +61,7 @@ public abstract class SaajSoapMessage extends AbstractSoapMessage {
* @param soapMessage the SAAJ SOAPMessage
*/
protected SaajSoapMessage(SOAPMessage soapMessage) {
+ Assert.notNull(soapMessage, "soapMessage must not be null");
saajMessage = soapMessage;
}
@@ -71,6 +72,14 @@ public abstract class SaajSoapMessage extends AbstractSoapMessage {
return saajMessage;
}
+ /**
+ * Sets the SAAJ SOAPMessage that this SaajSoapMessage is based on.
+ */
+ public final void setSaajMessage(SOAPMessage soapMessage) {
+ Assert.notNull(soapMessage, "soapMessage must not be null");
+ saajMessage = soapMessage;
+ }
+
public final SoapEnvelope getEnvelope() {
if (envelope == null) {
try {
@@ -91,6 +100,21 @@ public abstract class SaajSoapMessage extends AbstractSoapMessage {
if (saajMessage.saveRequired()) {
saajMessage.saveChanges();
}
+ if (outputStream instanceof TransportOutputStream) {
+ TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
+ // some SAAJ implementations (Axis 1) do not have a Content-Type header by default
+ MimeHeaders headers = saajMessage.getMimeHeaders();
+ if (ObjectUtils.isEmpty(headers.getHeader("Content-Type"))) {
+ headers.addHeader("Content-Type", getVersion().getContentType());
+ if (saajMessage.saveRequired()) {
+ saajMessage.saveChanges();
+ }
+ }
+ for (Iterator iterator = headers.getAllHeaders(); iterator.hasNext();) {
+ MimeHeader mimeHeader = (MimeHeader) iterator.next();
+ transportOutputStream.addHeader(mimeHeader.getName(), mimeHeader.getValue());
+ }
+ }
saajMessage.writeTo(outputStream);
}
catch (SOAPException ex) {
@@ -163,15 +187,6 @@ public abstract class SaajSoapMessage extends AbstractSoapMessage {
};
}
- public SoapVersion getVersion() {
- if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
- return SoapVersion.SOAP_11;
- }
- else {
- return super.getVersion();
- }
- }
-
/**
* SAAJ-specific implementation of org.springframework.ws.soap.Attachment
*/
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageContext.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageContext.java
deleted file mode 100644
index f91e8e6b..00000000
--- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageContext.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2005 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.saaj;
-
-import java.io.IOException;
-import java.util.Iterator;
-import javax.xml.soap.MessageFactory;
-import javax.xml.soap.MimeHeader;
-import javax.xml.soap.MimeHeaders;
-import javax.xml.soap.SOAPException;
-import javax.xml.soap.SOAPMessage;
-
-import org.springframework.util.Assert;
-import org.springframework.util.ObjectUtils;
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.SoapMessageCreationException;
-import org.springframework.ws.soap.context.AbstractSoapMessageContext;
-import org.springframework.ws.transport.TransportRequest;
-import org.springframework.ws.transport.TransportResponse;
-
-/**
- * SAAJ-specific implementation of the SoapMessageContext interface. Created by the
- * SaajSoapMessageContextFactory.
- *
- * @author Arjen Poutsma
- * @see SaajSoapMessageContextFactory
- */
-public abstract class SaajSoapMessageContext extends AbstractSoapMessageContext {
-
- private final MessageFactory messageFactory;
-
- /**
- * Creates a new instance based on the given SAAJ request message, and a message factory.
- *
- * @param request the request message
- * @param transportRequest the transport request
- * @param messageFactory the message factory used for creating a response
- */
- protected SaajSoapMessageContext(SaajSoapMessage request,
- TransportRequest transportRequest,
- MessageFactory messageFactory) {
- super(request, transportRequest);
- Assert.notNull(messageFactory);
- this.messageFactory = messageFactory;
- }
-
- public final void sendResponse(TransportResponse transportResponse) throws IOException {
- if (hasResponse()) {
- SOAPMessage response = getSaajResponse();
- try {
- if (response.saveRequired()) {
- response.saveChanges();
- }
- // some SAAJ implementations (Axis 1) do not have a Content-Type header by default
- MimeHeaders headers = response.getMimeHeaders();
- if (ObjectUtils.isEmpty(headers.getHeader("Content-Type"))) {
- headers.addHeader("Content-Type", getSoapResponse().getVersion().getContentType());
- if (response.saveRequired()) {
- response.saveChanges();
- }
- }
- for (Iterator iterator = headers.getAllHeaders(); iterator.hasNext();) {
- MimeHeader mimeHeader = (MimeHeader) iterator.next();
- transportResponse.addHeader(mimeHeader.getName(), mimeHeader.getValue());
- }
- response.writeTo(transportResponse.getOutputStream());
- }
- catch (SOAPException ex) {
- throw new SaajSoapMessageException("Could not write message to TransportResponse: " + ex.getMessage(),
- ex);
- }
- }
- }
-
- protected SoapMessage createResponseSoapMessage() {
- try {
- SOAPMessage saajMessage = messageFactory.createMessage();
- return createSaajSoapMessage(saajMessage);
- }
- catch (SOAPException ex) {
- throw new SoapMessageCreationException("Could not create message: " + ex.toString(), ex);
- }
- }
-
- /**
- * Creates a new SaajSoapMessage using the given SAAJ message.
- */
- protected abstract SaajSoapMessage createSaajSoapMessage(SOAPMessage saajMessage);
-
- /**
- * Returns the request as a SAAJ SOAP message.
- */
- public final SOAPMessage getSaajRequest() {
- return ((SaajSoapMessage) getSoapRequest()).getSaajMessage();
- }
-
- /**
- * Returns the response as a SAAJ SOAP message.
- */
- public final SOAPMessage getSaajResponse() {
- return ((SaajSoapMessage) getSoapResponse()).getSaajMessage();
- }
-
- /**
- * Sets the request to the given SAAJ SOAP message.
- */
- public abstract void setSaajRequest(SOAPMessage request);
-
- /**
- * Sets the response to the given SAAJ SOAP message.
- */
- public abstract void setSaajResponse(SOAPMessage response);
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageContextFactory.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageContextFactory.java
deleted file mode 100644
index f57f2f3f..00000000
--- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageContextFactory.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2005 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.saaj;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-import javax.xml.soap.MessageFactory;
-import javax.xml.soap.MimeHeaders;
-import javax.xml.soap.SOAPConstants;
-import javax.xml.soap.SOAPException;
-import javax.xml.soap.SOAPMessage;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.StringUtils;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.context.MessageContextFactory;
-import org.springframework.ws.soap.SoapMessageCreationException;
-import org.springframework.ws.soap.saaj.saaj12.Saaj12SoapMessageContext;
-import org.springframework.ws.soap.saaj.saaj13.Saaj13SoapMessageContext;
-import org.springframework.ws.soap.saaj.support.SaajUtils;
-import org.springframework.ws.transport.TransportContext;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * SAAJ-specific implementation of the MessageContextFactory interface. Creates a
- * SaajSoapMessageContext. This factory will use SAAJ 1.3 when found, or fall back to SAAJ 1.2.
- *
- * @author Arjen Poutsma
- * @see SaajSoapMessageContext
- */
-public class SaajSoapMessageContextFactory implements MessageContextFactory, InitializingBean {
-
- private static final Log logger = LogFactory.getLog(SaajSoapMessageContextFactory.class);
-
- private MessageFactory messageFactory;
-
- private String messageFactoryProtocol;
-
- public void setMessageFactory(MessageFactory messageFactory) {
- this.messageFactory = messageFactory;
- }
-
- /**
- * Sets the protocol for the MessageFactory. Only used for SAAJ 1.3+, defaults to
- * SOAPConstants.DEFAULT_SOAP_PROTOCOL (i.e. SOAP 1.1).
- *
- * @see MessageFactory#newInstance(String)
- * @see SOAPConstants#DEFAULT_SOAP_PROTOCOL
- * @see SOAPConstants#SOAP_1_1_PROTOCOL
- * @see SOAPConstants#SOAP_1_2_PROTOCOL
- * @see SOAPConstants#DYNAMIC_SOAP_PROTOCOL
- */
- public void setSoapProtocol(String messageFactoryProtocol) {
- this.messageFactoryProtocol = messageFactoryProtocol;
- }
-
- public void afterPropertiesSet() throws Exception {
- if (messageFactory == null) {
- try {
- if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
- if (!StringUtils.hasLength(messageFactoryProtocol)) {
- messageFactoryProtocol = SOAPConstants.DEFAULT_SOAP_PROTOCOL;
- }
- if (logger.isInfoEnabled()) {
- logger.info("Creating SAAJ 1.3 MessageFactory with " + messageFactoryProtocol);
- }
- messageFactory = MessageFactory.newInstance(messageFactoryProtocol);
- }
- else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
- if (logger.isInfoEnabled()) {
- logger.info("Creating SAAJ 1.2 MessageFactory");
- }
- messageFactory = MessageFactory.newInstance();
- }
- else {
- throw new IllegalStateException("SaajSoapMessageContextFactory requires SAAJ 1.2, which was not" +
- "found on the classpath");
- }
- }
- catch (SOAPException ex) {
- throw new SoapMessageCreationException("Could not create MessageFactory: " + ex.getMessage(), ex);
- }
- }
- }
-
- public MessageContext createContext(TransportContext transportContext) throws IOException {
- TransportRequest transportRequest = transportContext.getTransportRequest();
- MimeHeaders mimeHeaders = new MimeHeaders();
- for (Iterator headerNames = transportRequest.getHeaderNames(); headerNames.hasNext();) {
- String headerName = (String) headerNames.next();
- for (Iterator headerValues = transportRequest.getHeaders(headerName); headerValues.hasNext();) {
- String headerValue = (String) headerValues.next();
- StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");
- while (tokenizer.hasMoreTokens()) {
- mimeHeaders.addHeader(headerName, tokenizer.nextToken().trim());
- }
- }
- }
- try {
- SOAPMessage requestMessage = messageFactory.createMessage(mimeHeaders, transportRequest.getInputStream());
- if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
- return new Saaj13SoapMessageContext(requestMessage, transportRequest, messageFactory);
- }
- else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
- return new Saaj12SoapMessageContext(requestMessage, transportRequest, messageFactory);
- }
- else {
- throw new IllegalStateException(
- "SaajSoapMessageContextFactory requires SAAJ 1.2, which was not" + "found on the classpath");
- }
- }
- catch (SOAPException ex) {
- throw new SoapMessageCreationException("Could not create message from TransportRequest: " + ex.getMessage(),
- ex);
- }
- }
-
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java
new file mode 100644
index 00000000..ad49a6f5
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2006 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.saaj;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.MimeHeaders;
+import javax.xml.soap.SOAPConstants;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.StringUtils;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+import org.springframework.ws.soap.SoapMessageCreationException;
+import org.springframework.ws.soap.saaj.saaj12.Saaj12SoapMessage;
+import org.springframework.ws.soap.saaj.saaj13.Saaj13SoapMessage;
+import org.springframework.ws.soap.saaj.support.SaajUtils;
+import org.springframework.ws.transport.TransportInputStream;
+
+/**
+ * SAAJ-specific implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory}.
+ * This factory will use SAAJ 1.3 when found, or fall back to SAAJ 1.2.
+ *
+ * @author Arjen Poutsma
+ * @see org.springframework.ws.soap.saaj.SaajSoapMessage
+ */
+public class SaajSoapMessageFactory implements WebServiceMessageFactory, InitializingBean {
+
+ private static final Log logger = LogFactory.getLog(SaajSoapMessageFactory.class);
+
+ private MessageFactory messageFactory;
+
+ private String messageFactoryProtocol;
+
+ public void afterPropertiesSet() throws Exception {
+ try {
+ if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
+ if (!StringUtils.hasLength(messageFactoryProtocol)) {
+ messageFactoryProtocol = SOAPConstants.DEFAULT_SOAP_PROTOCOL;
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("Creating SAAJ 1.3 MessageFactory with " + messageFactoryProtocol);
+ }
+ messageFactory = MessageFactory.newInstance(messageFactoryProtocol);
+ }
+ else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Creating SAAJ 1.2 MessageFactory");
+ }
+ messageFactory = MessageFactory.newInstance();
+ }
+ else {
+ throw new IllegalStateException(
+ "SaajSoapMessageContextFactory requires SAAJ 1.2, which was not" + "found on the classpath");
+ }
+ }
+ catch (SOAPException ex) {
+ throw new SoapMessageCreationException("Could not create MessageFactory: " + ex.getMessage(), ex);
+ }
+ }
+
+ public WebServiceMessage createWebServiceMessage() {
+ try {
+ return createSaajSoapMessage(messageFactory.createMessage());
+ }
+ catch (SOAPException ex) {
+ throw new SoapMessageCreationException("Could not create empty message: " + ex.getMessage(), ex);
+ }
+ }
+
+ public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
+ MimeHeaders mimeHeaders = new MimeHeaders();
+ if (inputStream instanceof TransportInputStream) {
+ TransportInputStream transportInputStream = (TransportInputStream) inputStream;
+ for (Iterator headerNames = transportInputStream.getHeaderNames(); headerNames.hasNext();) {
+ String headerName = (String) headerNames.next();
+ for (Iterator headerValues = transportInputStream.getHeaders(headerName); headerValues.hasNext();) {
+ String headerValue = (String) headerValues.next();
+ StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");
+ while (tokenizer.hasMoreTokens()) {
+ mimeHeaders.addHeader(headerName, tokenizer.nextToken().trim());
+ }
+ }
+ }
+ }
+ try {
+ return createSaajSoapMessage(messageFactory.createMessage(mimeHeaders, inputStream));
+ }
+ catch (SOAPException ex) {
+ throw new SoapMessageCreationException("Could not create message from InputStream: " + ex.getMessage(), ex);
+ }
+ }
+
+ private WebServiceMessage createSaajSoapMessage(SOAPMessage requestMessage) {
+ if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
+ return new Saaj13SoapMessage(requestMessage);
+ }
+ else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
+ return new Saaj12SoapMessage(requestMessage);
+ }
+ else {
+ throw new IllegalStateException(
+ "SaajSoapMessageContextFactory requires SAAJ 1.2, which was not" + "found on the classpath");
+ }
+ }
+
+ /**
+ * Sets the protocol for the MessageFactory. Only used for SAAJ 1.3+, defaults to
+ * SOAPConstants.DEFAULT_SOAP_PROTOCOL (i.e. SOAP 1.1).
+ *
+ * @see MessageFactory#newInstance(String)
+ * @see javax.xml.soap.SOAPConstants#DEFAULT_SOAP_PROTOCOL
+ * @see javax.xml.soap.SOAPConstants#SOAP_1_1_PROTOCOL
+ * @see javax.xml.soap.SOAPConstants#SOAP_1_2_PROTOCOL
+ * @see javax.xml.soap.SOAPConstants#DYNAMIC_SOAP_PROTOCOL
+ */
+ public void setSoapProtocol(String messageFactoryProtocol) {
+ this.messageFactoryProtocol = messageFactoryProtocol;
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessage.java b/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessage.java
index 9a416c74..e5ef46a8 100644
--- a/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessage.java
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessage.java
@@ -20,17 +20,16 @@ import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.soap.SoapEnvelope;
+import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
/**
- * SAAJ 1.2 specific implementation of the SoapMessage interface. Accessed via the
- * SaajSoapMessageContext.
+ * SAAJ 1.2 specific implementation of the SoapMessage interface.
*
* @author Arjen Poutsma
* @see javax.xml.soap.SOAPMessage
- * @see org.springframework.ws.soap.saaj.SaajSoapMessageContext
*/
-class Saaj12SoapMessage extends SaajSoapMessage {
+public class Saaj12SoapMessage extends SaajSoapMessage {
public Saaj12SoapMessage(SOAPMessage soapMessage) {
super(soapMessage);
@@ -40,4 +39,7 @@ class Saaj12SoapMessage extends SaajSoapMessage {
return new Saaj12SoapEnvelope(saajEnvelope);
}
+ public SoapVersion getVersion() {
+ return SoapVersion.SOAP_11;
+ }
}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessageContext.java b/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessageContext.java
deleted file mode 100644
index 8ffcb9f6..00000000
--- a/core/src/main/java/org/springframework/ws/soap/saaj/saaj12/Saaj12SoapMessageContext.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2006 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.saaj.saaj12;
-
-import javax.xml.soap.MessageFactory;
-import javax.xml.soap.SOAPMessage;
-
-import org.springframework.ws.soap.saaj.SaajSoapMessage;
-import org.springframework.ws.soap.saaj.SaajSoapMessageContext;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * SAAJ 1.2 specific implementation of the SoapMessageContext interface. Created by the
- * SaajSoapMessageContextFactory.
- *
- * @author Arjen Poutsma
- * @see org.springframework.ws.soap.saaj.SaajSoapMessageContextFactory
- */
-public class Saaj12SoapMessageContext extends SaajSoapMessageContext {
-
- /**
- * Creates a new instance based on the given SAAJ request message, and a message factory.
- *
- * @param request the request message
- * @param transportRequest the transport request
- * @param messageFactory the message factory used for creating a response
- */
- public Saaj12SoapMessageContext(SOAPMessage request,
- TransportRequest transportRequest,
- MessageFactory messageFactory) {
- super(new Saaj12SoapMessage(request), transportRequest, messageFactory);
- }
-
- protected SaajSoapMessage createSaajSoapMessage(SOAPMessage saajMessage) {
- return new Saaj12SoapMessage(saajMessage);
- }
-
- public void setSaajRequest(SOAPMessage request) {
- setRequest(new Saaj12SoapMessage(request));
- }
-
- public void setSaajResponse(SOAPMessage response) {
- setResponse(new Saaj12SoapMessage(response));
- }
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessage.java b/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessage.java
index 0a96a428..63c9208e 100644
--- a/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessage.java
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessage.java
@@ -22,14 +22,19 @@ import javax.xml.soap.SOAPMessage;
import org.springframework.ws.soap.SoapEnvelope;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
-class Saaj13SoapMessage extends SaajSoapMessage {
+/**
+ * SAAJ 1.3 specific implementation of the SoapMessage interface.
+ *
+ * @author Arjen Poutsma
+ */
+public class Saaj13SoapMessage extends SaajSoapMessage {
/**
* Create a new SaajSoapMessage based on the given SAAJ SOAPMessage.
*
* @param soapMessage the SAAJ SOAPMessage
*/
- protected Saaj13SoapMessage(SOAPMessage soapMessage) {
+ public Saaj13SoapMessage(SOAPMessage soapMessage) {
super(soapMessage);
}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessageContext.java b/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessageContext.java
deleted file mode 100644
index c60dd80d..00000000
--- a/core/src/main/java/org/springframework/ws/soap/saaj/saaj13/Saaj13SoapMessageContext.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2006 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.saaj.saaj13;
-
-import javax.xml.soap.MessageFactory;
-import javax.xml.soap.SOAPMessage;
-
-import org.springframework.ws.soap.saaj.SaajSoapMessage;
-import org.springframework.ws.soap.saaj.SaajSoapMessageContext;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * SAAJ 1.3 specific implementation of the SoapMessageContext interface. Created by the
- * SaajSoapMessageContextFactory.
- *
- * @author Arjen Poutsma
- * @see org.springframework.ws.soap.saaj.SaajSoapMessageContextFactory
- */
-public class Saaj13SoapMessageContext extends SaajSoapMessageContext {
-
- /**
- * Creates a new instance based on the given SAAJ request message, and a message factory.
- *
- * @param request the request message
- * @param transportRequest the transport request
- * @param messageFactory the message factory used for creating a response
- */
- public Saaj13SoapMessageContext(SOAPMessage request,
- TransportRequest transportRequest,
- MessageFactory messageFactory) {
- super(new Saaj13SoapMessage(request), transportRequest, messageFactory);
- }
-
- protected SaajSoapMessage createSaajSoapMessage(SOAPMessage saajMessage) {
- return new Saaj13SoapMessage(saajMessage);
- }
-
- public void setSaajRequest(SOAPMessage request) {
- setRequest(new Saaj13SoapMessage(request));
- }
-
- public void setSaajResponse(SOAPMessage response) {
- setResponse(new Saaj13SoapMessage(response));
- }
-}
diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java b/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java
index 5680f08b..0ef4b49d 100644
--- a/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java
+++ b/core/src/main/java/org/springframework/ws/soap/saaj/support/SaajUtils.java
@@ -150,18 +150,6 @@ public abstract class SaajUtils {
}
}
- /**
- * Loads a SAAJ SOAPMessage from the given resource.
- *
- * @param resource the resource to read from
- * @return the loaded SAAJ message
- * @throws SOAPException if the message cannot be constructed
- * @throws IOException if the input stream resource cannot be loaded
- */
- public static SOAPMessage loadMessage(Resource resource) throws SOAPException, IOException {
- return loadMessage(resource, MessageFactory.newInstance());
- }
-
/**
* Loads a SAAJ SOAPMessage from the given resource with a given message factory.
*
diff --git a/core/src/main/java/org/springframework/ws/transport/SimpleTransportContext.java b/core/src/main/java/org/springframework/ws/transport/SimpleTransportContext.java
new file mode 100644
index 00000000..32ea9024
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/SimpleTransportContext.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 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.transport;
+
+/**
+ * Simple implementation of the TransportContext interface.
+ *
+ * @author Arjen Poutsma
+ */
+public class SimpleTransportContext implements TransportContext {
+
+ private final TransportInputStream transportInputStream;
+
+ private final TransportOutputStream transportOutputStream;
+
+ /**
+ * Creates a new SimpleTransportContext that exposes the given streams.
+ */
+ public SimpleTransportContext(TransportInputStream transportInputStream,
+ TransportOutputStream transportOutputStream) {
+ this.transportInputStream = transportInputStream;
+ this.transportOutputStream = transportOutputStream;
+ }
+
+ public TransportInputStream getTransportInputStream() {
+ return transportInputStream;
+ }
+
+ public TransportOutputStream getTransportOutputStream() {
+ return transportOutputStream;
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/TransportContext.java b/core/src/main/java/org/springframework/ws/transport/TransportContext.java
index 4bc488cc..06aa10ab 100644
--- a/core/src/main/java/org/springframework/ws/transport/TransportContext.java
+++ b/core/src/main/java/org/springframework/ws/transport/TransportContext.java
@@ -1,15 +1,21 @@
package org.springframework.ws.transport;
/**
- * Defines the contract for Web service request that come in via a transport. Exposes headers and the inputstream to
- * read from.
+ * Strategy interface for determining the current {@link TransportInputStream} and {@link TransportOutputStream}.
+ *
+ * An instance of this class can be associated with a thread via the {@link TransportContextHolder} class.
*
* @author Arjen Poutsma
*/
public interface TransportContext {
- TransportRequest getTransportRequest() throws TransportException;
-
- TransportResponse getTransportResponse() throws TransportException;
+ /**
+ * Returns the current TransportInputStream.
+ */
+ TransportInputStream getTransportInputStream();
+ /**
+ * Returns the current TransportOutputStream.
+ */
+ TransportOutputStream getTransportOutputStream();
}
diff --git a/core/src/main/java/org/springframework/ws/transport/TransportContextHolder.java b/core/src/main/java/org/springframework/ws/transport/TransportContextHolder.java
new file mode 100644
index 00000000..d893bdd6
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/TransportContextHolder.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 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.transport;
+
+/**
+ * Simple holder class that associates a TransportContext instance with the current thread. The
+ * TransportContext will be inherited by any child threads spawned by the current thread.
+ *
+ * @author Arjen Poutsma
+ * @see TransportContext
+ */
+public abstract class TransportContextHolder {
+
+ private static final ThreadLocal transportContextHolder = new InheritableThreadLocal();
+
+ /**
+ * Associate the given TransportContext with the current thread.
+ *
+ * @param transportContext the current transport context, or null to reset the thread-bound context
+ */
+ public static void setTransportContext(TransportContext transportContext) {
+ transportContextHolder.set(transportContext);
+ }
+
+ /**
+ * Return the TransportContext associated with the current thread, if any.
+ *
+ * @return the current transport context, or null if none
+ */
+ public static TransportContext getTransportContext() {
+ return (TransportContext) transportContextHolder.get();
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/TransportInputStream.java b/core/src/main/java/org/springframework/ws/transport/TransportInputStream.java
new file mode 100644
index 00000000..6569c847
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/TransportInputStream.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2006 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.transport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+
+/**
+ * A TransportInputStream is an input stream with MIME input headers. It is used to construct {@link
+ * org.springframework.ws.WebServiceMessage WebServiceMessages} from a transport.
+ *
+ * @author Arjen Poutsma
+ * @see #getHeaderNames()
+ * @see #getHeaders(String)
+ */
+public abstract class TransportInputStream extends InputStream {
+
+ protected TransportInputStream() {
+ }
+
+ public void close() throws IOException {
+ getInputStream().close();
+ }
+
+ public int available() throws IOException {
+ return getInputStream().available();
+ }
+
+ public synchronized void mark(int readlimit) {
+ try {
+ getInputStream().mark(readlimit);
+ }
+ catch (IOException e) {
+ }
+ }
+
+ public boolean markSupported() {
+ try {
+ return getInputStream().markSupported();
+ }
+ catch (IOException e) {
+ return false;
+ }
+ }
+
+ public int read(byte b[]) throws IOException {
+ return getInputStream().read(b);
+ }
+
+ public int read(byte b[], int off, int len) throws IOException {
+ return getInputStream().read(b, off, len);
+ }
+
+ public synchronized void reset() throws IOException {
+ getInputStream().reset();
+ }
+
+ public long skip(long n) throws IOException {
+ return getInputStream().skip(n);
+ }
+
+ public int read() throws IOException {
+ return getInputStream().read();
+ }
+
+ /**
+ * Returns the input stream to read from.
+ */
+ protected abstract InputStream getInputStream() throws IOException;
+
+ /**
+ * Returns an iteration over all the header names this request contains. Returns an empty Iterator if
+ * the request has no headers.
+ */
+ public abstract Iterator getHeaderNames() throws IOException;
+
+ /**
+ * Returns an iteration over all the string values of the specified request header. Returns an empty
+ * Iterator if the request did not include any headers of the specified name.
+ */
+ public abstract Iterator getHeaders(String name) throws IOException;
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java b/core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java
new file mode 100644
index 00000000..3b8a788f
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/TransportOutputStream.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 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.transport;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A TransportOutputStream is an output stream with MIME input headers. It is used to write {@link
+ * org.springframework.ws.WebServiceMessage WebServiceMessages} to a transport.
+ *
+ * @author Arjen Poutsma
+ * @see #addHeader(String,String)
+ */
+public abstract class TransportOutputStream extends OutputStream {
+
+ protected TransportOutputStream() {
+ }
+
+ public void close() throws IOException {
+ getOutputStream().close();
+ }
+
+ public void flush() throws IOException {
+ getOutputStream().flush();
+ }
+
+ public void write(byte b[]) throws IOException {
+ getOutputStream().write(b);
+ }
+
+ public void write(byte b[], int off, int len) throws IOException {
+ getOutputStream().write(b, off, len);
+ }
+
+ public void write(int b) throws IOException {
+ getOutputStream().write(b);
+ }
+
+ /**
+ * Adds a response header with the given name and value. This method can be called multiple times, to allow for
+ * headers with multiple values.
+ *
+ * @param name the name of the header
+ * @param value the value of the header
+ */
+ public abstract void addHeader(String name, String value) throws IOException;
+
+ /**
+ * Returns the output stream to write to.
+ */
+ protected abstract OutputStream getOutputStream() throws IOException;
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/TransportRequest.java b/core/src/main/java/org/springframework/ws/transport/TransportRequest.java
deleted file mode 100644
index 6d0efbfd..00000000
--- a/core/src/main/java/org/springframework/ws/transport/TransportRequest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2006 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.transport;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Iterator;
-
-/**
- * Defines the contract for Web service request that come in via a transport. Exposes headers and the inputstream to
- * read from.
- *
- * @author Arjen Poutsma
- */
-public interface TransportRequest {
-
- /**
- * Returns an iteratoion over all the header names this request contains. Returns an empty Iterator if
- * the request has no headers, this method .
- */
- Iterator getHeaderNames() throws TransportException;
-
- /**
- * Returns an iteration over all the string values of the specified request header. Returns an empty
- * Iterator if the request did not include any headers of the specified name.
- */
- Iterator getHeaders(String name) throws TransportException;
-
- /**
- * Returns the contents of the request as a InputStream.
- */
- InputStream getInputStream() throws TransportException, IOException;
-
- /**
- * Return a URL handle for this request.
- */
- String getUrl() throws TransportException;
-
-}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpServletTransportInputStream.java b/core/src/main/java/org/springframework/ws/transport/http/HttpServletTransportInputStream.java
new file mode 100644
index 00000000..516d54a3
--- /dev/null
+++ b/core/src/main/java/org/springframework/ws/transport/http/HttpServletTransportInputStream.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2006 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.transport.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.ws.transport.TransportException;
+import org.springframework.ws.transport.TransportInputStream;
+import org.springframework.ws.transport.support.EnumerationIterator;
+
+/**
+ * HTTP Servlet specific implementation of the TransportInputStream interface. Exposes the
+ * HttpServletRequest.
+ *
+ * @author Arjen Poutsma
+ * @see #getHttpServletRequest()
+ */
+public class HttpServletTransportInputStream extends TransportInputStream {
+
+ private final HttpServletRequest httpServletRequest;
+
+ /**
+ * Constructs a new instance of the HttpTransportRequest with the given
+ * HttpServletRequest.
+ */
+ public HttpServletTransportInputStream(HttpServletRequest httpServletRequest) throws IOException {
+ this.httpServletRequest = httpServletRequest;
+ }
+
+ protected InputStream getInputStream() throws IOException {
+ return httpServletRequest.getInputStream();
+ }
+
+ /**
+ * Returns the wrapped HttpServletRequest.
+ */
+ public HttpServletRequest getHttpServletRequest() {
+ return httpServletRequest;
+ }
+
+ public Iterator getHeaderNames() throws TransportException {
+ return new EnumerationIterator(httpServletRequest.getHeaderNames());
+ }
+
+ public Iterator getHeaders(String name) throws TransportException {
+ return new EnumerationIterator(httpServletRequest.getHeaders(name));
+ }
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpTransportResponse.java b/core/src/main/java/org/springframework/ws/transport/http/HttpServletTransportOutputStream.java
similarity index 61%
rename from core/src/main/java/org/springframework/ws/transport/http/HttpTransportResponse.java
rename to core/src/main/java/org/springframework/ws/transport/http/HttpServletTransportOutputStream.java
index 64ce7f99..99c32588 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/HttpTransportResponse.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/HttpServletTransportOutputStream.java
@@ -20,38 +20,39 @@ import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
-import org.springframework.ws.transport.TransportResponse;
+import org.springframework.ws.transport.TransportOutputStream;
/**
- * HTTP-specific implementation of the TransportResponse interface. Exposes the
- * HttpServletResponse
+ * HTTP Servlet specific implementation of the TransportOutputStream interface. Exposes the
+ * HttpServletResponse.
*
* @author Arjen Poutsma
+ * @see #getHttpServletResponse()
*/
-public class HttpTransportResponse implements TransportResponse {
+public class HttpServletTransportOutputStream extends TransportOutputStream {
- private final HttpServletResponse response;
+ private final HttpServletResponse httpServletResponse;
/**
* Constructs a new instance of the HttpTransportResponse with the given
* HttpServletResponse.
*/
- public HttpTransportResponse(HttpServletResponse response) {
- this.response = response;
+ public HttpServletTransportOutputStream(HttpServletResponse httpServletResponse) throws IOException {
+ this.httpServletResponse = httpServletResponse;
+ }
+
+ protected OutputStream getOutputStream() throws IOException {
+ return httpServletResponse.getOutputStream();
}
/**
* Returns the wrapped HttpServletResponse.
*/
public HttpServletResponse getHttpServletResponse() {
- return response;
+ return httpServletResponse;
}
public void addHeader(String name, String value) {
- response.addHeader(name, value);
- }
-
- public OutputStream getOutputStream() throws IOException {
- return response.getOutputStream();
+ httpServletResponse.addHeader(name, value);
}
}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpTransportContext.java b/core/src/main/java/org/springframework/ws/transport/http/HttpTransportContext.java
deleted file mode 100644
index c6f5a250..00000000
--- a/core/src/main/java/org/springframework/ws/transport/http/HttpTransportContext.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.springframework.ws.transport.http;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.util.Assert;
-import org.springframework.ws.transport.TransportContext;
-import org.springframework.ws.transport.TransportRequest;
-import org.springframework.ws.transport.TransportResponse;
-
-/**
- * HTTP-specific implementation of the TransportContext interface. Exposes the
- * HttpServletRequest and HttpServletResponse.
- *
- * @author Arjen Poutsma
- */
-public class HttpTransportContext implements TransportContext {
-
- private final HttpTransportRequest transportRequest;
-
- private final HttpTransportResponse transportResponse;
-
- /**
- * Constructs a new instance of the HttpTransportContext with the given HttpServletRequest
- * and HttpServletResponse
- */
- public HttpTransportContext(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
- Assert.notNull(httpServletRequest, "No httpServletRequest given");
- Assert.notNull(httpServletResponse, "No httpServletResponse given");
- transportRequest = new HttpTransportRequest(httpServletRequest);
- transportResponse = new HttpTransportResponse(httpServletResponse);
- }
-
- public TransportRequest getTransportRequest() {
- return transportRequest;
- }
-
- public TransportResponse getTransportResponse() {
- return transportResponse;
- }
-
- /**
- * Returns the wrapped HttpServletRequest.
- */
- public HttpServletRequest getHttpServletRequest() {
- return transportRequest.getHttpServletRequest();
- }
-
- /**
- * Returns the wrapped HttpServletResponse.
- */
- public HttpServletResponse getHttpServletRespo() {
- return transportResponse.getHttpServletResponse();
- }
-
-}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpTransportRequest.java b/core/src/main/java/org/springframework/ws/transport/http/HttpTransportRequest.java
deleted file mode 100644
index 21de9eb9..00000000
--- a/core/src/main/java/org/springframework/ws/transport/http/HttpTransportRequest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2006 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.transport.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Iterator;
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.util.Assert;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * HTTP-specific implementation of the TransportRequest interface. Exposes the
- * HttpServletRequest
- *
- * @author Arjen Poutsma
- */
-public class HttpTransportRequest implements TransportRequest {
-
- private final HttpServletRequest request;
-
- /**
- * Constructs a new instance of the HttpTransportRequest with the given
- * HttpServletRequest.
- */
- public HttpTransportRequest(HttpServletRequest request) {
- Assert.notNull(request, "request is required");
- this.request = request;
- }
-
- /**
- * Returns the wrapped HttpServletRequest.
- */
- public HttpServletRequest getHttpServletRequest() {
- return request;
- }
-
- public Iterator getHeaders(String name) {
- return new EnumerationIterator(request.getHeaders(name));
- }
-
- public InputStream getInputStream() throws IOException {
- return request.getInputStream();
- }
-
- public Iterator getHeaderNames() {
- return new EnumerationIterator(request.getHeaderNames());
- }
-
- public String getUrl() {
- StringBuffer url = new StringBuffer(request.getScheme());
- url.append("://").append(request.getServerName()).append(':').append(request.getServerPort());
- url.append(request.getRequestURI());
- return url.toString();
- }
-
- /**
- * Private static class that adapts a header enumeration provided by the HttpServletRequest and provides it as an
- * iterator.
- */
- private static class EnumerationIterator implements Iterator {
-
- private final Enumeration enumeration;
-
- public EnumerationIterator(Enumeration enumeration) {
- this.enumeration = enumeration;
- }
-
- public boolean hasNext() {
- return enumeration.hasMoreElements();
- }
-
- public Object next() {
- return enumeration.nextElement();
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java b/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java
index 52e3b106..f87b61dc 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java
@@ -26,7 +26,7 @@ import org.springframework.ws.EndpointAdapter;
import org.springframework.ws.EndpointExceptionResolver;
import org.springframework.ws.EndpointMapping;
import org.springframework.ws.MessageDispatcher;
-import org.springframework.ws.context.MessageContextFactory;
+import org.springframework.ws.WebServiceMessageFactory;
/**
* Servlet for simplified dispatching of Web service messages. Delegates to a MessageDispatcher and a
@@ -75,9 +75,9 @@ public class MessageDispatcherServlet extends FrameworkServlet {
public static final String ENDPOINT_MAPPING_BEAN_NAME = "endpointMapping";
/**
- * Well-known name for the MessageContextFactory object in the bean factory for this namespace.
+ * Well-known name for the WebServiceMessageFactory object in the bean factory for this namespace.
*/
- public static final String MESSAGE_CONTEXT_FACTORY_BEAN_NAME = "messageContextFactory";
+ public static final String WEB_SERVICE_MESSAGE_FACTORY_BEAN_NAME = "messageFactory";
/**
* Well-known name for the MessageDispatcher object in the bean factory for this namespace.
@@ -187,7 +187,7 @@ public class MessageDispatcherServlet extends FrameworkServlet {
}
protected void initFrameworkServlet() throws ServletException, BeansException {
- initMessageContextFactory();
+ initWebServiceMessageFactory();
initMessageDispatcher();
}
@@ -343,29 +343,29 @@ public class MessageDispatcherServlet extends FrameworkServlet {
}
}
- private void initMessageContextFactory() throws BeansException {
- MessageContextFactory messageContextFactory;
+ private void initWebServiceMessageFactory() throws BeansException {
+ WebServiceMessageFactory messageFactory;
try {
- messageContextFactory = (MessageContextFactory) getWebApplicationContext()
- .getBean(MESSAGE_CONTEXT_FACTORY_BEAN_NAME, MessageContextFactory.class);
+ messageFactory = (WebServiceMessageFactory) getWebApplicationContext()
+ .getBean(WEB_SERVICE_MESSAGE_FACTORY_BEAN_NAME, WebServiceMessageFactory.class);
}
catch (NoSuchBeanDefinitionException ignored) {
- messageContextFactory = (MessageContextFactory) getDefaultStrategy(MessageContextFactory.class);
+ messageFactory = (WebServiceMessageFactory) getDefaultStrategy(WebServiceMessageFactory.class);
if (logger.isInfoEnabled()) {
- logger.info("Unable to locate MessageContextFactory with name '" + MESSAGE_CONTEXT_FACTORY_BEAN_NAME +
- "': using default [" + messageContextFactory + "]");
+ logger.info("Unable to locate WebServiceMessageFactory with name '" +
+ WEB_SERVICE_MESSAGE_FACTORY_BEAN_NAME + "': using default [" + messageFactory + "]");
}
- if (messageContextFactory instanceof InitializingBean) {
+ if (messageFactory instanceof InitializingBean) {
try {
- ((InitializingBean) messageContextFactory).afterPropertiesSet();
+ ((InitializingBean) messageFactory).afterPropertiesSet();
}
catch (Exception ex) {
- throw new BeanInitializationException(
- "Could not invoke afterPropertiesSet() on messageContextFactory", ex);
+ throw new BeanInitializationException("Could not invoke afterPropertiesSet() on message factory",
+ ex);
}
}
}
- handlerAdapter.setMessageContextFactory(messageContextFactory);
+ handlerAdapter.setMessageFactory(messageFactory);
}
private void initMessageDispatcher() {
diff --git a/core/src/main/java/org/springframework/ws/transport/http/MessageEndpointHandlerAdapter.java b/core/src/main/java/org/springframework/ws/transport/http/MessageEndpointHandlerAdapter.java
index 8fe08703..8bd23090 100644
--- a/core/src/main/java/org/springframework/ws/transport/http/MessageEndpointHandlerAdapter.java
+++ b/core/src/main/java/org/springframework/ws/transport/http/MessageEndpointHandlerAdapter.java
@@ -28,33 +28,38 @@ import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.ws.NoEndpointFoundException;
import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.context.MessageContextFactory;
import org.springframework.ws.endpoint.MessageEndpoint;
import org.springframework.ws.soap.SoapMessage;
+import org.springframework.ws.transport.SimpleTransportContext;
+import org.springframework.ws.transport.TransportContext;
+import org.springframework.ws.transport.TransportContextHolder;
+import org.springframework.ws.transport.TransportInputStream;
+import org.springframework.ws.transport.TransportOutputStream;
/**
* Adapter to use the MessageEndpoint interface with the generic DispatcherServlet. Requires a
- * MessageContextFactory, which is used to convert the incoming HttpServletRequest into a
- * MessageContext, and passes that context to the mapped MessageEndpoint. If a response is
- * created, that is sent via the HttpServletResponse.
+ * {@link WebServiceMessageFactory}, which is used to convert the incoming HttpServletRequest into a {@link
+ * WebServiceMessage}, and passes that context to the mapped MessageEndpoint. If a response is created,
+ * that is sent via the HttpServletResponse.
*
* Note that the MessageDispatcher implements the MessageEndpoint interface, enabling this
* adapter to function as a gateway to further message handling logic.
*
* @author Arjen Poutsma
* @see org.springframework.ws.endpoint.MessageEndpoint
- * @see MessageContextFactory
* @see org.springframework.ws.MessageDispatcher
*/
public class MessageEndpointHandlerAdapter implements HandlerAdapter, InitializingBean {
private static final Log logger = LogFactory.getLog(MessageEndpointHandlerAdapter.class);
- private MessageContextFactory messageContextFactory;
+ private WebServiceMessageFactory messageFactory;
- public void setMessageContextFactory(MessageContextFactory messageContextFactory) {
- this.messageContextFactory = messageContextFactory;
+ public void setMessageFactory(WebServiceMessageFactory messageFactory) {
+ this.messageFactory = messageFactory;
}
public long getLastModified(HttpServletRequest request, Object handler) {
@@ -78,34 +83,43 @@ public class MessageEndpointHandlerAdapter implements HandlerAdapter, Initializi
}
public final void afterPropertiesSet() throws Exception {
- Assert.notNull(messageContextFactory, "messageContextFactory is required");
- logger.info("Using message context factory " + messageContextFactory);
+ Assert.notNull(messageFactory, "messageFactory is required");
+ logger.info("Using message factory [" + messageFactory + "]");
}
private void handlePost(HttpServletRequest httpServletRequest,
MessageEndpoint endpoint,
HttpServletResponse httpServletResponse) throws Exception {
- HttpTransportContext transportContext = new HttpTransportContext(httpServletRequest, httpServletResponse);
- MessageContext messageContext = messageContextFactory.createContext(transportContext);
+ TransportInputStream tis = new HttpServletTransportInputStream(httpServletRequest);
+ TransportOutputStream tos = new HttpServletTransportOutputStream(httpServletResponse);
+
+ TransportContext previousTransportContext = TransportContextHolder.getTransportContext();
+ TransportContextHolder.setTransportContext(new SimpleTransportContext(tis, tos));
+
try {
+ WebServiceMessage messageRequest = messageFactory.createWebServiceMessage(tis);
+ MessageContext messageContext = new DefaultMessageContext(messageRequest, messageFactory);
endpoint.invoke(messageContext);
if (!messageContext.hasResponse()) {
httpServletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
else {
- WebServiceMessage webServiceResponse = messageContext.getResponse();
- if (webServiceResponse instanceof SoapMessage &&
- ((SoapMessage) webServiceResponse).getSoapBody().hasFault()) {
+ WebServiceMessage messageResponse = messageContext.getResponse();
+ if (messageResponse instanceof SoapMessage &&
+ ((SoapMessage) messageResponse).getSoapBody().hasFault()) {
httpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
else {
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
}
- messageContext.sendResponse(new HttpTransportResponse(httpServletResponse));
+ messageResponse.writeTo(tos);
}
}
catch (NoEndpointFoundException ex) {
httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
+ finally {
+ TransportContextHolder.setTransportContext(previousTransportContext);
+ }
}
}
diff --git a/core/src/main/resources/org/springframework/ws/transport/http/MessageDispatcherServlet.properties b/core/src/main/resources/org/springframework/ws/transport/http/MessageDispatcherServlet.properties
index e418729f..a27f274a 100644
--- a/core/src/main/resources/org/springframework/ws/transport/http/MessageDispatcherServlet.properties
+++ b/core/src/main/resources/org/springframework/ws/transport/http/MessageDispatcherServlet.properties
@@ -4,4 +4,4 @@
org.springframework.ws.MessageDispatcher=org.springframework.ws.soap.SoapMessageDispatcher
-org.springframework.ws.context.MessageContextFactory=org.springframework.ws.soap.saaj.SaajSoapMessageContextFactory
\ No newline at end of file
+org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
\ No newline at end of file
diff --git a/core/src/test/java/org/springframework/ws/AbstractWebServiceMessageFactoryTestCase.java b/core/src/test/java/org/springframework/ws/AbstractWebServiceMessageFactoryTestCase.java
new file mode 100644
index 00000000..aa055d46
--- /dev/null
+++ b/core/src/test/java/org/springframework/ws/AbstractWebServiceMessageFactoryTestCase.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 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;
+
+import junit.framework.TestCase;
+
+public abstract class AbstractWebServiceMessageFactoryTestCase extends TestCase {
+
+ protected WebServiceMessageFactory messageFactory;
+
+ protected final void setUp() throws Exception {
+ messageFactory = createMessageFactory();
+ }
+
+ public void testCreateEmptyMessage() throws Exception {
+ WebServiceMessage message = messageFactory.createWebServiceMessage();
+ assertNotNull("WebServiceMessage is null", message);
+ }
+
+ protected abstract WebServiceMessageFactory createMessageFactory() throws Exception;
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/springframework/ws/MessageDispatcherTest.java b/core/src/test/java/org/springframework/ws/MessageDispatcherTest.java
index ca8f4a33..18f377b3 100644
--- a/core/src/test/java/org/springframework/ws/MessageDispatcherTest.java
+++ b/core/src/test/java/org/springframework/ws/MessageDispatcherTest.java
@@ -20,18 +20,24 @@ import java.util.Collections;
import junit.framework.TestCase;
import org.easymock.MockControl;
+import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.mock.MockMessageContext;
public class MessageDispatcherTest extends TestCase {
private MessageDispatcher dispatcher;
- private MockMessageContext messageContext;
+ private MessageContext messageContext;
+
+ private MockControl factoryControl;
+
+ private WebServiceMessageFactory factoryMock;
protected void setUp() throws Exception {
dispatcher = new MessageDispatcher();
- messageContext = new MockMessageContext();
+ factoryControl = MockControl.createControl(WebServiceMessageFactory.class);
+ factoryMock = (WebServiceMessageFactory) factoryControl.getMock();
+ messageContext = new DefaultMessageContext(new MockWebServiceMessage(), factoryMock);
}
public void testGetEndpoint() throws Exception {
@@ -44,8 +50,10 @@ public class MessageDispatcherTest extends TestCase {
mappingControl.expectAndReturn(mappingMock.getEndpoint(messageContext), chain);
mappingControl.replay();
+ factoryControl.replay();
EndpointInvocationChain result = dispatcher.getEndpoint(messageContext);
mappingControl.verify();
+ factoryControl.verify();
assertEquals("getEndpoint returns invalid EndpointInvocationChain", chain, result);
}
@@ -57,8 +65,10 @@ public class MessageDispatcherTest extends TestCase {
Object endpoint = new Object();
adapterControl.expectAndReturn(adapterMock.supports(endpoint), true);
adapterControl.replay();
+ factoryControl.replay();
EndpointAdapter result = dispatcher.getEndpointAdapter(endpoint);
adapterControl.verify();
+ factoryControl.verify();
assertEquals("getEnpointAdapter returns invalid EndpointAdapter", adapterMock, result);
}
@@ -70,6 +80,7 @@ public class MessageDispatcherTest extends TestCase {
Object endpoint = new Object();
adapterControl.expectAndReturn(adapterMock.supports(endpoint), false);
adapterControl.replay();
+ factoryControl.replay();
try {
dispatcher.getEndpointAdapter(endpoint);
fail("getEndpointAdapter does not throw IllegalStateException for unsupported endpoint");
@@ -78,6 +89,7 @@ public class MessageDispatcherTest extends TestCase {
// Expected
}
adapterControl.verify();
+ factoryControl.verify();
}
public void testProcessEndpointExceptionReturnsResponse() throws Exception {
@@ -98,9 +110,12 @@ public class MessageDispatcherTest extends TestCase {
};
dispatcher.setEndpointExceptionResolvers(Collections.singletonList(resolver));
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), new MockWebServiceMessage());
+ factoryControl.replay();
dispatcher.processEndpointException(messageContext, endpoint, ex);
assertNotNull("processEndpointException sets no response", messageContext.getResponse());
+ factoryControl.verify();
}
public void testProcessUnsupportedEndpointException() throws Exception {
@@ -149,10 +164,12 @@ public class MessageDispatcherTest extends TestCase {
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
mappingControl.expectAndReturn(mappingMock.getEndpoint(messageContext), chain);
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), new MockWebServiceMessage());
mappingControl.replay();
interceptorControl.replay();
adapterControl.replay();
+ factoryControl.replay();
// response required for interceptor invocation
messageContext.getResponse();
dispatcher.dispatch(messageContext);
@@ -160,6 +177,7 @@ public class MessageDispatcherTest extends TestCase {
mappingControl.verify();
interceptorControl.verify();
adapterControl.verify();
+ factoryControl.verify();
}
public void testFlowNoResponse() throws Exception {
@@ -189,12 +207,14 @@ public class MessageDispatcherTest extends TestCase {
mappingControl.replay();
interceptorControl.replay();
adapterControl.replay();
+ factoryControl.replay();
dispatcher.dispatch(messageContext);
mappingControl.verify();
interceptorControl.verify();
adapterControl.verify();
+ factoryControl.verify();
}
public void testInterceptedRequestFlow() throws Exception {
@@ -218,10 +238,12 @@ public class MessageDispatcherTest extends TestCase {
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
mappingControl.expectAndReturn(mappingMock.getEndpoint(messageContext), chain);
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), new MockWebServiceMessage());
mappingControl.replay();
interceptorControl.replay();
adapterControl.replay();
+ factoryControl.replay();
// response required for interceptor invocation
messageContext.getResponse();
@@ -231,6 +253,7 @@ public class MessageDispatcherTest extends TestCase {
mappingControl.verify();
interceptorControl.verify();
adapterControl.verify();
+ factoryControl.verify();
}
public void testInterceptedResponseFlow() throws Exception {
@@ -255,10 +278,12 @@ public class MessageDispatcherTest extends TestCase {
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
mappingControl.expectAndReturn(mappingMock.getEndpoint(messageContext), chain);
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), new MockWebServiceMessage());
mappingControl.replay();
interceptorControl.replay();
adapterControl.replay();
+ factoryControl.replay();
// response required for interceptor invocation
messageContext.getResponse();
@@ -267,6 +292,7 @@ public class MessageDispatcherTest extends TestCase {
mappingControl.verify();
interceptorControl.verify();
adapterControl.verify();
+ factoryControl.verify();
}
}
\ No newline at end of file
diff --git a/core/src/test/java/org/springframework/ws/mock/MockWebServiceMessage.java b/core/src/test/java/org/springframework/ws/MockWebServiceMessage.java
similarity index 98%
rename from core/src/test/java/org/springframework/ws/mock/MockWebServiceMessage.java
rename to core/src/test/java/org/springframework/ws/MockWebServiceMessage.java
index 8210aec7..8a54775c 100644
--- a/core/src/test/java/org/springframework/ws/mock/MockWebServiceMessage.java
+++ b/core/src/test/java/org/springframework/ws/MockWebServiceMessage.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.ws.mock;
+package org.springframework.ws;
import java.io.IOException;
import java.io.InputStream;
@@ -34,7 +34,6 @@ import javax.xml.transform.stream.StreamResult;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.util.FileCopyUtils;
-import org.springframework.ws.WebServiceMessage;
import org.springframework.xml.sax.SaxUtils;
import org.springframework.xml.transform.StringSource;
diff --git a/core/src/test/java/org/springframework/ws/MockWebServiceMessageFactory.java b/core/src/test/java/org/springframework/ws/MockWebServiceMessageFactory.java
new file mode 100644
index 00000000..9124d5a9
--- /dev/null
+++ b/core/src/test/java/org/springframework/ws/MockWebServiceMessageFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.stream.StreamSource;
+
+public class MockWebServiceMessageFactory implements WebServiceMessageFactory {
+
+ public WebServiceMessage createWebServiceMessage() {
+ return new MockWebServiceMessage();
+ }
+
+ public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
+ try {
+ return new MockWebServiceMessage(new StreamSource(inputStream));
+ }
+ catch (TransformerException ex) {
+ throw new IOException(ex.getMessage());
+ }
+ }
+}
diff --git a/core/src/test/java/org/springframework/ws/context/DefaultMessageContextTest.java b/core/src/test/java/org/springframework/ws/context/DefaultMessageContextTest.java
new file mode 100644
index 00000000..61b820c1
--- /dev/null
+++ b/core/src/test/java/org/springframework/ws/context/DefaultMessageContextTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006 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.context;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.ws.MockWebServiceMessage;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+
+public class DefaultMessageContextTest extends TestCase {
+
+ private DefaultMessageContext context;
+
+ private MockControl factoryControl;
+
+ private WebServiceMessageFactory factoryMock;
+
+ private WebServiceMessage request;
+
+ protected void setUp() throws Exception {
+ factoryControl = MockControl.createControl(WebServiceMessageFactory.class);
+ factoryMock = (WebServiceMessageFactory) factoryControl.getMock();
+ request = new MockWebServiceMessage();
+ context = new DefaultMessageContext(request, factoryMock);
+ }
+
+ public void testRequest() throws Exception {
+ assertEquals("Invalid request returned", request, context.getRequest());
+ }
+
+ public void testResponse() throws Exception {
+ WebServiceMessage response = new MockWebServiceMessage();
+ factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), response);
+ factoryControl.replay();
+
+ WebServiceMessage result = context.getResponse();
+ assertEquals("Invalid response returned", response, result);
+ factoryControl.verify();
+ }
+
+ public void testProperties() throws Exception {
+ assertEquals("Invalid property names returned", 0, context.getPropertyNames().length);
+ String name = "name";
+ assertFalse("Property set", context.containsProperty(name));
+ String value = "value";
+ context.setProperty(name, value);
+ assertTrue("Property not set", context.containsProperty(name));
+ assertEquals("Invalid property names returned", Arrays.asList(new String[]{name}),
+ Arrays.asList(context.getPropertyNames()));
+ assertEquals("Invalid property value returned", value, context.getProperty(name));
+ context.removeProperty(name);
+ assertFalse("Property set", context.containsProperty(name));
+ assertEquals("Invalid property names returned", 0, context.getPropertyNames().length);
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/springframework/ws/endpoint/AbstractMessageEndpointTestCase.java b/core/src/test/java/org/springframework/ws/endpoint/AbstractMessageEndpointTestCase.java
index f3b9c619..8405b198 100644
--- a/core/src/test/java/org/springframework/ws/endpoint/AbstractMessageEndpointTestCase.java
+++ b/core/src/test/java/org/springframework/ws/endpoint/AbstractMessageEndpointTestCase.java
@@ -18,8 +18,10 @@ package org.springframework.ws.endpoint;
import javax.xml.transform.Source;
-import org.springframework.ws.mock.MockMessageContext;
-import org.springframework.ws.mock.MockWebServiceMessage;
+import org.springframework.ws.MockWebServiceMessage;
+import org.springframework.ws.MockWebServiceMessageFactory;
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
import org.springframework.xml.transform.StringSource;
public abstract class AbstractMessageEndpointTestCase extends AbstractEndpointTestCase {
@@ -33,13 +35,16 @@ public abstract class AbstractMessageEndpointTestCase extends AbstractEndpointTe
public void testNoResponse() throws Exception {
endpoint = createNoResponseEndpoint();
StringSource requestSource = new StringSource(REQUEST);
- MockMessageContext context = new MockMessageContext(new MockWebServiceMessage(requestSource));
+
+ MessageContext context =
+ new DefaultMessageContext(new MockWebServiceMessage(requestSource), new MockWebServiceMessageFactory());
endpoint.invoke(context);
assertFalse("Response message created", context.hasResponse());
}
protected final void testSource(Source requestSource) throws Exception {
- MockMessageContext context = new MockMessageContext(new MockWebServiceMessage(requestSource));
+ MessageContext context =
+ new DefaultMessageContext(new MockWebServiceMessage(requestSource), new MockWebServiceMessageFactory());
endpoint.invoke(context);
assertTrue("No response message created", context.hasResponse());
assertXMLEqual(RESPONSE, ((MockWebServiceMessage) context.getResponse()).getPayloadAsString());
diff --git a/core/src/test/java/org/springframework/ws/endpoint/MarshallingPayloadEndpointTest.java b/core/src/test/java/org/springframework/ws/endpoint/MarshallingPayloadEndpointTest.java
index 188f9811..e4c7e3fb 100644
--- a/core/src/test/java/org/springframework/ws/endpoint/MarshallingPayloadEndpointTest.java
+++ b/core/src/test/java/org/springframework/ws/endpoint/MarshallingPayloadEndpointTest.java
@@ -18,7 +18,6 @@ package org.springframework.ws.endpoint;
import java.io.StringReader;
import java.io.StringWriter;
-
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
@@ -28,19 +27,36 @@ import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.custommonkey.xmlunit.XMLTestCase;
-
+import org.easymock.MockControl;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.XmlMappingException;
-import org.springframework.ws.mock.MockMessageContext;
-import org.springframework.ws.mock.MockWebServiceMessage;
+import org.springframework.ws.MockWebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
public class MarshallingPayloadEndpointTest extends XMLTestCase {
- public void testInvoke() throws Exception {
- MockWebServiceMessage request = new MockWebServiceMessage("MessageContext interface.
- *
- * @author Arjen Poutsma
- */
-public class MockMessageContext extends AbstractMessageContext {
-
- private TransportResponse transportResponse;
-
- public MockMessageContext() {
- super(new MockWebServiceMessage(), new MockTransportRequest());
- }
-
- public MockMessageContext(MockWebServiceMessage request) {
- super(request, new MockTransportRequest());
- }
-
- public MockMessageContext(MockWebServiceMessage request, TransportContext transportContext) {
- super(request, transportContext.getTransportRequest());
- transportResponse = transportContext.getTransportResponse();
- }
-
- public MockMessageContext(String content) {
- super(new MockWebServiceMessage(content), new MockTransportRequest());
- }
-
- protected WebServiceMessage createResponseMessage() {
- return new MockWebServiceMessage();
- }
-
- public void sendResponse(TransportResponse transportResponse) throws IOException {
- getResponse().writeTo(this.transportResponse.getOutputStream());
- }
-}
diff --git a/core/src/test/java/org/springframework/ws/mock/MockTransportContext.java b/core/src/test/java/org/springframework/ws/mock/MockTransportContext.java
deleted file mode 100644
index d4aca745..00000000
--- a/core/src/test/java/org/springframework/ws/mock/MockTransportContext.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2006 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.mock;
-
-import org.springframework.ws.transport.TransportContext;
-import org.springframework.ws.transport.TransportRequest;
-import org.springframework.ws.transport.TransportResponse;
-
-/**
- * Mock implementation of the TransportContext interface.
- *
- * @author Arjen Poutsma
- */
-public class MockTransportContext implements TransportContext {
-
- private MockTransportRequest request;
-
- private MockTransportResponse response;
-
- public MockTransportContext() {
- request = new MockTransportRequest();
- response = new MockTransportResponse();
- }
-
- public MockTransportContext(MockTransportRequest request) {
- this.request = request;
- }
-
- public MockTransportContext(MockTransportRequest request, MockTransportResponse response) {
- this.request = request;
- this.response = response;
- }
-
- public TransportRequest getTransportRequest() {
- return request;
- }
-
- public TransportResponse getTransportResponse() {
- return response;
- }
-}
diff --git a/core/src/test/java/org/springframework/ws/mock/MockTransportRequest.java b/core/src/test/java/org/springframework/ws/mock/MockTransportRequest.java
deleted file mode 100644
index 85d897f5..00000000
--- a/core/src/test/java/org/springframework/ws/mock/MockTransportRequest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2006 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.mock;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Properties;
-
-import org.springframework.util.Assert;
-import org.springframework.ws.transport.TransportRequest;
-
-/**
- * Mock implementation of the TransportRequest interface.
- *
- * @author Arjen Poutsma
- */
-public class MockTransportRequest implements TransportRequest {
-
- private byte[] contents;
-
- private Properties headers;
-
- private String url;
-
- public MockTransportRequest() {
- headers = new Properties();
- contents = new byte[0];
- }
-
- public MockTransportRequest(Properties headers, byte[] contents) {
- Assert.notNull(headers, "headers must not be null");
- Assert.notNull(contents, "contents must not be null");
- this.headers = headers;
- this.contents = contents;
- }
-
- public MockTransportRequest(byte[] contents) {
- Assert.notNull(contents, "contents must not be null");
- this.contents = contents;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public String getUrl() {
- return url;
- }
-
- public InputStream getInputStream() throws IOException {
- return new ByteArrayInputStream(contents);
- }
-
- public Iterator getHeaderNames() {
- return headers.keySet().iterator();
- }
-
- public Iterator getHeaders(String name) {
- String value = headers.getProperty(name);
- return value != null ? Collections.singletonList(value).iterator() : Collections.EMPTY_LIST.iterator();
- }
-
- public void addHeader(String name, String value) {
- headers.setProperty(name, value);
- }
-}
diff --git a/core/src/test/java/org/springframework/ws/mock/MockTransportResponse.java b/core/src/test/java/org/springframework/ws/mock/MockTransportResponse.java
deleted file mode 100644
index e6a4771d..00000000
--- a/core/src/test/java/org/springframework/ws/mock/MockTransportResponse.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2006 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.mock;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Properties;
-
-import org.springframework.ws.transport.TransportResponse;
-
-/**
- * Mock implementation of the TransportResponse interface.
- *
- * @author Arjen Poutsma
- */
-public class MockTransportResponse implements TransportResponse {
-
- private Properties headers = new Properties();
-
- private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-
- public void addHeader(String name, String value) {
- String currentValue = headers.getProperty(name);
- if (currentValue != null) {
- value = currentValue + "," + value;
- }
- headers.setProperty(name, value);
- }
-
- public Properties getHeaders() {
- return headers;
- }
-
- public String getContents() {
- try {
- return new String(outputStream.toByteArray(), "UTF-8");
- }
- catch (UnsupportedEncodingException e) {
- return "";
- }
- }
-
- public OutputStream getOutputStream() throws IOException {
- return outputStream;
- }
-}
diff --git a/core/src/test/java/org/springframework/ws/pox/dom/DomPoxMessageContextFactoryTest.java b/core/src/test/java/org/springframework/ws/pox/dom/DomPoxMessageContextFactoryTest.java
deleted file mode 100644
index b308d52b..00000000
--- a/core/src/test/java/org/springframework/ws/pox/dom/DomPoxMessageContextFactoryTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2006 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.pox.dom;
-
-import junit.framework.TestCase;
-import org.springframework.ws.mock.MockTransportContext;
-import org.springframework.ws.mock.MockTransportRequest;
-
-public class DomPoxMessageContextFactoryTest extends TestCase {
-
- private DomPoxMessageContextFactory contextFactory;
-
- protected void setUp() throws Exception {
- contextFactory = new DomPoxMessageContextFactory();
- contextFactory.afterPropertiesSet();
- }
-
- public void testCreateContext() throws Exception {
- String content = "WebServiceTemplate and other WS-accessing helpers.
+ *
+ * @author Arjen Poutsma
+ */
+public abstract class WebServiceAccessor extends TransformerObjectSupport implements InitializingBean {
+
+ private WebServiceMessageFactory messageFactory;
+
+ private WebServiceMessageSender messageSender;
+
+ /**
+ * Returns the message factory used for creating messages.
+ */
+ public WebServiceMessageFactory getMessageFactory() {
+ return messageFactory;
+ }
+
+ /**
+ * Sets the message factory used for creating messages.
+ */
+ public void setMessageFactory(WebServiceMessageFactory messageFactory) {
+ this.messageFactory = messageFactory;
+ }
+
+ /**
+ * Returns the message sender.
+ */
+ public WebServiceMessageSender getMessageSender() {
+ return messageSender;
+ }
+
+ /**
+ * Sets the message sender.
+ */
+ public void setMessageSender(WebServiceMessageSender messageSender) {
+ this.messageSender = messageSender;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(getMessageFactory(), "messageFactory is required");
+ Assert.notNull(getMessageSender(), "messageSender is required");
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/client/WebServiceMessageCallback.java b/sandbox/src/main/java/org/springframework/ws/client/WebServiceMessageCallback.java
new file mode 100644
index 00000000..70e0147e
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/client/WebServiceMessageCallback.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2006 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.client;
+
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * @author Arjen Poutsma
+ */
+public interface WebServiceMessageCallback {
+
+ void doInWebServiceMessage(WebServiceMessage message) throws Exception;
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/client/WebServiceMessageExtractor.java b/sandbox/src/main/java/org/springframework/ws/client/WebServiceMessageExtractor.java
new file mode 100644
index 00000000..5fb3029b
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/client/WebServiceMessageExtractor.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 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.client;
+
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * @author Arjen Poutsma
+ */
+public interface WebServiceMessageExtractor {
+
+ /**
+ * Process the content in the given WebServiceMessage, creating a corresponding result object.
+ *
+ * @param message the message to extract data from
+ * @return an arbitrary result object, or null if none
+ */
+ Object extractData(WebServiceMessage message) throws Exception;
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/client/WebServiceOperations.java b/sandbox/src/main/java/org/springframework/ws/client/WebServiceOperations.java
new file mode 100644
index 00000000..a8c2a258
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/client/WebServiceOperations.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 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.client;
+
+import javax.xml.transform.Source;
+
+/**
+ * @author Arjen Poutsma
+ */
+public interface WebServiceOperations {
+
+ /**
+ * Sends a web service message that contains the given payload. Returns the payload of the response message, if
+ * any.
+ *
+ * @param payload the payload of the message.
+ * @return the payload of the response message, or null if no response is given
+ */
+ Source send(Source payload);
+
+ /**
+ * Sends a web service message that contains the given payload, marshalled by the configured
+ * Marshaller. Returns the unmarshalled payload of the response message, if any.
+ *
+ * @param payload the object to marshal into a message payload
+ * @return the unmarshalled payload of the response message, or null if no response is given
+ */
+ Object marshalAndSend(Object payload);
+
+ Object send(WebServiceMessageCallback callback, WebServiceMessageExtractor extractor);
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/client/WebServiceTemplate.java b/sandbox/src/main/java/org/springframework/ws/client/WebServiceTemplate.java
new file mode 100644
index 00000000..779c80f9
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/client/WebServiceTemplate.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2006 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.client;
+
+import java.io.IOException;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.util.Assert;
+import org.springframework.ws.WebServiceException;
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class WebServiceTemplate extends WebServiceAccessor implements WebServiceOperations {
+
+ private Marshaller marshaller;
+
+ private Unmarshaller unmarshaller;
+
+ /**
+ * Returns the marshaller for this template.
+ */
+ public Marshaller getMarshaller() {
+ return marshaller;
+ }
+
+ /**
+ * Sets the marshaller for this template.
+ */
+ public void setMarshaller(Marshaller marshaller) {
+ this.marshaller = marshaller;
+ }
+
+ /**
+ * Returns the unmarshaller for this template.
+ */
+ public Unmarshaller getUnmarshaller() {
+ return unmarshaller;
+ }
+
+ /**
+ * Sets the unmarshaller for this template.
+ */
+ public void setUnmarshaller(Unmarshaller unmarshaller) {
+ this.unmarshaller = unmarshaller;
+ }
+
+ public Object marshalAndSend(final Object payload) {
+ checkMarshallerAndUnmarshaller();
+ return send(new WebServiceMessageCallback() {
+ public void doInWebServiceMessage(WebServiceMessage message) throws IOException {
+ getMarshaller().marshal(payload, message.getPayloadResult());
+ }
+ }, new WebServiceMessageExtractor() {
+ public Object extractData(WebServiceMessage message) throws IOException {
+ return getUnmarshaller().unmarshal(message.getPayloadSource());
+ }
+ });
+ }
+
+ public Source send(final Source payload) {
+ return (Source) send(new WebServiceMessageCallback() {
+ public void doInWebServiceMessage(WebServiceMessage message) throws Exception {
+ Transformer transformer = createTransformer();
+ transformer.transform(payload, message.getPayloadResult());
+ }
+ }, new WebServiceMessageExtractor() {
+ public Object extractData(WebServiceMessage message) throws WebServiceException {
+ return message.getPayloadSource();
+ }
+ });
+ }
+
+ private void checkMarshallerAndUnmarshaller() throws IllegalStateException {
+ if (getMarshaller() == null) {
+ throw new IllegalStateException("No marshaller registered. Check configuration of WebServiceTemplate.");
+ }
+ if (getUnmarshaller() == null) {
+ throw new IllegalStateException("No unmarshaller registered. Check configuration of WebServiceTemplate.");
+ }
+ }
+
+ public WebServiceMessage send(WebServiceMessageCallback callback) {
+ return (WebServiceMessage) send(callback, new WebServiceMessageExtractor() {
+ public Object extractData(WebServiceMessage message) throws Exception {
+ return message;
+ }
+ });
+ }
+
+ public Object send(WebServiceMessageCallback callback, WebServiceMessageExtractor extractor) {
+ Assert.notNull(callback, "callback must not be null");
+ Assert.notNull(extractor, "extractor must not be null");
+ WebServiceMessage request = getMessageFactory().createWebServiceMessage();
+ try {
+ callback.doInWebServiceMessage(request);
+ WebServiceMessage response = getMessageSender().send(request);
+ if (response == null) {
+ return null;
+ }
+ else {
+ return extractor.extractData(response);
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ return null;
+ }
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java
new file mode 100644
index 00000000..fdc20081
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/WebServiceMessageSender.java
@@ -0,0 +1,18 @@
+package org.springframework.ws.transport;
+
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * @author Arjen Poutsma
+ */
+public interface WebServiceMessageSender {
+
+ /**
+ * Sends the given web service message and returns the result, if any.
+ *
+ * @param message the message to be sent
+ * @return the result, or null if none
+ */
+ WebServiceMessage send(WebServiceMessage message);
+
+}
diff --git a/core/src/main/java/org/springframework/ws/transport/TransportResponse.java b/sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java
similarity index 63%
rename from core/src/main/java/org/springframework/ws/transport/TransportResponse.java
rename to sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java
index 740ddce8..c1324b5b 100644
--- a/core/src/main/java/org/springframework/ws/transport/TransportResponse.java
+++ b/sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSender.java
@@ -14,21 +14,13 @@
* limitations under the License.
*/
-package org.springframework.ws.transport;
+package org.springframework.ws.transport.http;
-import java.io.IOException;
-import java.io.OutputStream;
+import org.springframework.ws.transport.WebServiceMessageSender;
/**
- * Defines the contract for Web service request that come in via a transport. Exposes headers and the inputstream to
- * read from.
- *
* @author Arjen Poutsma
*/
-public interface TransportResponse {
-
- void addHeader(String name, String value);
-
- OutputStream getOutputStream() throws IOException;
+public abstract class AbstractHttpWebServiceMessageSender implements WebServiceMessageSender {
}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportInputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportInputStream.java
new file mode 100644
index 00000000..78295e70
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportInputStream.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006 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.transport.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+import org.springframework.ws.transport.TransportInputStream;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class HttpUrlConnectionTransportInputStream extends TransportInputStream {
+
+ private final HttpURLConnection connection;
+
+ public HttpUrlConnectionTransportInputStream(HttpURLConnection connection) throws IOException {
+ Assert.notNull(connection, "connection must not be null");
+ this.connection = connection;
+ }
+
+ public Iterator getHeaderNames() throws IOException {
+ List headerNames = new ArrayList();
+ // Header field 0 is the status line, so we start at 1
+ int i = 1;
+ while (true) {
+ String headerName = connection.getHeaderField(i);
+ if (!StringUtils.hasLength(headerName)) {
+ break;
+ }
+ headerNames.add(headerName);
+ i++;
+ }
+ return headerNames.iterator();
+ }
+
+ public Iterator getHeaders(String name) throws IOException {
+ String headerField = connection.getHeaderField(name);
+ if (headerField == null) {
+ return Collections.EMPTY_LIST.iterator();
+ }
+ else {
+ Set tokens = StringUtils.commaDelimitedListToSet(headerField);
+ return tokens.iterator();
+ }
+ }
+
+ protected InputStream getInputStream() throws IOException {
+ return connection.getInputStream();
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportOutputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportOutputStream.java
new file mode 100644
index 00000000..aec2dfe0
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportOutputStream.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2006 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.transport.http;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+
+import org.springframework.util.Assert;
+import org.springframework.ws.transport.TransportOutputStream;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class HttpUrlConnectionTransportOutputStream extends TransportOutputStream {
+
+ private final HttpURLConnection connection;
+
+ public HttpUrlConnectionTransportOutputStream(HttpURLConnection connection) throws IOException {
+ Assert.notNull(connection, "connection must not be null");
+ this.connection = connection;
+ }
+
+ public void addHeader(String name, String value) throws IOException {
+ connection.setRequestProperty(name, value);
+ }
+
+ protected OutputStream getOutputStream() throws IOException {
+ return connection.getOutputStream();
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/SimpleHttpWebServiceMessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/http/SimpleHttpWebServiceMessageSender.java
new file mode 100644
index 00000000..76927219
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/http/SimpleHttpWebServiceMessageSender.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 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.transport.http;
+
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.transport.WebServiceMessageSender;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class SimpleHttpWebServiceMessageSender implements WebServiceMessageSender {
+
+ public final WebServiceMessage send(WebServiceMessage message) {
+ //TODO implement
+ throw new UnsupportedOperationException("Not implemented");
+ }
+}
diff --git a/core/src/test/java/org/springframework/ws/soap/saaj/SaajSoap11MessageContextFactoryTest.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportException.java
similarity index 55%
rename from core/src/test/java/org/springframework/ws/soap/saaj/SaajSoap11MessageContextFactoryTest.java
rename to sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportException.java
index ad954d37..2590d624 100644
--- a/core/src/test/java/org/springframework/ws/soap/saaj/SaajSoap11MessageContextFactoryTest.java
+++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 the original author or authors.
+ * Copyright 2006 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.
@@ -14,15 +14,20 @@
* limitations under the License.
*/
-package org.springframework.ws.soap.saaj;
+package org.springframework.ws.transport.jms;
-import org.springframework.ws.context.MessageContextFactory;
-import org.springframework.ws.soap.context.AbstractSoap11MessageContextFactoryTestCase;
+import org.springframework.ws.transport.TransportException;
-public class SaajSoap11MessageContextFactoryTest extends AbstractSoap11MessageContextFactoryTestCase {
+/**
+ * @author Arjen Poutsma
+ */
+public class JmsTransportException extends TransportException {
- protected MessageContextFactory createSoapMessageContextFactory() {
- return new SaajSoapMessageContextFactory();
+ public JmsTransportException(String string) {
+ super(string);
}
-}
\ No newline at end of file
+ public JmsTransportException(String string, Throwable throwable) {
+ super(string, throwable);
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportInputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportInputStream.java
new file mode 100644
index 00000000..a78ce260
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportInputStream.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 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.transport.jms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Iterator;
+import javax.jms.JMSException;
+import javax.jms.TextMessage;
+
+import org.springframework.util.Assert;
+import org.springframework.ws.transport.TransportInputStream;
+import org.springframework.ws.transport.support.EnumerationIterator;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class JmsTransportInputStream extends TransportInputStream {
+
+ private final TextMessage textMessage;
+
+ public JmsTransportInputStream(TextMessage textMessage) throws IOException {
+ Assert.notNull(textMessage, "textMessage must not be null");
+ this.textMessage = textMessage;
+ }
+
+ protected InputStream getInputStream() throws IOException {
+ try {
+ return new ByteArrayInputStream(textMessage.getText().getBytes("UTF-8"));
+ }
+ catch (JMSException ex) {
+ throw new IOException("Could not get text of message: " + ex.getMessage());
+ }
+ }
+
+ public Iterator getHeaderNames() throws IOException {
+ try {
+ return new EnumerationIterator(textMessage.getPropertyNames());
+ }
+ catch (JMSException ex) {
+ throw new IOException("Could not get property names: " + ex.getMessage());
+ }
+ }
+
+ public Iterator getHeaders(String name) throws IOException {
+ try {
+ String value = textMessage.getStringProperty(name);
+ return Collections.singletonList(value).iterator();
+ }
+ catch (JMSException ex) {
+ throw new IOException("Could not get property value: " + ex.getMessage());
+ }
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportMessageListener.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportMessageListener.java
new file mode 100644
index 00000000..345f5137
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportMessageListener.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2006 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.transport.jms;
+
+import java.io.IOException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.Assert;
+import org.springframework.ws.NoEndpointFoundException;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.WebServiceMessageFactory;
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.endpoint.MessageEndpoint;
+import org.springframework.ws.transport.SimpleTransportContext;
+import org.springframework.ws.transport.TransportContext;
+import org.springframework.ws.transport.TransportContextHolder;
+import org.springframework.ws.transport.TransportInputStream;
+import org.springframework.ws.transport.TransportOutputStream;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class JmsTransportMessageListener implements MessageListener, InitializingBean {
+
+ private static final Log logger = LogFactory.getLog(JmsTransportMessageListener.class);
+
+ private WebServiceMessageFactory messageFactory;
+
+ private MessageEndpoint endpoint;
+
+ public void setMessageFactory(WebServiceMessageFactory messageFactory) {
+ this.messageFactory = messageFactory;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(messageFactory, "messageFactory is required");
+ logger.info("Using message factory [" + messageFactory + "]");
+ }
+
+ public void onMessage(Message message) {
+ if (message instanceof TextMessage) {
+ TextMessage textMessage = (TextMessage) message;
+ try {
+ handleTextMessage(textMessage);
+ }
+ catch (IOException ex) {
+ throw new JmsTransportException("Could not create message: " + ex.getMessage(), ex);
+ }
+ catch (Exception ex) {
+ throw new JmsTransportException("Could not handle message: " + ex.getMessage(), ex);
+ }
+ }
+ else {
+ throw new JmsTransportException("JmsTransportMessageListener can only handle TextMessages");
+ }
+ }
+
+ private void handleTextMessage(TextMessage textMessage) throws Exception {
+ TransportInputStream tis = new JmsTransportInputStream(textMessage);
+ TransportOutputStream tos = new JmsTransportOutputStream(getSession());
+
+ TransportContext previousTransportContext = TransportContextHolder.getTransportContext();
+ TransportContextHolder.setTransportContext(new SimpleTransportContext(tis, tos));
+
+ try {
+ WebServiceMessage messageRequest = messageFactory.createWebServiceMessage(tis);
+ MessageContext messageContext = new DefaultMessageContext(messageRequest, messageFactory);
+ endpoint.invoke(messageContext);
+ if (messageContext.hasResponse()) {
+ WebServiceMessage messageResponse = messageContext.getResponse();
+ messageResponse.writeTo(tos);
+ }
+ }
+ catch (NoEndpointFoundException ex) {
+ // do nothing
+ }
+ finally {
+ TransportContextHolder.setTransportContext(previousTransportContext);
+ }
+
+ }
+
+ private Session getSession() {
+ //TODO implement
+ throw new UnsupportedOperationException("Not implemented");
+ }
+}
diff --git a/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportOutputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportOutputStream.java
new file mode 100644
index 00000000..b19464f8
--- /dev/null
+++ b/sandbox/src/main/java/org/springframework/ws/transport/jms/JmsTransportOutputStream.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2006 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.transport.jms;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.jms.JMSException;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.springframework.util.Assert;
+import org.springframework.ws.transport.TransportOutputStream;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class JmsTransportOutputStream extends TransportOutputStream {
+
+ private TextMessage textMessage;
+
+ private Session session;
+
+ public JmsTransportOutputStream(Session session) {
+ Assert.notNull(session, "session must not be null");
+ this.session = session;
+ }
+
+ private TextMessage getTextMessage() throws IOException {
+ if (textMessage == null) {
+ try {
+ textMessage = session.createTextMessage();
+ }
+ catch (JMSException ex) {
+ throw new IOException("Could not create text message: " + ex.getMessage());
+ }
+ }
+ return textMessage;
+ }
+
+ protected OutputStream getOutputStream() throws IOException {
+ return new TextMessageOutputStream(getTextMessage());
+ }
+
+ public void addHeader(String name, String value) throws IOException {
+ try {
+ getTextMessage().setStringProperty(name, value);
+ }
+ catch (JMSException ex) {
+ throw new IOException("Could not set property " + ex.getMessage());
+ }
+ }
+
+ private static class TextMessageOutputStream extends ByteArrayOutputStream {
+
+ private final TextMessage textMessage;
+
+ public TextMessageOutputStream(TextMessage textMessage) {
+ this.textMessage = textMessage;
+ }
+
+ public void close() throws IOException {
+ try {
+ textMessage.setText(new String(toString("UTF-8")));
+ }
+ catch (JMSException ex) {
+ throw new IOException("Could not set message text: " + ex.getMessage());
+ }
+ }
+ }
+}
diff --git a/sandbox/src/test/java/org/springframework/ws/client/WebServiceTemplateTest.java b/sandbox/src/test/java/org/springframework/ws/client/WebServiceTemplateTest.java
new file mode 100644
index 00000000..67edd555
--- /dev/null
+++ b/sandbox/src/test/java/org/springframework/ws/client/WebServiceTemplateTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 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.client;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+
+public class WebServiceTemplateTest extends TestCase {
+
+ private WebServiceTemplate template;
+
+ private MockControl marshallerControl;
+
+ private Marshaller marshallerMock;
+
+ private MockControl unmarshallerControl;
+
+ private Unmarshaller unmarshallerMock;
+
+ protected void setUp() throws Exception {
+ template = new WebServiceTemplate();
+ marshallerControl = MockControl.createControl(Marshaller.class);
+ marshallerMock = (Marshaller) marshallerControl.getMock();
+ template.setMarshaller(marshallerMock);
+ unmarshallerControl = MockControl.createControl(Unmarshaller.class);
+ unmarshallerMock = (Unmarshaller) unmarshallerControl.getMock();
+ template.setUnmarshaller(unmarshallerMock);
+ }
+
+ public void testMarshalAndSendNoMarshallerSet() throws Exception {
+ template.setMarshaller(null);
+ try {
+ template.marshalAndSend(new Object());
+ fail("IllegalStateException expected");
+ }
+ catch (IllegalStateException ex) {
+ // expected behavior
+ }
+ }
+
+ public void testMarshalAndSendNoUnmarshallerSet() throws Exception {
+ template.setUnmarshaller(null);
+ try {
+ template.marshalAndSend(new Object());
+ fail("IllegalStateException expected");
+ }
+ catch (IllegalStateException ex) {
+ // expected behavior
+ }
+ }
+}
\ No newline at end of file
diff --git a/sandbox/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderTestCase.java b/sandbox/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderTestCase.java
new file mode 100644
index 00000000..dbcbc71c
--- /dev/null
+++ b/sandbox/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderTestCase.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 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.transport.http;
+
+import java.io.IOException;
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+import org.springframework.util.FileCopyUtils;
+
+public abstract class AbstractHttpWebServiceMessageSenderTestCase extends TestCase {
+
+ protected Server jettyServer;
+
+ protected static final String HEADER_NAME = "SOAPAction";
+
+ protected static final String HEADER_VALUE = "http://springframework.org/spring-ws";
+
+ protected void setUp() throws Exception {
+ jettyServer = new Server(8888);
+ Context root = new Context(jettyServer, "/");
+ root.addServlet(new ServletHolder(new EchoServlet()), "/*");
+ jettyServer.start();
+ }
+
+ private static class EchoServlet extends GenericServlet {
+
+ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) req;
+ HttpServletResponse httpServletResponse = (HttpServletResponse) res;
+ assertEquals("Invalid header", HEADER_VALUE, httpServletRequest.getHeader(HEADER_NAME));
+ httpServletResponse.addHeader(HEADER_NAME, HEADER_VALUE);
+ FileCopyUtils.copy(req.getInputStream(), res.getOutputStream());
+ }
+ }
+}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java b/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java
index 92b73b63..12b71933 100644
--- a/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java
@@ -16,18 +16,12 @@
package org.springframework.ws.soap.security.xwss;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.Iterator;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import junit.framework.TestCase;
import org.springframework.ws.soap.saaj.SaajSoapMessageContext;
import org.springframework.ws.soap.saaj.saaj13.Saaj13SoapMessageContext;
-import org.springframework.ws.transport.TransportException;
-import org.springframework.ws.transport.TransportRequest;
public class XwsSecurityInterceptorTest extends TestCase {
@@ -52,8 +46,7 @@ public class XwsSecurityInterceptorTest extends TestCase {
}
};
- SaajSoapMessageContext context =
- new Saaj13SoapMessageContext(request, new DummyTransportRequest(), messageFactory);
+ SaajSoapMessageContext context = new Saaj13SoapMessageContext(request, messageFactory);
interceptor.handleRequest(context, null);
assertEquals("Invalid request", validatedRequest, context.getSaajRequest());
}
@@ -74,29 +67,10 @@ public class XwsSecurityInterceptorTest extends TestCase {
};
SOAPMessage request = messageFactory.createMessage();
- SaajSoapMessageContext context =
- new Saaj13SoapMessageContext(request, new DummyTransportRequest(), messageFactory);
+ SaajSoapMessageContext context = new Saaj13SoapMessageContext(request, messageFactory);
context.setSaajResponse(response);
interceptor.handleResponse(context, null);
assertEquals("Invalid response", securedResponse, context.getSaajResponse());
}
- private static class DummyTransportRequest implements TransportRequest {
-
- public Iterator getHeaderNames() {
- return Collections.EMPTY_LIST.iterator();
- }
-
- public Iterator getHeaders(String name) {
- return Collections.EMPTY_LIST.iterator();
- }
-
- public String getUrl() throws TransportException {
- return null;
- }
-
- public InputStream getInputStream() throws IOException {
- return null;
- }
- }
}
\ No newline at end of file