View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.MuleEvent;
11  import org.mule.api.MuleMessage;
12  import org.mule.api.MuleMessageCollection;
13  import org.mule.api.ThreadSafeAccess;
14  import org.mule.api.transformer.DataType;
15  import org.mule.api.transformer.TransformerException;
16  import org.mule.transformer.types.DataTypeFactory;
17  
18  import java.util.ArrayList;
19  import java.util.Iterator;
20  import java.util.List;
21  
22  import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
23  
24  /**
25   * A {@link org.mule.api.MuleMessage} type that manages a collection of MuleMessage Objects.
26   * Typically this type of message is only used when users explicitly want to work with aggregated or re-sequenced
27   * collections of messages.
28   *
29   *  Note that the {@link #getPayload()} for this message will return a {@link java.util.List} of payload objects for
30   * each of the Mule messages stored in this collection.
31   *
32   * Calling {@link org.mule.api.MuleMessage#getPayload(Class)} will attempt to transform all payloads and return a {@link java.util.List}.
33   *
34   * The methods {@link org.mule.api.MuleMessage#getPayloadAsString()} and {@link org.mule.api.MuleMessage#getPayloadAsBytes()} are unsupported, instead users should
35   * call {@link org.mule.api.MuleMessage#getPayload(Class)} and pass in the return type <code>byte[].class</code> or <code>String.class</code>.
36   */
37  public class DefaultMessageCollection extends DefaultMuleMessage implements MuleMessageCollection
38  {
39      private List messageList = new CopyOnWriteArrayList();
40  
41      private boolean invalidatedPayload;
42  
43      public DefaultMessageCollection(MuleContext muleContext)
44      {
45          //This will be a collection of payloads
46          super(new CopyOnWriteArrayList(), muleContext);
47          invalidatedPayload = false;
48      }
49  
50      /**
51       * Performs a shallow copy
52       * @param msg
53       * @param muleContext
54       */
55      public DefaultMessageCollection(DefaultMessageCollection msg, MuleContext muleContext)
56      {
57          this(muleContext);
58          if (!msg.invalidatedPayload)
59          {
60              for (int i = 0; i < msg.getMessagesAsArray().length; i++)
61              {
62                  addMessage(msg.getMessagesAsArray()[i]);
63              }
64          }
65          else
66          {
67              invalidatedPayload = true;
68          }
69  
70      }
71  
72      protected void checkValidPayload()
73      {
74          if (invalidatedPayload)
75          {
76              throw new IllegalStateException("Payload was invalidated calling setPayload and the message is not collection anymore.");
77          }
78      }
79  
80      public void addMessage(MuleMessage message)
81      {
82          checkValidPayload();
83          getMessageList().add(message);
84          getPayloadList().add(message.getPayload());
85      }
86  
87      public MuleMessage[] getMessagesAsArray()
88      {
89          checkValidPayload();
90          List list = getMessageList();
91          MuleMessage[] messages = new MuleMessage[list.size()];
92          messages = (MuleMessage[])list.toArray(messages);
93          return messages;
94      }
95  
96      public Object[] getPayloadsAsArray()
97      {
98          checkValidPayload();
99          List list = getPayloadList();
100         Object[] payloads = new Object[list.size()];
101         payloads = list.toArray(payloads);
102         return payloads;
103     }
104 
105     public void removedMessage(MuleMessage message)
106     {
107         checkValidPayload();
108         getMessageList().remove(message);
109         getPayloadList().remove(message.getPayload());
110     }
111 
112     public void addMessage(MuleMessage message, int index)
113     {
114         checkValidPayload();
115         getMessageList().add(index, message);
116         getPayloadList().add(index, message.getPayload());
117     }
118 
119     public void addMessages(MuleEvent[] events)
120     {
121         checkValidPayload();
122         for (int i = 0; i < events.length; i++)
123         {
124             MuleEvent event = events[i];
125             addMessage(event.getMessage());
126         }
127     }
128 
129     public void addMessages(List messages)
130     {
131         checkValidPayload();
132         for (Iterator iterator = messages.iterator(); iterator.hasNext(); )
133         {
134             MuleMessage message = (MuleMessage) iterator.next();
135             addMessage(message);
136         }
137     }
138 
139     public void addMessages(MuleMessage[] messages)
140     {
141         checkValidPayload();
142         for (int i = 0; i < messages.length; i++)
143         {
144             addMessage(messages[i]);
145         }
146     }
147 
148     public MuleMessage getMessage(int index)
149     {
150         checkValidPayload();
151         return (MuleMessage) getMessageList().get(index);
152     }
153 
154     protected List getMessageList()
155     {
156         checkValidPayload();
157         return messageList;
158     }
159 
160     protected List getPayloadList()
161     {
162         checkValidPayload();
163         return (List) getPayload();
164     }
165 
166     @Override
167     public synchronized void setPayload(Object payload)
168     {
169         if (this.getPayload() == payload)
170         {
171             return;
172         }
173         else
174         {
175             super.setPayload(payload);
176             invalidatedPayload = true;
177         }
178     }
179 
180     /**
181      * Applies the {@link org.mule.api.MuleMessage#getPayload(Class)} call to every message in the collection and returns a
182      * {@link java.util.List} of results.
183      *
184      * {@inheritDoc}
185      */
186     @Override
187     public Object getPayload(Class outputType) throws TransformerException
188     {
189         if (invalidatedPayload)
190         {
191             return super.getPayload(outputType);
192         }
193         else
194         {
195             DataType outputDataType = DataTypeFactory.create(outputType);
196             List results = new ArrayList(getMessageList().size());
197             for (Iterator iterator = getMessageList().iterator(); iterator.hasNext(); )
198             {
199                 MuleMessage message = (MuleMessage) iterator.next();
200                 results.add(message.getPayload(outputDataType));
201             }
202             return results;
203         }
204     }
205 
206     public int size()
207     {
208         checkValidPayload();
209         return getMessageList().size();
210     }
211 
212     /**
213      * {@inheritDoc}
214      */
215     @Override
216     public byte[] getPayloadAsBytes() throws Exception
217     {
218         if (invalidatedPayload)
219         {
220             return super.getPayloadAsBytes();
221         }
222         else
223         {
224             throw new UnsupportedOperationException("getPayloadAsBytes(), use getPayload(DataType.BYTE_ARRAY_DATA_TYPE)");
225         }
226     }
227 
228     /**
229      * {@inheritDoc}
230      */
231     @Override
232     public String getPayloadAsString(String encoding) throws Exception
233     {
234         if (invalidatedPayload)
235         {
236             return super.getPayloadAsString(encoding);
237         }
238         else
239         {
240             throw new UnsupportedOperationException("getPayloadAsString(), use getPayload(DataType.STRING_DATA_TYPE)");
241         }
242     }
243 
244     /**
245      * {@inheritDoc}
246      */
247     @Override
248     public String getPayloadForLogging(String encoding)
249     {
250         if (invalidatedPayload)
251         {
252             return super.getPayloadForLogging(encoding);
253         }
254         else
255         {
256             return "[This is a message collection]";
257         }
258     }
259 
260     /**
261      * {@inheritDoc}
262      */
263     @Override
264     public String getPayloadForLogging()
265     {
266         if (invalidatedPayload)
267         {
268             return super.getPayloadForLogging();
269         }
270         else
271         {
272             return "[This is a message collection]";
273         }
274     }
275 
276     /**
277      * We need to overload this if we find we want to make this class available to users, but the copy will be expensive;
278      */
279     public ThreadSafeAccess newThreadCopy()
280     {
281         checkValidPayload();
282         return new DefaultMessageCollection(this, muleContext);
283     }
284 
285     /**
286      * {@inheritDoc}
287      */
288     @Override
289     public MuleMessage createInboundMessage() throws Exception
290     {
291         if (invalidatedPayload)
292         {
293             return super.createInboundMessage();
294         }
295         else
296         {
297             DefaultMessageCollection newMessage = new DefaultMessageCollection(getMuleContext());
298             MuleMessage[] messages = getMessagesAsArray();
299             for (MuleMessage message : messages)
300             {
301                 newMessage.addMessage(message.createInboundMessage());
302             }
303             copyToInbound(newMessage);
304 
305             return newMessage;
306         }
307     }
308 
309     public boolean isInvalidatedPayload()
310     {
311         return invalidatedPayload;
312     }
313 }