View Javadoc

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