From 13e90ecd0db67c79e7b82661da926f9104ae18b4 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Sun, 19 Nov 2006 20:34:50 +0000 Subject: [PATCH] Added Commons Http client support. --- .../soap/axiom/AxiomSoapMessageFactory.java | 12 +- .../main/webapp/WEB-INF/spring-ws-servlet.xml | 19 +- sandbox/pom.xml | 16 +- .../ws/transport/MessageSender.java | 2 +- .../http/AbstractHttpMessageSender.java | 26 --- .../http/CommonsHttpMessageSender.java | 183 ++++++++++++++++++ .../http/CommonsHttpTransportInputStream.java | 77 ++++++++ .../CommonsHttpTransportOutputStream.java | 67 +++++++ .../http/HttpUrlConnectionMessageSender.java | 67 ++++--- ...HttpUrlConnectionTransportInputStream.java | 32 ++- ...ttpUrlConnectionTransportOutputStream.java | 14 ++ .../mail/MailTransportInputStream.java | 67 +++++++ .../mail/MailTransportOutputStream.java | 54 ++++++ ...ctHttpWebServiceMessageSenderTestCase.java | 4 + .../http/CommonsHttpMessageSenderTest.java | 52 +++++ .../HttpUrlConnectionMessageSenderTest.java | 11 +- sandbox/src/test/resources/log4j.properties | 6 + 17 files changed, 625 insertions(+), 84 deletions(-) delete mode 100644 sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpMessageSender.java create mode 100644 sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java create mode 100644 sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportInputStream.java create mode 100644 sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportOutputStream.java create mode 100644 sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportInputStream.java create mode 100644 sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportOutputStream.java create mode 100644 sandbox/src/test/java/org/springframework/ws/transport/http/CommonsHttpMessageSenderTest.java create mode 100644 sandbox/src/test/resources/log4j.properties diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java index d68fcd2a..d66c7289 100644 --- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java +++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java @@ -37,7 +37,7 @@ import org.apache.axiom.soap.impl.llom.soap12.SOAP12Factory; 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.util.StringUtils; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; import org.springframework.ws.transport.TransportInputStream; @@ -110,10 +110,14 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia 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(); + if (iterator.hasNext()) { + contentType = (String) iterator.next(); + } + } + if (!StringUtils.hasLength(contentType)) { + // fall back to SOAP 1.1 as a default + contentType = SOAP11Constants.SOAP_11_CONTENT_TYPE; } - Assert.hasLength(contentType, "No " + CONTENT_TYPE_HEADER + " header present of TransportRequest"); try { if (isMultiPartRelated(contentType)) { return createMultiPartAxiomSoapMessage(inputStream, contentType); diff --git a/samples/echo/src/main/webapp/WEB-INF/spring-ws-servlet.xml b/samples/echo/src/main/webapp/WEB-INF/spring-ws-servlet.xml index 40c10d46..f635b402 100755 --- a/samples/echo/src/main/webapp/WEB-INF/spring-ws-servlet.xml +++ b/samples/echo/src/main/webapp/WEB-INF/spring-ws-servlet.xml @@ -1,7 +1,13 @@ - - - + + + + This web application context contains Spring-WS beans. The beans defined in this context are automatically + detected by Spring-WS, similar to the way Controllers are picked up in Spring Web MVC. + + This endpoint mapping uses the qualified name of the payload (body contents) to determine the endpoint for @@ -40,7 +46,10 @@ - - + + + This bean is our "business" service. + + \ No newline at end of file diff --git a/sandbox/pom.xml b/sandbox/pom.xml index 32263783..32de9430 100644 --- a/sandbox/pom.xml +++ b/sandbox/pom.xml @@ -44,25 +44,31 @@ javax.xml.soap saaj-api - 1.3 provided javax.servlet servlet-api - 2.4 provided javax.jms jms - 1.1 + provided + + + javax.mail + mail + provided + + com.sun.xml.messaging.saaj + saaj-impl + commons-httpclient commons-httpclient - 3.0.1 true @@ -77,4 +83,4 @@ test - \ No newline at end of file + diff --git a/sandbox/src/main/java/org/springframework/ws/transport/MessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/MessageSender.java index 59d49d9f..8f5e35d9 100644 --- a/sandbox/src/main/java/org/springframework/ws/transport/MessageSender.java +++ b/sandbox/src/main/java/org/springframework/ws/transport/MessageSender.java @@ -10,7 +10,7 @@ import org.springframework.ws.context.MessageContext; public interface MessageSender { /** - * Sends the given message context. The response message, if any, is stored in the context. + * Sends the given message context. The response message, if any, is stored in the context. * * @param messageContext the message to be sent */ diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpMessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpMessageSender.java deleted file mode 100644 index 7ba6cc4b..00000000 --- a/sandbox/src/main/java/org/springframework/ws/transport/http/AbstractHttpMessageSender.java +++ /dev/null @@ -1,26 +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 org.springframework.ws.transport.MessageSender; - -/** - * @author Arjen Poutsma - */ -public abstract class AbstractHttpMessageSender implements MessageSender { - -} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java new file mode 100644 index 00000000..aeaac9b3 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java @@ -0,0 +1,183 @@ +/* + * 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.net.URL; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.methods.PostMethod; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.transport.MessageSender; +import org.springframework.ws.transport.TransportInputStream; + +/** + * MessageSender implementation that uses Jakarta + * Commons HttpClient to execute POST requests. + *

+ * Allows to use a preconfigured HttpClient instance, potentially with authentication, HTTP connection pooling, etc. + * Also designed for easy subclassing, customizing specific template methods. + * + * @author Arjen Poutsma + * @see org.springframework.ws.transport.http.HttpUrlConnectionMessageSender + */ +public class CommonsHttpMessageSender implements MessageSender { + + private HttpClient httpClient; + + private URL url; + + /** + * Create a new instance of the CommonsHttpMessageSender with a default HttpClient that + * uses a default MultiThreadedHttpConnectionManager. + * + * @see org.apache.commons.httpclient.HttpClient + * @see org.apache.commons.httpclient.MultiThreadedHttpConnectionManager + */ + public CommonsHttpMessageSender() { + httpClient = new HttpClient(new MultiThreadedHttpConnectionManager()); + } + + /** + * Returns the HttpClient used by this message sender. + */ + public HttpClient getHttpClient() { + return httpClient; + } + + /** + * Set the HttpClient used by this message sender. + */ + public void setHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public void send(MessageContext messageContext) throws IOException { + PostMethod postMethod = createPostMethod(); + try { + writeRequestMessage(postMethod, messageContext.getRequest()); + executePostMethod(getHttpClient(), postMethod); + validateResponse(postMethod); + readResponse(postMethod, messageContext); + } + finally { + postMethod.releaseConnection(); + } + } + + /** + * Create a PostMethod for the given configuration. + * + * @return the PostMethod instance + * @throws IOException if thrown by I/O methods + */ + protected PostMethod createPostMethod() throws IOException { + return new PostMethod(getUrl().toString()); + } + + /** + * Set the given message as request body. + *

+ * The default implementation simply sets the message as the PostMethod's request body. This can be overridden, for + * example, to write a specific encoding and potentially set appropriate HTTP request headers. + * + * @param postMethod the PostMethod to set the request message on + * @param message the request message to be set + * @throws IOException if thrown by I/O methods + */ + protected void writeRequestMessage(PostMethod postMethod, WebServiceMessage message) throws IOException { + CommonsHttpTransportOutputStream tos = new CommonsHttpTransportOutputStream(postMethod); + try { + message.writeTo(tos); + tos.flush(); + } + finally { + tos.close(); + } + } + + /** + * Execute the given PostMethod instance. + * + * @param httpClient the HttpClient to execute on + * @param postMethod the PostMethod to execute + * @throws IOException if thrown by I/O methods + * @see org.apache.commons.httpclient.HttpClient#executeMethod(org.apache.commons.httpclient.HttpMethod) + */ + protected void executePostMethod(HttpClient httpClient, PostMethod postMethod) throws IOException { + httpClient.executeMethod(postMethod); + } + + /** + * Validate the given response as contained in the PostMethod object, throwing an exception if it does not + * correspond to a successful HTTP response. + *

+ * Default implementation rejects any HTTP status code that does not start with 2, excluding 500 (Internal Server + * Error, used for SOAP Faults). + * + * @param postMethod the executed PostMethod to validate + * @throws IOException if validation failed + * @see org.apache.commons.httpclient.methods.PostMethod#getStatusCode() + */ + protected void validateResponse(PostMethod postMethod) throws IOException { + int statusCode = postMethod.getStatusCode(); + if (statusCode != HttpStatus.SC_INTERNAL_SERVER_ERROR && statusCode / 100 != 2) { + throw new IOException("Did not receive successful HTTP response: status code = " + statusCode + + ", status message = [" + postMethod.getStatusText() + "]"); + } + + } + + /** + * Read the response from the given executed remote invocation request. + * + * @param postMethod the PostMethod to read the response message from + * @return an InputStream for the response body + * @throws IOException if thrown by I/O methods + */ + protected void readResponse(PostMethod postMethod, MessageContext messageContext) throws IOException { + if (postMethod.getStatusCode() == HttpStatus.SC_NO_CONTENT || postMethod.getResponseContentLength() == 0) { + return; + } + TransportInputStream tis = new CommonsHttpTransportInputStream(postMethod); + try { + messageContext.readResponse(tis); + } + finally { + if (tis != null) { + tis.close(); + } + } + } + + /** + * Returns the url used by this message sender. + */ + public URL getUrl() { + return url; + } + + /** + * Sets the url used by this message sender. + */ + public void setUrl(URL url) { + this.url = url; + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportInputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportInputStream.java new file mode 100644 index 00000000..606fd3e3 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportInputStream.java @@ -0,0 +1,77 @@ +/* + * 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.Arrays; +import java.util.Iterator; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.springframework.util.Assert; +import org.springframework.ws.transport.TransportInputStream; + +/** + * Implementation of the TransportInputStream interface based on {@link + * org.apache.commons.httpclient.methods.PostMethod}. Exposes the PostMethod. + * + * @author Arjen Poutsma + */ +public class CommonsHttpTransportInputStream extends TransportInputStream { + + private final PostMethod postMethod; + + /** + * Constructs a new instance of the CommonsHttpTransportInputStream with a given + * PostMethod. + */ + public CommonsHttpTransportInputStream(PostMethod postMethod) { + Assert.notNull(postMethod, "postMethod must not be null"); + this.postMethod = postMethod; + } + + protected InputStream createInputStream() throws IOException { + return postMethod.getResponseBodyAsStream(); + } + + public Iterator getHeaderNames() throws IOException { + Header[] headers = postMethod.getRequestHeaders(); + String[] names = new String[headers.length]; + for (int i = 0; i < headers.length; i++) { + names[i] = headers[i].getName(); + } + return Arrays.asList(names).iterator(); + } + + public Iterator getHeaders(String name) throws IOException { + Header[] headers = postMethod.getRequestHeaders(name); + String[] names = new String[headers.length]; + for (int i = 0; i < headers.length; i++) { + names[i] = headers[i].getValue(); + } + return Arrays.asList(names).iterator(); + } + + /** + * Returns the wrapped PostMethod. + */ + public HttpMethod getPostMethod() { + return postMethod; + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportOutputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportOutputStream.java new file mode 100644 index 00000000..7578ddb0 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/http/CommonsHttpTransportOutputStream.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.http; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; +import org.apache.commons.httpclient.methods.PostMethod; +import org.springframework.ws.transport.TransportOutputStream; + +/** + * Implementation of the TransportOutputStream interface based on {@link + * org.apache.commons.httpclient.methods.PostMethod}. Exposes the PostMethod. + * + * @author Arjen Poutsma + */ +public class CommonsHttpTransportOutputStream extends TransportOutputStream { + + private final PostMethod postMethod; + + private final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + /** + * Constructs a new instance of the CommonsHttpTransportOutputStream with a given + * PostMethod. + */ + public CommonsHttpTransportOutputStream(PostMethod postMethod) { + this.postMethod = postMethod; + } + + public void addHeader(String name, String value) throws IOException { + postMethod.addRequestHeader(name, value); + } + + public void close() throws IOException { + postMethod.setRequestEntity(new ByteArrayRequestEntity(bos.toByteArray())); + } + + protected OutputStream getOutputStream() throws IOException { + return bos; + } + + /** + * Returns the wrapped PostMethod. + */ + public HttpMethod getPostMethod() { + return postMethod; + } + +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java index 1edc7bea..8949d853 100644 --- a/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java +++ b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java @@ -30,15 +30,20 @@ import org.springframework.ws.transport.TransportOutputStream; /** * MessageSender implementation that uses standard J2SE facilities to execute POST requests, without * support for HTTP authentication or advanced configuration options. + *

+ * Designed for easy subclassing, customizing specific template methods. However, consider {@link + * org.springframework.ws.transport.http.CommonsHttpMessageSender} for more sophisticated needs: the J2SE + * HttpURLConnection is rather limited in its capabilities. * * @author Arjen Poutsma + * @see java.net.HttpURLConnection */ public class HttpUrlConnectionMessageSender implements MessageSender { - private URL url; - private static final String HTTP_METHOD_POST = "POST"; + private URL url; + /** * Returns the url used by this message sender. */ @@ -55,11 +60,15 @@ public class HttpUrlConnectionMessageSender implements MessageSender { public void send(MessageContext messageContext) throws IOException { HttpURLConnection connection = openConnection(); - prepareConnection(connection); - writeRequestMessage(connection, messageContext.getRequest()); - validateResponse(connection); - readResponse(connection, messageContext); - connection.disconnect(); + try { + prepareConnection(connection); + writeRequestMessage(connection, messageContext.getRequest()); + validateResponse(connection); + readResponse(connection, messageContext); + } + finally { + connection.disconnect(); + } } protected HttpURLConnection openConnection() throws IOException { @@ -77,28 +86,6 @@ public class HttpUrlConnectionMessageSender implements MessageSender { connection.setDoOutput(true); } - protected void writeRequestMessage(HttpURLConnection connection, WebServiceMessage message) throws IOException { - TransportOutputStream tos = null; - try { - tos = new HttpUrlConnectionTransportOutputStream(connection); - message.writeTo(tos); - tos.flush(); - } - finally { - if (tos != null) { - tos.close(); - } - } - } - - protected void validateResponse(HttpURLConnection connection) throws IOException { - int responseCode = connection.getResponseCode(); - if (responseCode != HttpURLConnection.HTTP_INTERNAL_ERROR && responseCode / 100 != 2) { - throw new IOException("Did not receive successful HTTP response: status code = " + responseCode + - ", status message = [" + connection.getResponseMessage() + "]"); - } - } - protected void readResponse(HttpURLConnection connection, MessageContext messageContext) throws IOException { if (connection.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT || connection.getContentLength() == 0) { return; @@ -114,4 +101,26 @@ public class HttpUrlConnectionMessageSender implements MessageSender { } } } + + protected void validateResponse(HttpURLConnection connection) throws IOException { + int responseCode = connection.getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_INTERNAL_ERROR && responseCode / 100 != 2) { + throw new IOException("Did not receive successful HTTP response: status code = " + responseCode + + ", status message = [" + connection.getResponseMessage() + "]"); + } + } + + protected void writeRequestMessage(HttpURLConnection connection, WebServiceMessage message) throws IOException { + TransportOutputStream tos = null; + try { + tos = new HttpUrlConnectionTransportOutputStream(connection); + message.writeTo(tos); + tos.flush(); + } + finally { + if (tos != null) { + tos.close(); + } + } + } } 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 index 3e6acd1f..33b799dd 100644 --- a/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportInputStream.java +++ b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportInputStream.java @@ -30,17 +30,40 @@ import org.springframework.util.StringUtils; import org.springframework.ws.transport.TransportInputStream; /** + * Implementation of the TransportInputStream interface based on {@link java.net.HttpURLConnection}. + * Exposes the HttpURLConnection. + * * @author Arjen Poutsma */ public class HttpUrlConnectionTransportInputStream extends TransportInputStream { private final HttpURLConnection connection; + /** + * Constructs a new instance of the HttpUrlConnectionTransportInputStream based on the given + * HttpURLConnection. + */ public HttpUrlConnectionTransportInputStream(HttpURLConnection connection) throws IOException { Assert.notNull(connection, "connection must not be null"); this.connection = connection; } + /** + * Returns the wrapped HttpURLConnection. + */ + public HttpURLConnection getConnection() { + return connection; + } + + protected InputStream createInputStream() throws IOException { + if (connection.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) { + return connection.getErrorStream(); + } + else { + return connection.getInputStream(); + } + } + public Iterator getHeaderNames() throws IOException { List headerNames = new ArrayList(); // Header field 0 is the status line, so we start at 1 @@ -66,13 +89,4 @@ public class HttpUrlConnectionTransportInputStream extends TransportInputStream return tokens.iterator(); } } - - protected InputStream createInputStream() throws IOException { - if (connection.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) { - return connection.getErrorStream(); - } - else { - 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 index aec2dfe0..19ed3966 100644 --- a/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportOutputStream.java +++ b/sandbox/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionTransportOutputStream.java @@ -24,12 +24,19 @@ import org.springframework.util.Assert; import org.springframework.ws.transport.TransportOutputStream; /** + * Implementation of the TransportOutputStream interface based on {@link java.net.HttpURLConnection}. + * Exposes the HttpURLConnection. + * * @author Arjen Poutsma */ public class HttpUrlConnectionTransportOutputStream extends TransportOutputStream { private final HttpURLConnection connection; + /** + * Constructs a new instance of the HttpUrlConnectionTransportOutputStream based on the given + * HttpURLConnection. + */ public HttpUrlConnectionTransportOutputStream(HttpURLConnection connection) throws IOException { Assert.notNull(connection, "connection must not be null"); this.connection = connection; @@ -42,4 +49,11 @@ public class HttpUrlConnectionTransportOutputStream extends TransportOutputStrea protected OutputStream getOutputStream() throws IOException { return connection.getOutputStream(); } + + /** + * Returns the wrapped HttpURLConnection. + */ + public HttpURLConnection getConnection() { + return connection; + } } diff --git a/sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportInputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportInputStream.java new file mode 100644 index 00000000..4865db93 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportInputStream.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.mail; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Iterator; +import javax.mail.Message; +import javax.mail.MessagingException; + +import org.springframework.ws.transport.TransportInputStream; +import org.springframework.ws.transport.support.EnumerationIterator; + +/** + * @author Arjen Poutsma + */ +public class MailTransportInputStream extends TransportInputStream { + + private final Message message; + + public MailTransportInputStream(Message message) { + this.message = message; + } + + protected InputStream createInputStream() throws IOException { + try { + return message.getDataHandler().getInputStream(); + } + catch (MessagingException ex) { + throw new IOException(ex.getMessage()); + } + } + + public Iterator getHeaders(String name) throws IOException { + try { + String[] headers = message.getHeader(name); + return Arrays.asList(headers).iterator(); + } + catch (MessagingException ex) { + throw new IOException(ex.getMessage()); + } + } + + public Iterator getHeaderNames() throws IOException { + try { + return new EnumerationIterator(message.getAllHeaders()); + } + catch (MessagingException ex) { + throw new IOException(ex.getMessage()); + } + } +} diff --git a/sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportOutputStream.java b/sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportOutputStream.java new file mode 100644 index 00000000..d25fd518 --- /dev/null +++ b/sandbox/src/main/java/org/springframework/ws/transport/mail/MailTransportOutputStream.java @@ -0,0 +1,54 @@ +/* + * 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.mail; + +import java.io.IOException; +import java.io.OutputStream; +import javax.mail.Message; +import javax.mail.MessagingException; + +import org.springframework.ws.transport.TransportOutputStream; + +/** + * @author Arjen Poutsma + */ +public class MailTransportOutputStream extends TransportOutputStream { + + private final Message message; + + public MailTransportOutputStream(Message message) { + this.message = message; + } + + public void addHeader(String name, String value) throws IOException { + try { + message.addHeader(name, value); + } + catch (MessagingException ex) { + throw new IOException(ex.getMessage()); + } + } + + protected OutputStream getOutputStream() throws IOException { + try { + return message.getDataHandler().getOutputStream(); + } + catch (MessagingException ex) { + throw new IOException(ex.getMessage()); + } + } +} 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 index ee0e5b6c..b92d6645 100644 --- a/sandbox/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderTestCase.java +++ b/sandbox/src/test/java/org/springframework/ws/transport/http/AbstractHttpWebServiceMessageSenderTestCase.java @@ -52,6 +52,10 @@ public abstract class AbstractHttpWebServiceMessageSenderTestCase extends TestCa } + protected final void tearDown() throws Exception { + jettyServer.stop(); + } + private static class EchoServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { diff --git a/sandbox/src/test/java/org/springframework/ws/transport/http/CommonsHttpMessageSenderTest.java b/sandbox/src/test/java/org/springframework/ws/transport/http/CommonsHttpMessageSenderTest.java new file mode 100644 index 00000000..13951fc2 --- /dev/null +++ b/sandbox/src/test/java/org/springframework/ws/transport/http/CommonsHttpMessageSenderTest.java @@ -0,0 +1,52 @@ +/* + * 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.net.URL; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPMessage; + +import org.springframework.ws.context.DefaultMessageContext; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; +import org.springframework.ws.soap.saaj.saaj13.Saaj13SoapMessage; + +public class CommonsHttpMessageSenderTest extends AbstractHttpWebServiceMessageSenderTestCase { + + private CommonsHttpMessageSender sender; + + private MessageFactory messageFactory; + + protected void onSetUp() throws Exception { + sender = new CommonsHttpMessageSender(); + sender.setUrl(new URL(URL)); + messageFactory = MessageFactory.newInstance(); + } + + public void testSend() throws Exception { + SOAPMessage message = messageFactory.createMessage(); + message.getMimeHeaders().addHeader(HEADER_NAME, HEADER_VALUE); + Saaj13SoapMessage request = new Saaj13SoapMessage(message); + MessageContext context = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory)); +// AxiomSoapMessageFactory soapMessageFactory = new AxiomSoapMessageFactory(); +// MessageContext context = new DefaultMessageContext(soapMessageFactory); + sender.send(context); + assertTrue("No response", context.hasResponse()); + + context.getResponse().writeTo(System.out); + } +} diff --git a/sandbox/src/test/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSenderTest.java b/sandbox/src/test/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSenderTest.java index 56e984a4..2571f78c 100644 --- a/sandbox/src/test/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSenderTest.java +++ b/sandbox/src/test/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSenderTest.java @@ -22,7 +22,8 @@ import javax.xml.soap.SOAPMessage; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; -import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory; +import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; +import org.springframework.ws.soap.saaj.saaj13.Saaj13SoapMessage; public class HttpUrlConnectionMessageSenderTest extends AbstractHttpWebServiceMessageSenderTestCase { @@ -39,10 +40,10 @@ public class HttpUrlConnectionMessageSenderTest extends AbstractHttpWebServiceMe public void testSend() throws Exception { SOAPMessage message = messageFactory.createMessage(); message.getMimeHeaders().addHeader(HEADER_NAME, HEADER_VALUE); -// Saaj13SoapMessage request = new Saaj13SoapMessage(message); -// MessageContext context = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory)); - AxiomSoapMessageFactory soapMessageFactory = new AxiomSoapMessageFactory(); - MessageContext context = new DefaultMessageContext(soapMessageFactory); + Saaj13SoapMessage request = new Saaj13SoapMessage(message); + MessageContext context = new DefaultMessageContext(request, new SaajSoapMessageFactory(messageFactory)); +// AxiomSoapMessageFactory soapMessageFactory = new AxiomSoapMessageFactory(); +// MessageContext context = new DefaultMessageContext(soapMessageFactory); sender.send(context); assertTrue("No response", context.hasResponse()); diff --git a/sandbox/src/test/resources/log4j.properties b/sandbox/src/test/resources/log4j.properties new file mode 100644 index 00000000..92e896c8 --- /dev/null +++ b/sandbox/src/test/resources/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootCategory=INFO, stdout +log4j.logger.org.springframework.ws=DEBUG + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n \ No newline at end of file