View Javadoc

1   /*
2    * $Id: JmsMessageUtilsTestCase.java 19230 2010-08-26 21:02:04Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.transport.jms;
12  
13  import static org.mockito.Matchers.anyObject;
14  import static org.mockito.Mockito.mock;
15  import static org.mockito.Mockito.times;
16  import static org.mockito.Mockito.verify;
17  import static org.mockito.Mockito.when;
18  
19  import org.mule.tck.AbstractMuleTestCase;
20  import org.mule.tck.testmodels.fruit.BananaFactory;
21  import org.mule.tck.testmodels.fruit.Orange;
22  
23  import java.io.IOException;
24  import java.io.NotSerializableException;
25  import java.io.ObjectInputStream;
26  import java.io.ObjectOutputStream;
27  import java.io.Serializable;
28  import java.util.ArrayList;
29  import java.util.Arrays;
30  import java.util.Enumeration;
31  import java.util.HashMap;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  
36  import javax.jms.BytesMessage;
37  import javax.jms.JMSException;
38  import javax.jms.MapMessage;
39  import javax.jms.Message;
40  import javax.jms.MessageFormatException;
41  import javax.jms.ObjectMessage;
42  import javax.jms.Session;
43  import javax.jms.StreamMessage;
44  import javax.jms.TextMessage;
45  
46  import org.apache.activemq.command.ActiveMQBytesMessage;
47  import org.apache.activemq.command.ActiveMQMapMessage;
48  import org.apache.activemq.command.ActiveMQObjectMessage;
49  import org.apache.activemq.command.ActiveMQStreamMessage;
50  import org.apache.activemq.command.ActiveMQTextMessage;
51  import org.apache.commons.collections.IteratorUtils;
52  import org.apache.commons.collections.iterators.IteratorEnumeration;
53  
54  public class JmsMessageUtilsTestCase extends AbstractMuleTestCase
55  {
56      public static final String ENCODING = "UTF-8";
57  
58      public void testHeaders()
59      {
60          // already valid headers are returned as-is, so we can assertSame
61          assertSame("identifier", JmsMessageUtils.encodeHeader("identifier"));
62          assertSame("_identifier", JmsMessageUtils.encodeHeader("_identifier"));
63          assertSame("identifier_", JmsMessageUtils.encodeHeader("identifier_"));
64          assertSame("ident_ifier", JmsMessageUtils.encodeHeader("ident_ifier"));
65  
66          assertEquals("_identifier", JmsMessageUtils.encodeHeader("-identifier"));
67          assertEquals("identifier_", JmsMessageUtils.encodeHeader("identifier-"));
68          assertEquals("ident_ifier", JmsMessageUtils.encodeHeader("ident-ifier"));
69          assertEquals("_ident_ifier_", JmsMessageUtils.encodeHeader("-ident_ifier-"));
70          assertEquals("_ident_ifier_", JmsMessageUtils.encodeHeader("-ident-ifier-"));
71      }
72  
73      public void testTextMessageNullContent() throws Exception
74      {
75          TextMessage mockMessage = mock(TextMessage.class);
76          when(mockMessage.getText()).thenReturn(null);
77  
78          byte[] result = JmsMessageUtils.toByteArray(mockMessage, JmsConstants.JMS_SPECIFICATION_102B,
79              ENCODING);
80          assertNotNull(result);
81          assertEquals("Should return an empty byte array.", 0, result.length);
82  
83          verify(mockMessage).getText();
84      }
85  
86      public void testByteMessageNullContentInJmsVersion_1_0_1() throws Exception
87      {
88          BytesMessage mockMessage1 = mock(BytesMessage.class);
89          when(mockMessage1.readBytes((byte[]) anyObject())).thenReturn(-1);
90  
91          byte[] result1 = JmsMessageUtils.toByteArray(mockMessage1, JmsConstants.JMS_SPECIFICATION_102B,
92              ENCODING);
93          assertNotNull(result1);
94          assertEquals("Should return an empty byte array.", 0, result1.length);
95          verify(mockMessage1).reset();
96      }
97  
98      public void testByteMessageNullContentInJmsVersion_1_1() throws Exception
99      {
100         BytesMessage mockMessage2 = mock(BytesMessage.class);
101         when(mockMessage2.getBodyLength()).thenReturn(Long.valueOf(0));
102 
103         byte[] result2 = JmsMessageUtils.toByteArray(mockMessage2, JmsConstants.JMS_SPECIFICATION_11,
104             ENCODING);
105         assertNotNull(result2);
106         assertEquals("Should return an empty byte array.", 0, result2.length);
107         verify(mockMessage2).reset();
108     }
109 
110     public void testStreamMessageSerialization() throws Exception
111     {
112         Session session = mock(Session.class);
113         when(session.createStreamMessage()).thenReturn(new ActiveMQStreamMessage());
114 
115         // Creates a test list with data
116         List data = new ArrayList();
117         data.add(Boolean.TRUE);
118         data.add(new Byte("1"));
119         data.add(new Short("2"));
120         data.add(new Character('3'));
121         data.add(new Integer("4"));
122         // can't write Longs: https://issues.apache.org/activemq/browse/AMQ-1965
123         // data.add(new Long("5"));
124         data.add(new Float("6"));
125         data.add(new Double("7"));
126         data.add(new String("8"));
127         data.add(null);
128         data.add(new byte[]{9, 10});        
129 
130         StreamMessage result = (StreamMessage) JmsMessageUtils.toMessage(data, session);
131 
132         // Resets so it's readable
133         result.reset();
134         assertEquals(Boolean.TRUE, result.readObject());
135         assertEquals(new Byte("1"), result.readObject());
136         assertEquals(new Short("2"), result.readObject());
137         assertEquals(new Character('3'), result.readObject());
138         assertEquals(new Integer("4"), result.readObject());
139         // can't write Longs: https://issues.apache.org/activemq/browse/AMQ-1965
140         // assertEquals(new Long("5"), result.readObject());
141         assertEquals(new Float("6"), result.readObject());
142         assertEquals(new Double("7"), result.readObject());
143         assertEquals(new String("8"), result.readObject());
144         assertNull(result.readObject());
145         assertTrue(Arrays.equals(new byte[]{9, 10}, (byte[]) result.readObject()));
146     }
147 
148     public void testStreamMessageSerializationWithInvalidType() throws Exception
149     {
150         Session session = null;
151         session = mock(Session.class);
152         when(session.createStreamMessage()).thenReturn(new ActiveMQStreamMessage());
153 
154         // Creates a test list with data
155         List data = new ArrayList();
156         data.add(new Object());
157 
158         try
159         {
160             JmsMessageUtils.toMessage(data, session);
161             fail("Should've failed with MessageFormatException");
162         }
163         catch (MessageFormatException e)
164         {
165             // expected
166         }
167     }
168 
169     public void testMapMessageWithNullValue() throws Exception
170     {
171         String[] keys = new String[]{"key", "null"};
172         Iterator<String> keyIterator = IteratorUtils.arrayIterator(keys);
173         Enumeration<String> keyEnumeration = new IteratorEnumeration(keyIterator);
174 
175         MapMessage mockMessage1 = mock(MapMessage.class);
176         when(mockMessage1.getMapNames()).thenReturn(keyEnumeration);
177         when(mockMessage1.getObject("key")).thenReturn("value");
178         when(mockMessage1.getObject("null")).thenReturn(null);
179 
180         Object result = JmsMessageUtils.toObject(mockMessage1, JmsConstants.JMS_SPECIFICATION_11, ENCODING);
181         assertNotNull(result);
182         assertTrue(result instanceof Map);
183         Map map = (Map) result;
184         assertEquals("value", map.get("key"));
185         assertNull(map.get("null"));
186     }
187 
188     /**
189      * Tests that is able to convert a Map which only contains simple values into a
190      * MapMessage.
191      */
192     public void testConvertsValidMapWithSimpleValuesToMapMessage() throws JMSException
193     {
194         Session session = mock(Session.class);
195         when(session.createMapMessage()).thenReturn(new ActiveMQMapMessage());
196 
197         // Creates a test Map with data
198         Map data = new HashMap();
199         data.put("value1", new Float(4));
200         data.put("value2", new byte[]{1, 2, 3});
201         data.put("value3", "value3");
202         data.put("value4", new Double(67.9));
203         data.put("value5", true);
204         data.put("value6", null);
205 
206         Message message = JmsMessageUtils.toMessage(data, session);
207         assertTrue(message instanceof MapMessage);
208 
209         MapMessage mapMessage = (MapMessage) message;
210         assertEquals(new Float(4), mapMessage.getFloat("value1"));
211         assertTrue(Arrays.equals(new byte[]{1, 2, 3}, mapMessage.getBytes("value2")));
212         assertEquals("value3", mapMessage.getString("value3"));
213         assertEquals(new Double(67.9), mapMessage.getDouble("value4"));
214         assertTrue(mapMessage.getBoolean("value5"));
215         assertNull(mapMessage.getObject("value6"));
216     }
217 
218     /**
219      * Tests that is able to convert a Map which contains a serializable value into
220      * an ObjectMessage.
221      */
222     public void testConvertsMapWithSerializableValueIntoObjectMessage() throws Exception
223     {
224         Session session = mock(Session.class);
225         when(session.createObjectMessage()).thenReturn(new ActiveMQObjectMessage());
226 
227         // Creates a test Map containing a serializable object
228         Map data = new HashMap();
229         data.put("orange", new Orange());
230 
231         Message message = JmsMessageUtils.toMessage(data, session);
232         assertTrue(message instanceof ObjectMessage);
233 
234         ObjectMessage objectMessage = (ObjectMessage) message;
235         Map values = (Map) objectMessage.getObject();
236         assertEquals(new Orange(), values.get("orange"));
237     }
238 
239     /**
240      * Tests that trying to convert a Map which contains a non valid non serializable
241      * value throws an exception.
242      */
243     public void testConvertingMapIncludingNotValidNotSerializableValueThrowsException() throws Exception
244     {
245         Session session = mock(Session.class);
246         when(session.createObjectMessage()).thenReturn(new ActiveMQObjectMessage());
247 
248         // Creates a test Map containing a non serializable object
249         Map data = new HashMap();
250         data.put("notserializable", new BananaFactory());
251 
252         try
253         {
254             JmsMessageUtils.toMessage(data, session);
255             fail("Attempt to send a non-serializable object in a map should fail");
256         }
257         catch (Exception expected)
258         {
259             assertTrue(expected.getCause() instanceof NotSerializableException);
260         }
261     }
262 
263     public void testConvertingStringToTextMessage() throws JMSException
264     {
265         String text = "Hello world";
266 
267         Session session = mock(Session.class);
268         TextMessage textMessage = new ActiveMQTextMessage();
269         textMessage.setText(text);
270         when(session.createTextMessage(text)).thenReturn(textMessage);
271 
272         TextMessage message = (TextMessage) JmsMessageUtils.toMessage(text, session);
273         assertEquals(textMessage, message);
274         verify(session, times(1)).createTextMessage(text);
275     }
276 
277     public void testConvertingByteArrayToBytesMessage() throws JMSException
278     {
279         Session session = mock(Session.class);
280         when(session.createBytesMessage()).thenReturn(new ActiveMQBytesMessage());
281 
282         byte[] bytesArray = new byte[]{1, 2};
283         BytesMessage message = (BytesMessage) JmsMessageUtils.toMessage(bytesArray, session);
284 
285         // Makes the message readable
286         message.reset();
287         byte[] bytesArrayResult = new byte[(int) message.getBodyLength()];
288         int length = message.readBytes(bytesArrayResult);
289         assertEquals(2, length);
290         assertEquals(bytesArray[0], bytesArrayResult[0]);
291         assertEquals(bytesArray[1], bytesArrayResult[1]);
292     }
293 
294     public void testConvertingSerializableToObjectMessage() throws JMSException
295     {
296         Session session = mock(Session.class);
297         when(session.createObjectMessage()).thenReturn(new ActiveMQObjectMessage());
298 
299         final String OBJECT_ID = "id1234";
300         ObjectMessage message = (ObjectMessage) JmsMessageUtils.toMessage(new SerializableObject(OBJECT_ID),
301             session);
302 
303         Serializable serializable = message.getObject();
304         assertTrue(serializable instanceof SerializableObject);
305         assertEquals(OBJECT_ID, ((SerializableObject) serializable).id);
306     }
307 
308     public void testConvertingMessageToMessageReturnsSameObject() throws JMSException
309     {
310         Message original = mock(Message.class);
311         Message result = JmsMessageUtils.toMessage(original, null);
312         assertSame(original, result);
313     }
314 
315     public void testConvertingInvalidTypeThrowsException() throws JMSException
316     {
317         try
318         {
319             JmsMessageUtils.toMessage(new Object(), null);
320             fail("Able to convert to message an invalid type");
321         }
322         catch (JMSException e)
323         {
324             // Expected
325         }
326     }
327 
328     /**
329      * Dummy serializable class used to test that conversion from Map to JmsMessage
330      * is OK when it includes non primitive serializable values.
331      */
332     private static class SerializableObject implements Serializable
333     {
334         private static final long serialVersionUID = -4865136673252075014L;
335         private String id;
336 
337         public SerializableObject(String id)
338         {
339             this.id = id;
340         }
341 
342         private void readObject(ObjectInputStream aInputStream) throws ClassNotFoundException, IOException
343         {
344             aInputStream.defaultReadObject();
345         }
346 
347         private void writeObject(ObjectOutputStream aOutputStream) throws IOException
348         {
349             aOutputStream.defaultWriteObject();
350         }
351     }
352 }