View Javadoc

1   /*
2    * Copyright 2007 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.transport.jms.support;
18  
19  import java.net.URI;
20  import java.net.URISyntaxException;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.Enumeration;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.regex.Matcher;
27  import java.util.regex.Pattern;
28  import javax.jms.DeliveryMode;
29  import javax.jms.Destination;
30  import javax.jms.JMSException;
31  import javax.jms.Message;
32  import javax.jms.Queue;
33  import javax.jms.Topic;
34  
35  import org.springframework.ws.transport.jms.JmsTransportConstants;
36  
37  /**
38   * Collection of utility methods to work with JMS transports. Includes methods to retrieve JMS properties from an {@link
39   * URI}.
40   *
41   * @author Arjen Poutsma
42   * @since 1.5.0
43   */
44  public abstract class JmsTransportUtils {
45  
46      private static final String[] CONVERSION_TABLE = new String[]{JmsTransportConstants.HEADER_CONTENT_TYPE,
47              JmsTransportConstants.PROPERTY_CONTENT_TYPE, JmsTransportConstants.HEADER_CONTENT_LENGTH,
48              JmsTransportConstants.PROPERTY_CONTENT_LENGTH, JmsTransportConstants.HEADER_SOAP_ACTION,
49              JmsTransportConstants.PROPERTY_SOAP_ACTION};
50  
51      private static final Pattern DESTINATION_NAME_PATTERN = Pattern.compile("^([^\\?]+)");
52  
53      private static final Pattern DELIVERY_MODE_PATTERN = Pattern.compile("deliveryMode=(PERSISTENT|NON_PERSISTENT)");
54  
55      private static final Pattern MESSAGE_TYPE_PATTERN = Pattern.compile("messageType=(BYTES_MESSAGE|TEXT_MESSAGE)");
56  
57      private static final Pattern TIME_TO_LIVE_PATTERN = Pattern.compile("timeToLive=(\\d+)");
58  
59      private static final Pattern PRIORITY_PATTERN = Pattern.compile("priority=(\\d)");
60  
61      private static final Pattern REPLY_TO_NAME_PATTERN = Pattern.compile("replyToName=([^&]+)");
62  
63      private JmsTransportUtils() {
64      }
65  
66      /**
67       * Converts the given transport header to a JMS property name. Returns the given header name if no match is found.
68       *
69       * @param headerName the header name to transform
70       * @return the JMS property name
71       */
72      public static String headerToJmsProperty(String headerName) {
73          for (int i = 0; i < CONVERSION_TABLE.length; i = i + 2) {
74              if (CONVERSION_TABLE[i].equals(headerName)) {
75                  return CONVERSION_TABLE[i + 1];
76              }
77          }
78          return headerName;
79      }
80  
81      /**
82       * Converts the given JMS property name to a transport header name. Returns the given property name if no match is
83       * found.
84       *
85       * @param propertyName the JMS property name to transform
86       * @return the transport header name
87       */
88      public static String jmsPropertyToHeader(String propertyName) {
89          for (int i = 1; i < CONVERSION_TABLE.length; i = i + 2) {
90              if (CONVERSION_TABLE[i].equals(propertyName)) {
91                  return CONVERSION_TABLE[i - 1];
92              }
93          }
94          return propertyName;
95      }
96  
97      /**
98       * Converts the given JMS destination into a <code>jms</code> URI.
99       *
100      * @param destination the destination
101      * @return a jms URI
102      */
103     public static URI toUri(Destination destination) throws URISyntaxException, JMSException {
104         String destinationName;
105         if (destination instanceof Queue) {
106             destinationName = ((Queue) destination).getQueueName();
107         }
108         else if (destination instanceof Topic) {
109             Topic topic = (Topic) destination;
110             destinationName = topic.getTopicName();
111         }
112         else {
113             throw new IllegalArgumentException("Destination [ " + destination + "] is neither Queue nor Topic");
114         }
115         return new URI(JmsTransportConstants.JMS_URI_SCHEME, destinationName, null);
116     }
117 
118     /** Returns the destination name of the given URI. */
119     public static String getDestinationName(URI uri) {
120         return getStringParameter(DESTINATION_NAME_PATTERN, uri);
121     }
122 
123     /** Adds the given header to the specified message. */
124     public static void addHeader(Message message, String name, String value) throws JMSException {
125         String propertyName = JmsTransportUtils.headerToJmsProperty(name);
126         message.setStringProperty(propertyName, value);
127     }
128 
129     /**
130      * Returns an iterator over all header names in the given message. Delegates to {@link
131      * #jmsPropertyToHeader(String)}.
132      */
133     public static Iterator getHeaderNames(Message message) throws JMSException {
134         Enumeration properties = message.getPropertyNames();
135         List results = new ArrayList();
136         while (properties.hasMoreElements()) {
137             String property = (String) properties.nextElement();
138             if (property.startsWith(JmsTransportConstants.PROPERTY_PREFIX)) {
139                 String header = jmsPropertyToHeader(property);
140                 results.add(header);
141             }
142         }
143         return results.iterator();
144     }
145 
146     /**
147      * Returns an iterator over all the header values of the given message and header name. Delegates to {@link
148      * #headerToJmsProperty(String)}.
149      */
150     public static Iterator getHeaders(Message message, String name) throws JMSException {
151         String propertyName = headerToJmsProperty(name);
152         String value = message.getStringProperty(propertyName);
153         if (value != null) {
154             return Collections.singletonList(value).iterator();
155         }
156         else {
157             return Collections.EMPTY_LIST.iterator();
158         }
159     }
160 
161     /**
162      * Returns the delivery mode of the given URI.
163      *
164      * @see DeliveryMode#NON_PERSISTENT
165      * @see DeliveryMode#PERSISTENT
166      * @see Message#DEFAULT_DELIVERY_MODE
167      */
168     public static int getDeliveryMode(URI uri) {
169         String deliveryMode = getStringParameter(DELIVERY_MODE_PATTERN, uri);
170         if ("NON_PERSISTENT".equals(deliveryMode)) {
171             return DeliveryMode.NON_PERSISTENT;
172         }
173         else if ("PERSISTENT".equals(deliveryMode)) {
174             return DeliveryMode.PERSISTENT;
175         }
176         else {
177             return Message.DEFAULT_DELIVERY_MODE;
178         }
179     }
180 
181     /**
182      * Returns the message type of the given URI. Defaults to {@link JmsTransportConstants#BYTES_MESSAGE_TYPE}.
183      *
184      * @see JmsTransportConstants#BYTES_MESSAGE_TYPE
185      * @see JmsTransportConstants#TEXT_MESSAGE_TYPE
186      */
187     public static int getMessageType(URI uri) {
188         String deliveryMode = getStringParameter(MESSAGE_TYPE_PATTERN, uri);
189         if ("TEXT_MESSAGE".equals(deliveryMode)) {
190             return JmsTransportConstants.TEXT_MESSAGE_TYPE;
191         }
192         else {
193             return JmsTransportConstants.BYTES_MESSAGE_TYPE;
194         }
195     }
196 
197     /**
198      * Returns the lifetime, in milliseconds, of the given URI.
199      *
200      * @see Message#DEFAULT_TIME_TO_LIVE
201      */
202     public static long getTimeToLive(URI uri) {
203         return getLongParameter(TIME_TO_LIVE_PATTERN, uri, Message.DEFAULT_TIME_TO_LIVE);
204     }
205 
206     /**
207      * Returns the priority of the given URI.
208      *
209      * @see Message#DEFAULT_PRIORITY
210      */
211     public static int getPriority(URI uri) {
212         return getIntParameter(PRIORITY_PATTERN, uri, Message.DEFAULT_PRIORITY);
213     }
214 
215     /**
216      * Returns the reply-to name of the given URI.
217      *
218      * @see Message#setJMSReplyTo(Destination)
219      */
220     public static String getReplyToName(URI uri) {
221         return getStringParameter(REPLY_TO_NAME_PATTERN, uri);
222     }
223 
224     private static String getStringParameter(Pattern pattern, URI uri) {
225         Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
226         if (matcher.find() && matcher.groupCount() == 1) {
227             return matcher.group(1);
228         }
229         return null;
230     }
231 
232     private static int getIntParameter(Pattern pattern, URI uri, int defaultValue) {
233         Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
234         if (matcher.find() && matcher.groupCount() == 1) {
235             try {
236                 return Integer.parseInt(matcher.group(1));
237             }
238             catch (NumberFormatException ex) {
239                 // fall through to default value
240             }
241         }
242         return defaultValue;
243     }
244 
245     private static long getLongParameter(Pattern pattern, URI uri, long defaultValue) {
246         Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
247         if (matcher.find() && matcher.groupCount() == 1) {
248             try {
249                 return Long.parseLong(matcher.group(1));
250             }
251             catch (NumberFormatException ex) {
252                 // fall through to default value
253             }
254         }
255         return defaultValue;
256     }
257 
258 }