From 5a51be4f01ae2444ca863e2a1c7127e187f83138 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Sun, 3 Feb 2008 01:52:05 +0000 Subject: [PATCH] SWS-277 --- .../endpoint/mapping/UriEndpointMapping.java | 72 +++++++++++++++++++ .../ws/transport/WebServiceConnection.java | 4 ++ .../transport/http/CommonsHttpConnection.java | 15 ++++ .../transport/http/HttpServletConnection.java | 14 +++- .../ws/transport/http/HttpUrlConnection.java | 10 +++ ...ebServiceMessageReceiverObjectSupport.java | 14 ++++ .../client/core/WebServiceTemplateTest.java | 1 + .../mapping/UriEndpointMappingTest.java | 61 ++++++++++++++++ ...rviceMessageReceiverObjectSupportTest.java | 5 ++ .../transport/jms/JmsReceiverConnection.java | 15 ++++ .../ws/transport/jms/JmsSenderConnection.java | 15 ++++ .../jms/support/JmsTransportUtils.java | 24 +++++++ .../transport/mail/MailMessageReceiver.java | 11 +-- .../mail/MailReceiverConnection.java | 22 ++++++ .../transport/mail/MailSenderConnection.java | 9 +++ .../mail/support/MailTransportUtils.java | 19 +++++ 16 files changed, 300 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMapping.java create mode 100644 core/src/test/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMappingTest.java diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMapping.java b/core/src/main/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMapping.java new file mode 100644 index 00000000..777e3fd5 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMapping.java @@ -0,0 +1,72 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ws.server.endpoint.mapping; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory; +import org.springframework.ws.transport.WebServiceConnection; +import org.springframework.ws.transport.context.TransportContext; +import org.springframework.ws.transport.context.TransportContextHolder; + +/** + * Implementation of the EndpointMapping interface to map from the full request URI to endpoint beans. + * Supports both mapping to bean instances and mapping to bean names: the latter is required for prototype handlers. + *

+ * The endpointMap property is suitable for populating the endpoint map with bean references, e.g. via the + * map element in XML bean definitions. + *

+ * Mappings to bean names can be set via the mappings property, in a form accepted by the + * java.util.Properties class, like as follows: + *

+ * http://example.com:8080/services/bookFlight=bookFlightEndpoint
+ * jms://exampleQueue=getFlightsEndpoint
+ * 
+ * The syntax is SOAP_ACTION=ENDPOINT_BEAN_NAME. + *

+ * This endpoint mapping does not read from the request message, and therefore is more suitable for message factories + * which directly read from the transport request (such as the {@link AxiomSoapMessageFactory} with the + * payloadCaching disabled). However, this endpoint mapping obviously is transport specific. + * + * @author Arjen Poutsma + * @since 1.5.0 + */ +public class UriEndpointMapping extends AbstractMapBasedEndpointMapping { + + protected boolean validateLookupKey(String key) { + try { + new URI(key); + return true; + } + catch (URISyntaxException e) { + return false; + } + } + + protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { + TransportContext transportContext = TransportContextHolder.getTransportContext(); + if (transportContext != null) { + WebServiceConnection connection = transportContext.getConnection(); + if (connection != null) { + return connection.getUri().toString(); + } + } + return null; + } +} diff --git a/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java b/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java index 9d48bfbc..5b65cf41 100644 --- a/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/WebServiceConnection.java @@ -18,6 +18,7 @@ package org.springframework.ws.transport; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; @@ -52,6 +53,9 @@ public interface WebServiceConnection { */ WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException; + /** Returns the URI for this connection. */ + URI getUri() throws URISyntaxException; + /** * Indicates whether this connection has an error. Typically, error detection is done by inspecting connection error * codes, etc. diff --git a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java index 8d144b14..58fe1a79 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpConnection.java @@ -20,11 +20,14 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Arrays; import java.util.Iterator; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.httpclient.methods.PostMethod; @@ -63,6 +66,18 @@ public class CommonsHttpConnection extends AbstractHttpSenderConnection { } /* + * URI + */ + + public URI getUri() throws URISyntaxException { + try { + return new URI(postMethod.getURI().toString()); + } + catch (URIException ex) { + throw new URISyntaxException("", ex.getMessage()); + } + } +/* * Sending request */ diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java b/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java index 1157adf5..a7d515b9 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/HttpServletConnection.java @@ -19,6 +19,8 @@ package org.springframework.ws.transport.http; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Iterator; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -82,9 +84,19 @@ public class HttpServletConnection extends AbstractReceiverConnection } /* - * Receiving request + * URI */ + public URI getUri() throws URISyntaxException { + return new URI(httpServletRequest.getScheme(), null, httpServletRequest.getServerName(), + httpServletRequest.getServerPort(), httpServletRequest.getRequestURI(), + httpServletRequest.getQueryString(), null); + } + + /* + * Receiving request + */ + protected Iterator getRequestHeaderNames() throws IOException { return new EnumerationIterator(getHttpServletRequest().getHeaderNames()); } diff --git a/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java b/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java index 202e0b5b..bb34cc71 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java +++ b/core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnection.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -59,6 +61,14 @@ public class HttpUrlConnection extends AbstractHttpSenderConnection { connection.disconnect(); } + /* + * URI + */ + + public URI getUri() throws URISyntaxException { + return connection.getURL().toURI(); + } + /* * Sending request */ diff --git a/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java b/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java index 9455bf5c..9083db43 100644 --- a/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java +++ b/core/src/main/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupport.java @@ -16,6 +16,8 @@ package org.springframework.ws.transport.support; +import java.net.URISyntaxException; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -76,6 +78,7 @@ public abstract class WebServiceMessageReceiverObjectSupport implements Initiali */ protected final void handleConnection(WebServiceConnection connection, WebServiceMessageReceiver receiver) throws Exception { + logUri(connection); TransportContext previousTransportContext = TransportContextHolder.getTransportContext(); TransportContextHolder.setTransportContext(new DefaultTransportContext(connection)); @@ -105,4 +108,15 @@ public abstract class WebServiceMessageReceiverObjectSupport implements Initiali } } + private void logUri(WebServiceConnection connection) { + if (logger.isDebugEnabled()) { + try { + logger.debug("Regestering incoming connection [" + connection.getUri() + "]"); + } + catch (URISyntaxException e) { + // ignore + } + } + } + } diff --git a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java index 9b06666e..88956154 100644 --- a/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java +++ b/core/src/test/java/org/springframework/ws/client/core/WebServiceTemplateTest.java @@ -52,6 +52,7 @@ public class WebServiceTemplateTest extends XMLTestCase { template.setMessageFactory(messageFactory); connectionControl = MockControl.createStrictControl(FaultAwareWebServiceConnection.class); connectionMock = (FaultAwareWebServiceConnection) connectionControl.getMock(); + connectionControl.expectAndDefaultReturn(connectionMock.getUri(), new URI("mock")); final URI expectedUri = new URI("http://www.springframework.org/spring-ws"); template.setMessageSender(new WebServiceMessageSender() { diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMappingTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMappingTest.java new file mode 100644 index 00000000..99d8b575 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/server/endpoint/mapping/UriEndpointMappingTest.java @@ -0,0 +1,61 @@ +/* + * Copyright ${YEAR} the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ws.server.endpoint.mapping; + +import java.net.URI; + +import junit.framework.TestCase; +import org.easymock.MockControl; + +import org.springframework.ws.MockWebServiceMessageFactory; +import org.springframework.ws.context.DefaultMessageContext; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.transport.WebServiceConnection; +import org.springframework.ws.transport.context.DefaultTransportContext; +import org.springframework.ws.transport.context.TransportContextHolder; + +public class UriEndpointMappingTest extends TestCase { + + private UriEndpointMapping mapping; + + private MessageContext context; + + protected void setUp() throws Exception { + mapping = new UriEndpointMapping(); + context = new DefaultMessageContext(new MockWebServiceMessageFactory()); + } + + public void testGetLookupKeyForMessage() throws Exception { + MockControl control = MockControl.createControl(WebServiceConnection.class); + WebServiceConnection connectionMock = (WebServiceConnection) control.getMock(); + TransportContextHolder.setTransportContext(new DefaultTransportContext(connectionMock)); + + URI uri = new URI("jms://exampleQueue"); + control.expectAndReturn(connectionMock.getUri(), uri); + control.replay(); + + assertEquals("Invalid lookup key", uri.toString(), mapping.getLookupKeyForMessage(context)); + + control.verify(); + TransportContextHolder.setTransportContext(null); + } + + public void testValidateLookupKey() throws Exception { + assertTrue("URI not valid", mapping.validateLookupKey("http://example.com/services")); + assertFalse("URI not valid", mapping.validateLookupKey("some string")); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java b/core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java index cc425b79..4129fcaa 100644 --- a/core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java +++ b/core/src/test/java/org/springframework/ws/transport/support/WebServiceMessageReceiverObjectSupportTest.java @@ -16,8 +16,11 @@ package org.springframework.ws.transport.support; +import java.net.URI; + import junit.framework.TestCase; import org.easymock.MockControl; + import org.springframework.ws.MockWebServiceMessage; import org.springframework.ws.MockWebServiceMessageFactory; import org.springframework.ws.context.MessageContext; @@ -46,6 +49,7 @@ public class WebServiceMessageReceiverObjectSupportTest extends TestCase { } public void testHandleConnectionResponse() throws Exception { + connectionControl.expectAndReturn(connectionMock.getUri(), new URI("http://example.com")); connectionControl.expectAndReturn(connectionMock.receive(messageFactory), request); connectionMock.send(new MockWebServiceMessage()); connectionControl.setMatcher(MockControl.ALWAYS_MATCHER); @@ -67,6 +71,7 @@ public class WebServiceMessageReceiverObjectSupportTest extends TestCase { } public void testHandleConnectionNoResponse() throws Exception { + connectionControl.expectAndReturn(connectionMock.getUri(), new URI("http://example.com")); connectionControl.expectAndReturn(connectionMock.receive(messageFactory), request); connectionMock.close(); diff --git a/support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java b/support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java index 732c43e7..394a7786 100644 --- a/support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java +++ b/support/src/main/java/org/springframework/ws/transport/jms/JmsReceiverConnection.java @@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Iterator; import javax.jms.BytesMessage; import javax.jms.JMSException; @@ -98,6 +100,19 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { return responseMessage; } + /* + * URI + */ + + public URI getUri() throws URISyntaxException { + try { + return JmsTransportUtils.toUri(requestMessage.getJMSDestination()); + } + catch (JMSException ex) { + throw new URISyntaxException("", ex.getMessage()); + } + } + /* * Errors */ diff --git a/support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java b/support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java index 9d41dcdb..ca734fbc 100644 --- a/support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java +++ b/support/src/main/java/org/springframework/ws/transport/jms/JmsSenderConnection.java @@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Iterator; import javax.jms.BytesMessage; import javax.jms.Connection; @@ -136,6 +138,19 @@ public class JmsSenderConnection extends AbstractSenderConnection implements Web this.messageType = messageType; } + /* + * URI + */ + + public URI getUri() throws URISyntaxException { + try { + return JmsTransportUtils.toUri(requestDestination); + } + catch (JMSException ex) { + throw new URISyntaxException("", ex.getMessage()); + } + } + /* * Errors */ diff --git a/support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java b/support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java index ad5051d7..3964ce09 100644 --- a/support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java +++ b/support/src/main/java/org/springframework/ws/transport/jms/support/JmsTransportUtils.java @@ -17,6 +17,7 @@ package org.springframework.ws.transport.jms.support; import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; @@ -28,6 +29,8 @@ import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; +import javax.jms.Queue; +import javax.jms.Topic; import org.springframework.ws.transport.jms.JmsTransportConstants; @@ -91,6 +94,27 @@ public class JmsTransportUtils { return propertyName; } + /** + * Converts the given JMS destination a jms URI. + * + * @param destination the destination + * @return a jms URI + */ + public static URI toUri(Destination destination) throws URISyntaxException, JMSException { + String destinationName; + if (destination instanceof Queue) { + destinationName = ((Queue) destination).getQueueName(); + } + else if (destination instanceof Topic) { + Topic topic = (Topic) destination; + destinationName = topic.getTopicName(); + } + else { + throw new IllegalArgumentException("Destination [ " + destination + "] is neither Queue nor Topic"); + } + return new URI(JmsTransportConstants.JMS_URI_SCHEME, destinationName, null); + } + /** Returns the destination name of the given URI. */ public static String getDestinationName(URI uri) { return getStringParameter(DESTINATION_NAME_PATTERN, uri); diff --git a/support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java b/support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java index 325ad428..6721cded 100644 --- a/support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java +++ b/support/src/main/java/org/springframework/ws/transport/mail/MailMessageReceiver.java @@ -26,7 +26,6 @@ import javax.mail.Store; import javax.mail.URLName; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; import org.springframework.scheduling.SchedulingAwareRunnable; import org.springframework.util.Assert; @@ -67,9 +66,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver private MonitoringStrategy monitoringStrategy; - /** - * Sets the from address to use when sending reponse messages. - */ + /** Sets the from address to use when sending reponse messages. */ public void setFrom(String from) throws AddressException { this.from = new InternetAddress(from); } @@ -219,12 +216,6 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver try { Message[] messages = monitoringStrategy.monitor(folder); for (int i = 0; i < messages.length; i++) { - if (logger.isDebugEnabled()) { - if (messages[i] instanceof MimeMessage) { - MimeMessage mimeMessage = (MimeMessage) messages[i]; - logger.debug("Received email message with MessageID " + mimeMessage.getMessageID()); - } - } MessageHandler handler = new MessageHandler(messages[i]); execute(handler); } diff --git a/support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java b/support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java index f4c65851..fdde9bff 100644 --- a/support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java +++ b/support/src/main/java/org/springframework/ws/transport/mail/MailReceiverConnection.java @@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; @@ -28,6 +30,7 @@ import java.util.Iterator; import java.util.List; import javax.activation.DataHandler; import javax.activation.DataSource; +import javax.mail.Address; import javax.mail.Header; import javax.mail.Message; import javax.mail.MessagingException; @@ -37,6 +40,7 @@ import javax.mail.URLName; import javax.mail.internet.InternetAddress; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.transport.AbstractReceiverConnection; import org.springframework.ws.transport.TransportConstants; @@ -96,6 +100,24 @@ public class MailReceiverConnection extends AbstractReceiverConnection { } /* + * URI + */ + + public URI getUri() throws URISyntaxException { + try { + Address[] recipients = requestMessage.getRecipients(Message.RecipientType.TO); + if (!ObjectUtils.isEmpty(recipients) && recipients[0] instanceof InternetAddress) { + return MailTransportUtils.toUri((InternetAddress) recipients[0], requestMessage.getSubject()); + } + else { + throw new URISyntaxException("", "Could not determine To header"); + } + } + catch (MessagingException ex) { + throw new URISyntaxException("", ex.getMessage()); + } + } +/* * Errors */ diff --git a/support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java b/support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java index 6e64edf8..c3e0c127 100644 --- a/support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java +++ b/support/src/main/java/org/springframework/ws/transport/mail/MailSenderConnection.java @@ -21,6 +21,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -132,6 +134,13 @@ public class MailSenderConnection extends AbstractSenderConnection { this.subject = subject; } + /* + * URI + */ + public URI getUri() throws URISyntaxException { + return MailTransportUtils.toUri(to, subject); + } + /* * Sending */ diff --git a/support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java b/support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java index 79b22c98..78371938 100644 --- a/support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java +++ b/support/src/main/java/org/springframework/ws/transport/mail/support/MailTransportUtils.java @@ -17,6 +17,7 @@ package org.springframework.ws.transport.mail.support; import java.net.URI; +import java.net.URISyntaxException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.mail.Folder; @@ -30,7 +31,9 @@ import javax.mail.internet.InternetAddress; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.util.StringUtils; +import org.springframework.ws.transport.mail.MailTransportConstants; /** * Collection of utility methods to work with Mail transports. @@ -165,5 +168,21 @@ public abstract class MailTransportUtils { return tempURL.toString(); } + /** + * Converts the given internet address into a mailto URI. + * + * @param to the To: address + * @param subject the subject, may be null + * @return a mailto URI + */ + public static URI toUri(InternetAddress to, String subject) throws URISyntaxException { + if (StringUtils.hasLength(subject)) { + return new URI(MailTransportConstants.MAIL_URI_SCHEME, to.getAddress() + "?subject=" + subject, null); + } + else { + return new URI(MailTransportConstants.MAIL_URI_SCHEME, to.getAddress(), null); + } + } + }