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 9e51e7f3..732c43e7 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,7 +21,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Collections; import java.util.Iterator; import javax.jms.BytesMessage; import javax.jms.JMSException; @@ -35,7 +34,7 @@ import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.transport.AbstractReceiverConnection; import org.springframework.ws.transport.WebServiceConnection; -import org.springframework.ws.transport.support.EnumerationIterator; +import org.springframework.ws.transport.jms.support.JmsTransportUtils; /** * Implementation of {@link WebServiceConnection} that is used for server-side JMS access. Exposes a {@link @@ -117,7 +116,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { protected Iterator getRequestHeaderNames() throws IOException { try { - return new EnumerationIterator(requestMessage.getPropertyNames()); + return JmsTransportUtils.getHeaderNames(requestMessage); } catch (JMSException ex) { throw new JmsTransportException("Could not get property names", ex); @@ -126,8 +125,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { protected Iterator getRequestHeaders(String name) throws IOException { try { - String value = requestMessage.getStringProperty(name); - return Collections.singletonList(value).iterator(); + return JmsTransportUtils.getHeaders(requestMessage, name); } catch (JMSException ex) { throw new JmsTransportException("Could not get property value", ex); @@ -138,7 +136,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { if (requestMessage instanceof BytesMessage) { return new BytesMessageInputStream((BytesMessage) requestMessage); } - else { + else if (requestMessage instanceof TextMessage) { TextMessage textMessage = (TextMessage) requestMessage; try { String text = textMessage.getText(); @@ -149,6 +147,9 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { throw new JmsTransportException(ex); } } + else { + throw new IllegalStateException("Unknown request message type [" + requestMessage + "]"); + } } /* @@ -160,9 +161,12 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { if (requestMessage instanceof BytesMessage) { responseMessage = session.createBytesMessage(); } - else { + else if (requestMessage instanceof TextMessage) { responseMessage = session.createTextMessage(); } + else { + throw new IllegalStateException("Unknown request message type [" + requestMessage + "]"); + } responseMessage.setJMSCorrelationID(requestMessage.getJMSMessageID()); } catch (JMSException ex) { @@ -172,7 +176,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { protected void addResponseHeader(String name, String value) throws IOException { try { - responseMessage.setStringProperty(name, value); + JmsTransportUtils.addHeader(responseMessage, name, value); } catch (JMSException ex) { throw new JmsTransportException("Could not set property", ex); @@ -183,7 +187,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { if (responseMessage instanceof BytesMessage) { return new BytesMessageOutputStream((BytesMessage) responseMessage); } - else { + else if (responseMessage instanceof TextMessage) { return new ByteArrayOutputStream() { public void close() throws IOException { @@ -197,6 +201,9 @@ public class JmsReceiverConnection extends AbstractReceiverConnection { } }; } + else { + throw new IllegalStateException("Unknown request message type [" + responseMessage + "]"); + } } protected void onSendAfterWrite(WebServiceMessage message) throws IOException { 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 97da2044..9d41dcdb 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,7 +21,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Collections; import java.util.Iterator; import javax.jms.BytesMessage; import javax.jms.Connection; @@ -41,7 +40,7 @@ import org.springframework.util.Assert; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.transport.AbstractSenderConnection; import org.springframework.ws.transport.WebServiceConnection; -import org.springframework.ws.transport.support.EnumerationIterator; +import org.springframework.ws.transport.jms.support.JmsTransportUtils; /** * Implementation of {@link WebServiceConnection} that is used for client-side JMS access. Exposes a {@link @@ -169,7 +168,7 @@ public class JmsSenderConnection extends AbstractSenderConnection implements Web protected void addRequestHeader(String name, String value) throws IOException { try { - requestMessage.setStringProperty(name, value); + JmsTransportUtils.addHeader(requestMessage, name, value); } catch (JMSException ex) { throw new JmsTransportException("Could not set property", ex); @@ -257,7 +256,7 @@ public class JmsSenderConnection extends AbstractSenderConnection implements Web protected Iterator getResponseHeaderNames() throws IOException { try { - return new EnumerationIterator(responseMessage.getPropertyNames()); + return JmsTransportUtils.getHeaderNames(responseMessage); } catch (JMSException ex) { throw new JmsTransportException("Could not get property names", ex); @@ -266,13 +265,7 @@ public class JmsSenderConnection extends AbstractSenderConnection implements Web protected Iterator getResponseHeaders(String name) throws IOException { try { - String value = responseMessage.getStringProperty(name); - if (value != null) { - return Collections.singletonList(value).iterator(); - } - else { - return Collections.EMPTY_LIST.iterator(); - } + return JmsTransportUtils.getHeaders(responseMessage, name); } catch (JMSException ex) { throw new JmsTransportException("Could not get property value", ex); diff --git a/support/src/main/java/org/springframework/ws/transport/jms/JmsTransportConstants.java b/support/src/main/java/org/springframework/ws/transport/jms/JmsTransportConstants.java index 500b40a4..89b2e394 100644 --- a/support/src/main/java/org/springframework/ws/transport/jms/JmsTransportConstants.java +++ b/support/src/main/java/org/springframework/ws/transport/jms/JmsTransportConstants.java @@ -38,5 +38,16 @@ public interface JmsTransportConstants extends TransportConstants { /** Indicates a {@link TextMessage} type. */ int TEXT_MESSAGE_TYPE = 2; + /** Prefix for JMS properties that map to transport headers. */ + String PROPERTY_PREFIX = "SOAPJMS_"; + + /** JMS property used for storing {@link #HEADER_SOAP_ACTION}. */ + String PROPERTY_SOAP_ACTION = PROPERTY_PREFIX + "soapAction"; + + /** JMS property used for storing {@link #HEADER_CONTENT_LENGTH}. */ + String PROPERTY_CONTENT_LENGTH = PROPERTY_PREFIX + "contentLength"; + + /** JMS property used for storing {@link #HEADER_CONTENT_TYPE}. */ + String PROPERTY_CONTENT_TYPE = PROPERTY_PREFIX + "contentType"; } 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 148b486e..ad5051d7 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,10 +17,16 @@ package org.springframework.ws.transport.jms.support; import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.jms.DeliveryMode; import javax.jms.Destination; +import javax.jms.JMSException; import javax.jms.Message; import org.springframework.ws.transport.jms.JmsTransportConstants; @@ -34,6 +40,11 @@ import org.springframework.ws.transport.jms.JmsTransportConstants; */ public class JmsTransportUtils { + private static final String[] CONVERSION_TABLE = new String[]{JmsTransportConstants.HEADER_CONTENT_TYPE, + JmsTransportConstants.PROPERTY_CONTENT_TYPE, JmsTransportConstants.HEADER_CONTENT_LENGTH, + JmsTransportConstants.PROPERTY_CONTENT_LENGTH, JmsTransportConstants.HEADER_SOAP_ACTION, + JmsTransportConstants.PROPERTY_SOAP_ACTION}; + private static final Pattern DESTINATION_NAME_PATTERN = Pattern.compile("^([^\\?]+)"); private static final Pattern DELIVERY_MODE_PATTERN = Pattern.compile("deliveryMode=(PERSISTENT|NON_PERSISTENT)"); @@ -49,10 +60,80 @@ public class JmsTransportUtils { private JmsTransportUtils() { } + /** + * Converts the given transport header to a JMS property name. Returns the given header name if no match is found. + * + * @param headerName the header name to transform + * @return the JMS property name + */ + public static String headerToJmsProperty(String headerName) { + for (int i = 0; i < CONVERSION_TABLE.length; i = i + 2) { + if (CONVERSION_TABLE[i].equals(headerName)) { + return CONVERSION_TABLE[i + 1]; + } + } + return headerName; + } + + /** + * Converts the given JMS property name to a transport header name. Returns the given property name if no match is + * found. + * + * @param propertyName the JMS property name to transform + * @return the transport header name + */ + public static String jmsPropertyToHeader(String propertyName) { + for (int i = 1; i < CONVERSION_TABLE.length; i = i + 2) { + if (CONVERSION_TABLE[i].equals(propertyName)) { + return CONVERSION_TABLE[i - 1]; + } + } + return propertyName; + } + + /** Returns the destination name of the given URI. */ public static String getDestinationName(URI uri) { return getStringParameter(DESTINATION_NAME_PATTERN, uri); } + /** Adds the given header to the specified message. */ + public static void addHeader(Message message, String name, String value) throws JMSException { + String propertyName = JmsTransportUtils.headerToJmsProperty(name); + message.setStringProperty(propertyName, value); + } + + /** + * Returns an iterator over all header names in the given message. Delegates to {@link + * #jmsPropertyToHeader(String)}. + */ + public static Iterator getHeaderNames(Message message) throws JMSException { + Enumeration properties = message.getPropertyNames(); + List results = new ArrayList(); + while (properties.hasMoreElements()) { + String property = (String) properties.nextElement(); + if (property.startsWith(JmsTransportConstants.PROPERTY_PREFIX)) { + String header = jmsPropertyToHeader(property); + results.add(header); + } + } + return results.iterator(); + } + + /** + * Returns an iterator over all the header values of the given message and header name. Delegates to {@link + * #headerToJmsProperty(String)}. + */ + public static Iterator getHeaders(Message message, String name) throws JMSException { + String propertyName = headerToJmsProperty(name); + String value = message.getStringProperty(propertyName); + if (value != null) { + return Collections.singletonList(value).iterator(); + } + else { + return Collections.EMPTY_LIST.iterator(); + } + } + /** * Returns the delivery mode of the given URI. * diff --git a/support/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java b/support/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java index 65e1fc28..b7af52a3 100644 --- a/support/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java +++ b/support/src/test/java/org/springframework/ws/transport/jms/JmsMessageSenderIntegrationTest.java @@ -33,7 +33,6 @@ import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.SoapVersion; import org.springframework.ws.soap.saaj.SaajSoapMessage; import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; -import org.springframework.ws.transport.TransportConstants; import org.springframework.ws.transport.WebServiceConnection; public class JmsMessageSenderIntegrationTest extends AbstractDependencyInjectionSpringContextTests { @@ -80,8 +79,8 @@ public class JmsMessageSenderIntegrationTest extends AbstractDependencyInjection public Message createMessage(Session session) throws JMSException { BytesMessage response = session.createBytesMessage(); - response.setStringProperty(TransportConstants.HEADER_SOAP_ACTION, SOAP_ACTION); - response.setStringProperty(TransportConstants.HEADER_CONTENT_TYPE, + response.setStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION, SOAP_ACTION); + response.setStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE, SoapVersion.SOAP_11.getContentType()); response.writeBytes(buf); return response; @@ -117,8 +116,8 @@ public class JmsMessageSenderIntegrationTest extends AbstractDependencyInjection public Message createMessage(Session session) throws JMSException { TextMessage response = session.createTextMessage(); - response.setStringProperty(TransportConstants.HEADER_SOAP_ACTION, SOAP_ACTION); - response.setStringProperty(TransportConstants.HEADER_CONTENT_TYPE, + response.setStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION, SOAP_ACTION); + response.setStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE, SoapVersion.SOAP_11.getContentType()); response.setText(text); return response;