1   /*
2    * $Id: JmsTestUtils.java 7963 2007-08-21 08:53:15Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.test.integration.providers.jms.tools;
12  
13  import org.mule.util.ClassUtils;
14  import org.mule.util.FileUtils;
15  import org.mule.util.IOUtils;
16  
17  import java.io.File;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.util.Properties;
21  
22  import javax.jms.Connection;
23  import javax.jms.JMSException;
24  import javax.jms.Message;
25  import javax.jms.Queue;
26  import javax.jms.QueueConnection;
27  import javax.jms.QueueConnectionFactory;
28  import javax.jms.QueueReceiver;
29  import javax.jms.QueueSender;
30  import javax.jms.QueueSession;
31  import javax.jms.Session;
32  import javax.jms.TextMessage;
33  import javax.jms.Topic;
34  import javax.jms.TopicConnection;
35  import javax.jms.TopicConnectionFactory;
36  import javax.jms.TopicPublisher;
37  import javax.jms.TopicSession;
38  import javax.jms.TopicSubscriber;
39  import javax.jms.XAConnection;
40  import javax.jms.XAQueueConnection;
41  import javax.jms.XAQueueConnectionFactory;
42  import javax.jms.XASession;
43  import javax.jms.XATopicConnection;
44  import javax.jms.XATopicConnectionFactory;
45  import javax.naming.Context;
46  import javax.naming.InitialContext;
47  import javax.naming.NamingException;
48  import javax.naming.Reference;
49  
50  import org.apache.commons.logging.Log;
51  import org.apache.commons.logging.LogFactory;
52  
53  /**
54   * <code>JmsTestUtils</code> contains some helper code necessary to test
55   * interaction with different JMS providers.
56   */
57  public class JmsTestUtils
58  {
59      private static final Log logger = LogFactory.getLog(JmsTestUtils.class);
60  
61      public static final String UBERMQ_JMS_PROPERTIES = "ubermq-jndi-connection.properties";
62      public static final String OPEN_JMS_PROPERTIES = "openjms-jndi-connection.properties";
63      public static final String JORAM_JMS_PROPERTIES = "joram-jndi-connection.properties";
64      public static final String SPIRIT_WAVE_JMS_PROPERTIES = "spiritwave-jndi-connection.properties";
65      public static final String ACTIVE_MQ_JMS_PROPERTIES = "activemq-jndi-connection.properties";
66  
67      public static final String JMS_PROPERTIES = "mule-jms-provider.properties";
68  
69      public static final String JMS_PROPERTIES_PROPERTY = "org.mule.test.jms.properties";
70      public static final String DEFAULT_JNDI_CONECTION_NAME_PROPERTY = "connectionFactoryJNDIName";
71      public static final String JNDI_QUEUE_CONECTION_NAME_PROPERTY = "QueueConnectionFactoryJNDIName";
72      public static final String JNDI_TOPIC_CONECTION_NAME_PROPERTY = "TopicConnectionFactoryJNDIName";
73      public static final String JNDI_XAQUEUE_CONECTION_NAME_PROPERTY = "XAQueueConnectionFactoryJNDIName";
74      public static final String JNDI_XATOPIC_CONECTION_NAME_PROPERTY = "XATopicConnectionFactoryJNDIName";
75  
76      public static Properties getJmsProperties() throws IOException
77      {
78          InputStream is = IOUtils.getResourceAsStream(JMS_PROPERTIES, JmsTestUtils.class);
79  
80          String jmsProps = OPEN_JMS_PROPERTIES;
81          if (is != null)
82          {
83              Properties p = new Properties();
84              p.load(is);
85              jmsProps = p.getProperty("jms.provider.properties", OPEN_JMS_PROPERTIES);
86              is.close();
87          }
88          return getJmsProperties(jmsProps);
89      }
90  
91      public static Properties getJmsProperties(String propertyFile) throws IOException
92      {
93          InputStream is = IOUtils.getResourceAsStream(propertyFile, JmsTestUtils.class);
94  
95          Properties p = new Properties();
96          p.load(is);
97          is.close();
98  
99          fixProviderUrl(p);
100         return p;
101     }
102 
103     public static void fixProviderUrl(Properties props) throws IOException
104     {
105         String providerUrl = props.getProperty(Context.PROVIDER_URL);
106         if (providerUrl != null && !providerUrl.startsWith("file:") && providerUrl.indexOf(':') < 0)
107         {
108             providerUrl = "file:" + File.separator
109                           + FileUtils.getResourcePath(providerUrl, JmsTestUtils.class);
110             logger.debug("Setting provider url to: " + providerUrl);
111             props.setProperty(Context.PROVIDER_URL, providerUrl);
112         }
113     }
114 
115     public static QueueConnection getQueueConnection() throws IOException, NamingException, JMSException
116     {
117         return getQueueConnection(getJmsProperties());
118     }
119 
120     public static XAQueueConnection getXAQueueConnection() throws IOException, NamingException, JMSException
121     {
122         return getXAQueueConnection(getJmsProperties());
123     }
124 
125     public static XAQueueConnection getXAQueueConnection(Properties props)
126         throws IOException, NamingException, JMSException
127     {
128         String cnnFactoryName = props.getProperty(JNDI_XAQUEUE_CONECTION_NAME_PROPERTY);
129         if (cnnFactoryName == null)
130         {
131             throw new IOException("You must set the property " + JNDI_XAQUEUE_CONECTION_NAME_PROPERTY
132                                   + "in the JNDI property file");
133         }
134         Context ctx = new InitialContext(props);
135         XAQueueConnectionFactory qcf = (XAQueueConnectionFactory)lookupObject(ctx, cnnFactoryName);
136         XAQueueConnection cnn;
137         String username = (String)props.get("username");
138 
139         if (username != null)
140         {
141             String password = (String)props.get("password");
142             cnn = qcf.createXAQueueConnection(username, password);
143         }
144         else
145         {
146             cnn = qcf.createXAQueueConnection();
147         }
148         cnn.start();
149         return cnn;
150     }
151 
152     public static QueueConnection getQueueConnection(Properties props)
153         throws IOException, NamingException, JMSException
154     {
155         fixProviderUrl(props);
156         String cnnFactoryName = props.getProperty(DEFAULT_JNDI_CONECTION_NAME_PROPERTY);
157         if (cnnFactoryName == null)
158         {
159             throw new IOException("You must set the property " + DEFAULT_JNDI_CONECTION_NAME_PROPERTY
160                                   + "in the JNDI property file");
161         }
162         Context ctx = new InitialContext(props);
163         Object obj = lookupObject(ctx, cnnFactoryName);
164         QueueConnectionFactory qcf = (QueueConnectionFactory)obj;
165         QueueConnection cnn;
166         String username = (String)props.get("username");
167 
168         if (username != null)
169         {
170             String password = (String)props.get("password");
171             cnn = qcf.createQueueConnection(username, password);
172         }
173         else
174         {
175             cnn = qcf.createQueueConnection();
176         }
177         cnn.start();
178         return cnn;
179     }
180 
181     public static TopicConnection getTopicConnection() throws IOException, NamingException, JMSException
182     {
183         return getTopicConnection(getJmsProperties());
184     }
185 
186     public static TopicConnection getTopicConnection(Properties props)
187         throws IOException, NamingException, JMSException
188     {
189         fixProviderUrl(props);
190         String cnnFactoryName = props.getProperty(JNDI_TOPIC_CONECTION_NAME_PROPERTY);
191         if (cnnFactoryName == null)
192         {
193             throw new IOException("You must set the property " + DEFAULT_JNDI_CONECTION_NAME_PROPERTY
194                                   + "in the JNDI property file");
195         }
196         Context ctx = new InitialContext(props);
197 
198         TopicConnectionFactory tcf = (TopicConnectionFactory)lookupObject(ctx, cnnFactoryName);
199         TopicConnection cnn;
200         String username = (String)props.get("username");
201 
202         if (username != null)
203         {
204             String password = (String)props.get("password");
205             cnn = tcf.createTopicConnection(username, password);
206         }
207         else
208         {
209             cnn = tcf.createTopicConnection();
210         }
211         cnn.start();
212         return cnn;
213     }
214 
215     public static Object lookupObject(Context context, String reference) throws NamingException
216     {
217         Object ref = context.lookup(reference);
218         if (ref instanceof Reference)
219         {
220             String className = ((Reference)ref).getClassName();
221             try
222             {
223                 ref = ClassUtils.loadClass(className, JmsTestUtils.class).newInstance();
224             }
225             catch (Exception e)
226             {
227                 throw new NamingException("Failed to instanciate class: " + className + ". Exception was: "
228                                           + e.toString());
229             }
230         }
231         return ref;
232     }
233 
234     public static XATopicConnection getXATopicConnection() throws IOException, NamingException, JMSException
235     {
236         Properties props = getJmsProperties();
237         String cnnFactoryName = props.getProperty(JNDI_XATOPIC_CONECTION_NAME_PROPERTY);
238         if (cnnFactoryName == null)
239         {
240             throw new IOException("You must set the property " + JNDI_XAQUEUE_CONECTION_NAME_PROPERTY
241                                   + "in the JNDI property file");
242         }
243         Context ctx = new InitialContext(props);
244         XATopicConnectionFactory tcf = (XATopicConnectionFactory)lookupObject(ctx, cnnFactoryName);
245         XATopicConnection cnn;
246         String username = (String)props.get("username");
247 
248         if (username != null)
249         {
250             String password = (String)props.get("password");
251             cnn = tcf.createXATopicConnection(username, password);
252         }
253         else
254         {
255             cnn = tcf.createXATopicConnection();
256         }
257         cnn.start();
258         return cnn;
259     }
260 
261     public static Session getSession(Connection cnn) throws JMSException
262     {
263         Session session;
264         if (cnn instanceof QueueConnection)
265         {
266             session = ((QueueConnection)cnn).createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
267         }
268         else
269         {
270             session = ((TopicConnection)cnn).createTopicSession(false, QueueSession.AUTO_ACKNOWLEDGE);
271         }
272         return session;
273     }
274 
275     public static XASession getXASession(XAConnection cnn) throws JMSException
276     {
277         XASession session;
278         if (cnn instanceof XAQueueConnection)
279         {
280             session = ((XAQueueConnection)cnn).createXAQueueSession();
281         }
282         else
283         {
284             session = ((XATopicConnection)cnn).createXATopicSession();
285         }
286         return session;
287     }
288 
289     public static void drainQueue(QueueConnection cnn, String queue) throws Exception
290     {
291         QueueSession session = cnn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
292         Queue q = session.createQueue(queue);
293         QueueReceiver receiver = session.createReceiver(q);
294         // Add a delay so that activeMQ can fetch messages from the broker
295         // Thread.sleep(5000);
296         Message msg = null;
297         while ((msg = receiver.receive(1000)) != null)
298         {
299             logger.debug("Removing message: " + msg);
300             msg.acknowledge();
301         }
302         receiver.close();
303         session.close();
304     }
305 
306     public static void drainTopic(TopicConnection cnn, String topic) throws Exception
307     {
308         TopicSession session = cnn.createTopicSession(false, Session.DUPS_OK_ACKNOWLEDGE);
309         Topic t = session.createTopic(topic);
310 
311         TopicSubscriber subscriber = session.createSubscriber(t);
312         Message msg = subscriber.receiveNoWait();
313         while (msg != null)
314         {
315             try
316             {
317                 msg.acknowledge();
318             }
319             catch (JMSException e)
320             {
321                 // TODO shouldn't we bail out here? something is obviosuly wrong
322             }
323             msg = subscriber.receiveNoWait();
324         }
325         subscriber.close();
326         session.close();
327     }
328 
329     public static TextMessage getTextMessage(Connection cnn, String message) throws Exception
330     {
331         return getSession(cnn).createTextMessage(message);
332     }
333 
334     public static void queueSend(QueueConnection cnn,
335                                  String queueName,
336                                  String payload,
337                                  boolean transacted,
338                                  int ack,
339                                  String replyTo) throws JMSException
340     {
341         QueueSession session = cnn.createQueueSession(transacted, ack);
342         Queue queue = session.createQueue(queueName);
343         QueueSender sender = session.createSender(queue);
344         TextMessage msg = session.createTextMessage();
345         msg.setText(payload);
346         msg.setJMSDeliveryMode(ack);
347         if (replyTo != null)
348         {
349             msg.setJMSReplyTo(session.createQueue(replyTo));
350         }
351 
352         sender.send(msg);
353         sender.close();
354         session.close();
355     }
356 
357     public static void topicPublish(TopicConnection cnn,
358                                     String topicName,
359                                     String payload,
360                                     boolean transacted,
361                                     int ack) throws JMSException
362     {
363         topicPublish(cnn, topicName, payload, transacted, ack, null);
364     }
365 
366     public static void topicPublish(TopicConnection cnn,
367                                     String topicName,
368                                     String payload,
369                                     boolean transacted,
370                                     int ack,
371                                     String replyTo) throws JMSException
372     {
373         TopicSession session = cnn.createTopicSession(transacted, ack);
374         Topic topic = session.createTopic(topicName);
375         TopicPublisher publisher = session.createPublisher(topic);
376         TextMessage msg = session.createTextMessage();
377         msg.setText(payload);
378         msg.setJMSDeliveryMode(ack);
379         if (replyTo != null)
380         {
381             msg.setJMSReplyTo(session.createTopic(replyTo));
382         }
383         publisher.publish(msg);
384         publisher.close();
385         session.close();
386     }
387 
388     public static Message queueReceiver(QueueConnection cnn, String queueName, long timeout)
389         throws JMSException
390     {
391         QueueSession session = cnn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
392         Queue queue = session.createQueue(queueName);
393         QueueReceiver receiver = session.createReceiver(queue);
394         Message msg = receiver.receive(timeout);
395         if (msg != null)
396         {
397             msg.acknowledge();
398         }
399         receiver.close();
400         session.close();
401         return msg;
402     }
403 
404     public static Message topicSubscribe(TopicConnection cnn, String topicName, long timeout)
405         throws JMSException
406     {
407         TopicSubscriber receiver = getTopicSubscriber(cnn, topicName);
408         Message msg = receiver.receive(timeout);
409         if (msg != null)
410         {
411             msg.acknowledge();
412         }
413         receiver.close();
414         return msg;
415     }
416 
417     public static TopicSubscriber getTopicSubscriber(TopicConnection cnn, String topicName)
418         throws JMSException
419     {
420         TopicSession session = cnn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
421         Topic topic = session.createTopic(topicName);
422         TopicSubscriber receiver = session.createSubscriber(topic);
423         return receiver;
424     }
425 
426     public static QueueReceiver getQueueReceiver(QueueConnection cnn, String queueName) throws JMSException
427     {
428         QueueSession session = cnn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
429         Queue queue = session.createQueue(queueName);
430         QueueReceiver receiver = session.createReceiver(queue);
431         return receiver;
432     }
433 }