View Javadoc

1   /*
2    * $Id: MuleMessage.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.impl;
12  
13  import org.mule.MuleRuntimeException;
14  import org.mule.config.i18n.CoreMessages;
15  import org.mule.providers.AbstractMessageAdapter;
16  import org.mule.providers.DefaultMessageAdapter;
17  import org.mule.umo.UMOExceptionPayload;
18  import org.mule.umo.UMOMessage;
19  import org.mule.umo.provider.UMOMessageAdapter;
20  
21  import java.util.Iterator;
22  import java.util.Map;
23  import java.util.Set;
24  
25  import javax.activation.DataHandler;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  /**
31   * <code>MuleMessage</code> is a wrapper that contains a payload and properties
32   * associated with the payload.
33   */
34  
35  public class MuleMessage implements UMOMessage, ThreadSafeAccess
36  {
37      /**
38       * Serial version
39       */
40      private static final long serialVersionUID = 1541720810851984842L;
41  
42      private static Log logger = LogFactory.getLog(MuleMessage.class);
43  
44      private UMOMessageAdapter adapter;
45  
46      protected UMOExceptionPayload exceptionPayload;
47  
48      public MuleMessage(Object message)
49      {
50          this(message, (Map) null);
51      }
52  
53      public MuleMessage(Object message, Map properties)
54      {
55          if (message instanceof UMOMessageAdapter)
56          {
57              adapter = (UMOMessageAdapter) message;
58          }
59          else
60          {
61              adapter = new DefaultMessageAdapter(message);
62          }
63          addProperties(properties);
64          resetAccessControl();
65      }
66  
67      public MuleMessage(Object message, UMOMessageAdapter previous)
68      {
69          if (message instanceof UMOMessageAdapter)
70          {
71              adapter = (UMOMessageAdapter) message;
72          }
73          else
74          {
75              adapter = new DefaultMessageAdapter(message, previous);
76          }
77          if (previous.getExceptionPayload() != null)
78          {
79              setExceptionPayload(previous.getExceptionPayload());
80          }
81          setEncoding(previous.getEncoding());
82          if (previous.getAttachmentNames().size() > 0)
83          {
84              Set attNames = adapter.getAttachmentNames();
85              synchronized (attNames)
86              {
87                  for (Iterator iterator = attNames.iterator(); iterator.hasNext();)
88                  {
89                      String s = (String) iterator.next();
90                      try
91                      {
92                          addAttachment(s, adapter.getAttachment(s));
93                      }
94                      catch (Exception e)
95                      {
96                          throw new MuleRuntimeException(CoreMessages.failedToReadAttachment(s), e);
97                      }
98                  }
99              }
100         }
101         resetAccessControl();
102     }
103 
104     public UMOMessageAdapter getAdapter()
105     {
106         return adapter;
107     }
108 
109     /**
110      * Gets a property of the payload implementation
111      * 
112      * @param key the key on which to lookup the property value
113      * @return the property value or null if the property does not exist
114      */
115     public Object getProperty(String key)
116     {
117         return adapter.getProperty(key);
118     }
119 
120     public Object removeProperty(String key)
121     {
122         return adapter.removeProperty(key);
123     }
124 
125     /**
126      * Gets a property of the payload implementation
127      * 
128      * @param key the key on which to associate the value
129      * @param value the property value
130      */
131     public void setProperty(String key, Object value)
132     {
133         adapter.setProperty(key, value);
134     }
135 
136     /**
137      * Converts the payload implementation into a String representation
138      * 
139      * @return String representation of the payload
140      * @throws Exception Implemetation may throw an endpoint specific exception
141      */
142     public String getPayloadAsString() throws Exception
143     {
144         return adapter.getPayloadAsString();
145     }
146 
147     /**
148      * Converts the message implementation into a String representation
149      * 
150      * @param encoding The encoding to use when transforming the message (if
151      *            necessary). The parameter is used when converting from a byte array
152      * @return String representation of the message payload
153      * @throws Exception Implementation may throw an endpoint specific exception
154      */
155     public String getPayloadAsString(String encoding) throws Exception
156     {
157         if (encoding == null)
158         {
159             return adapter.getPayloadAsString();
160         }
161         else
162         {
163             return adapter.getPayloadAsString(encoding);
164         }
165     }
166 
167     /**
168      * @return all properties on this payload
169      */
170     public Set getPropertyNames()
171     {
172         return adapter.getPropertyNames();
173     }
174 
175     /**
176      * Converts the payload implementation into a String representation
177      * 
178      * @return String representation of the payload
179      * @throws Exception Implemetation may throw an endpoint specific exception
180      */
181     public byte[] getPayloadAsBytes() throws Exception
182     {
183         return adapter.getPayloadAsBytes();
184     }
185 
186     /**
187      * @return the current payload
188      */
189     public Object getPayload()
190     {
191         return adapter.getPayload();
192     }
193 
194     public void addProperties(Map properties)
195     {
196         adapter.addProperties(properties);
197     }
198 
199     public void clearProperties()
200     {
201         adapter.clearProperties();
202     }
203 
204     /**
205      * Gets a double property from the event
206      * 
207      * @param name the name or key of the property
208      * @param defaultValue a default value if the property doesn't exist in the event
209      * @return the property value or the defaultValue if the property does not exist
210      */
211     public double getDoubleProperty(String name, double defaultValue)
212     {
213         return adapter.getDoubleProperty(name, defaultValue);
214     }
215 
216     /**
217      * Sets a double property on the event
218      * 
219      * @param name the property name or key
220      * @param value the property value
221      */
222     public void setDoubleProperty(String name, double value)
223     {
224         adapter.setDoubleProperty(name, value);
225     }
226 
227     public String getUniqueId()
228     {
229         return adapter.getUniqueId();
230     }
231 
232     public Object getProperty(String name, Object defaultValue)
233     {
234         return adapter.getProperty(name, defaultValue);
235     }
236 
237     public int getIntProperty(String name, int defaultValue)
238     {
239         return adapter.getIntProperty(name, defaultValue);
240     }
241 
242     public long getLongProperty(String name, long defaultValue)
243     {
244         return adapter.getLongProperty(name, defaultValue);
245     }
246 
247     public boolean getBooleanProperty(String name, boolean defaultValue)
248     {
249         return adapter.getBooleanProperty(name, defaultValue);
250     }
251 
252     public void setBooleanProperty(String name, boolean value)
253     {
254         adapter.setBooleanProperty(name, value);
255     }
256 
257     public void setIntProperty(String name, int value)
258     {
259         adapter.setIntProperty(name, value);
260     }
261 
262     public void setLongProperty(String name, long value)
263     {
264         adapter.setLongProperty(name, value);
265     }
266 
267     /**
268      * Sets a correlationId for this message. The correlation Id can be used by
269      * components in the system to manage message relations <p/> transport protocol.
270      * As such not all messages will support the notion of a correlationId i.e. tcp
271      * or file. In this situation the correlation Id is set as a property of the
272      * message where it's up to developer to keep the association with the message.
273      * For example if the message is serialised to xml the correlationId will be
274      * available in the message.
275      * 
276      * @param id the Id reference for this relationship
277      */
278     public void setCorrelationId(String id)
279     {
280         adapter.setCorrelationId(id);
281     }
282 
283     /**
284      * Sets a correlationId for this message. The correlation Id can be used by
285      * components in the system to manage message relations. <p/> The correlationId
286      * is associated with the message using the underlying transport protocol. As
287      * such not all messages will support the notion of a correlationId i.e. tcp or
288      * file. In this situation the correlation Id is set as a property of the message
289      * where it's up to developer to keep the association with the message. For
290      * example if the message is serialised to xml the correlationId will be
291      * available in the message.
292      * 
293      * @return the correlationId for this message or null if one hasn't been set
294      */
295     public String getCorrelationId()
296     {
297         return adapter.getCorrelationId();
298     }
299 
300     /**
301      * Sets a replyTo address for this message. This is useful in an asynchronous
302      * environment where the caller doesn't wait for a response and the response
303      * needs to be routed somewhere for further processing. The value of this field
304      * can be any valid endpointUri url.
305      * 
306      * @param replyTo the endpointUri url to reply to
307      */
308     public void setReplyTo(Object replyTo)
309     {
310         adapter.setReplyTo(replyTo);
311     }
312 
313     /**
314      * Sets a replyTo address for this message. This is useful in an asynchronous
315      * environment where the caller doesn't wait for a response and the response
316      * needs to be routed somewhere for further processing. The value of this field
317      * can be any valid endpointUri url.
318      * 
319      * @return the endpointUri url to reply to or null if one has not been set
320      */
321     public Object getReplyTo()
322     {
323         return adapter.getReplyTo();
324     }
325 
326     /**
327      * Gets the sequence or ordering number for this message in the the correlation
328      * group (as defined by the correlationId)
329      * 
330      * @return the sequence number or -1 if the sequence is not important
331      */
332     public int getCorrelationSequence()
333     {
334         return adapter.getCorrelationSequence();
335     }
336 
337     /**
338      * Gets the sequence or ordering number for this message in the the correlation
339      * group (as defined by the correlationId)
340      * 
341      * @param sequence the sequence number or -1 if the sequence is not important
342      */
343     public void setCorrelationSequence(int sequence)
344     {
345         adapter.setCorrelationSequence(sequence);
346     }
347 
348     /**
349      * Determines how many messages are in the correlation group
350      * 
351      * @return total messages in this group or -1 if the size is not known
352      */
353     public int getCorrelationGroupSize()
354     {
355         return adapter.getCorrelationGroupSize();
356     }
357 
358     /**
359      * Determines how many messages are in the correlation group
360      * 
361      * @param size the total messages in this group or -1 if the size is not known
362      */
363     public void setCorrelationGroupSize(int size)
364     {
365         adapter.setCorrelationGroupSize(size);
366     }
367 
368     public UMOExceptionPayload getExceptionPayload()
369     {
370         return exceptionPayload;
371     }
372 
373     public void setExceptionPayload(UMOExceptionPayload exceptionPayload)
374     {
375         this.exceptionPayload = exceptionPayload;
376     }
377 
378     public String toString()
379     {
380         return adapter.toString();
381     }
382 
383     public void addAttachment(String name, DataHandler dataHandler) throws Exception
384     {
385         adapter.addAttachment(name, dataHandler);
386     }
387 
388     public void removeAttachment(String name) throws Exception
389     {
390         adapter.removeAttachment(name);
391     }
392 
393     public DataHandler getAttachment(String name)
394     {
395         return adapter.getAttachment(name);
396     }
397 
398     public Set getAttachmentNames()
399     {
400         return adapter.getAttachmentNames();
401     }
402 
403     /**
404      * Gets the encoding for the current message. For potocols that send encoding
405      * Information with the message, this method should be overriden to expose the
406      * transport encoding, otherwise the default encoding in the Mule configuration
407      * will be used
408      * 
409      * @return the encoding for this message. This method must never return null
410      */
411     public String getEncoding()
412     {
413         return adapter.getEncoding();
414     }
415 
416     /**
417      * Sets the encoding for this message
418      * 
419      * @param encoding the encoding to use
420      */
421     public void setEncoding(String encoding)
422     {
423         adapter.setEncoding(encoding);
424     }
425 
426     /**
427      * Gets a String property from the event
428      * 
429      * @param name the name or key of the property
430      * @param defaultValue a default value if the property doesn't exist in the event
431      * @return the property value or the defaultValue if the property does not exist
432      */
433     public String getStringProperty(String name, String defaultValue)
434     {
435         return adapter.getStringProperty(name, defaultValue);
436     }
437 
438     /**
439      * Sets a String property on the event
440      * 
441      * @param name the property name or key
442      * @param value the property value
443      */
444     public void setStringProperty(String name, String value)
445     {
446         adapter.setStringProperty(name, value);
447     }
448 
449     public ThreadSafeAccess newThreadCopy()
450     {
451         if (adapter instanceof ThreadSafeAccess)
452         {
453             logger.debug("new copy of message for " + Thread.currentThread());
454             return new MuleMessage(((ThreadSafeAccess) adapter).newThreadCopy(), this);
455         }
456         else
457         {
458             // not much we can do here - streaming will have to handle things itself
459             return this;
460         }
461     }
462 
463     public void resetAccessControl()
464     {
465         if (adapter instanceof AbstractMessageAdapter)
466         {
467             ((AbstractMessageAdapter) adapter).resetAccessControl();
468         }
469     }
470 
471     public void assertAccess(boolean write)
472     {
473         if (adapter instanceof AbstractMessageAdapter)
474         {
475             ((AbstractMessageAdapter) adapter).assertAccess(write);
476         }
477     }
478 
479 }