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 }