1
2
3
4
5
6
7
8
9
10
11 package org.mule;
12
13 import org.mule.api.ExceptionPayload;
14 import org.mule.api.MuleContext;
15 import org.mule.api.MuleEvent;
16 import org.mule.api.MuleException;
17 import org.mule.api.MuleMessage;
18 import org.mule.api.MuleRuntimeException;
19 import org.mule.api.ThreadSafeAccess;
20 import org.mule.api.config.MuleProperties;
21 import org.mule.api.transformer.DataType;
22 import org.mule.api.transformer.MessageTransformer;
23 import org.mule.api.transformer.Transformer;
24 import org.mule.api.transformer.TransformerException;
25 import org.mule.api.transport.OutputHandler;
26 import org.mule.api.transport.PropertyScope;
27 import org.mule.config.MuleManifest;
28 import org.mule.config.i18n.CoreMessages;
29 import org.mule.transformer.types.DataTypeFactory;
30 import org.mule.transformer.types.MimeTypes;
31 import org.mule.transport.NullPayload;
32 import org.mule.util.ClassUtils;
33 import org.mule.util.ObjectUtils;
34 import org.mule.util.StringMessageUtils;
35 import org.mule.util.StringUtils;
36 import org.mule.util.UUID;
37 import org.mule.util.store.DeserializationPostInitialisable;
38
39 import java.io.File;
40 import java.io.FileInputStream;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.io.Serializable;
46 import java.net.URL;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Set;
54
55 import javax.activation.DataHandler;
56 import javax.activation.FileDataSource;
57
58 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
59 import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
60 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
61 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
62 import org.apache.commons.logging.Log;
63 import org.apache.commons.logging.LogFactory;
64
65
66
67
68
69 public class DefaultMuleMessage implements MuleMessage, ThreadSafeAccess, DeserializationPostInitialisable
70 {
71 protected static final String NOT_SET = "<not set>";
72
73 private static final long serialVersionUID = 1541720810851984844L;
74 private static final Log logger = LogFactory.getLog(DefaultMuleMessage.class);
75 private static final List<Class<?>> consumableClasses = new ArrayList<Class<?>>();
76
77
78
79
80
81 private String id = UUID.getUUID();
82
83 private transient Object payload;
84 private transient Object originalPayload;
85
86
87
88
89
90 private ExceptionPayload exceptionPayload;
91
92
93
94
95 private MessagePropertiesContext properties = new MessagePropertiesContext();
96
97
98
99
100 @SuppressWarnings("unchecked")
101 private Map<String, DataHandler> inboundAttachments = new ConcurrentHashMap();
102
103
104
105
106 @SuppressWarnings("unchecked")
107 private Map<String, DataHandler> outboundAttachments = new ConcurrentHashMap();
108
109 private transient List<Integer> appliedTransformerHashCodes;
110 private transient byte[] cache;
111 protected transient MuleContext muleContext;
112
113
114
115 private transient AtomicReference ownerThread = null;
116 private transient AtomicBoolean mutable = null;
117
118 private DataType<?> dataType;
119
120 static
121 {
122 addToConsumableClasses("javax.xml.stream.XMLStreamReader");
123 addToConsumableClasses("javax.xml.transform.stream.StreamSource");
124 consumableClasses.add(OutputHandler.class);
125 }
126
127 private static void addToConsumableClasses(String className)
128 {
129 try
130 {
131 consumableClasses.add(ClassUtils.loadClass(className, DefaultMuleMessage.class));
132 }
133 catch (ClassNotFoundException e)
134 {
135
136 }
137 }
138
139 public DefaultMuleMessage(Object message, MuleContext muleContext)
140 {
141 this(message, (Map<String, Object>) null, muleContext);
142 }
143
144 public DefaultMuleMessage(Object message, Map<String, Object> outboundProperties, MuleContext muleContext)
145 {
146 this(message, outboundProperties, null, muleContext);
147 }
148
149 public DefaultMuleMessage(Object message, Map<String, Object> outboundProperties, Map<String, DataHandler> attachments, MuleContext muleContext)
150 {
151 this(message, null, outboundProperties, attachments, muleContext);
152 }
153
154 public DefaultMuleMessage(Object message, Map<String, Object> inboundProperties,
155 Map<String, Object> outboundProperties, Map<String, DataHandler> attachments,
156 MuleContext muleContext)
157 {
158 setMuleContext(muleContext);
159 initAppliedTransformerHashCodes();
160
161 if (message instanceof MuleMessage)
162 {
163 MuleMessage muleMessage = (MuleMessage) message;
164 setPayload(muleMessage.getPayload());
165 copyMessageProperties(muleMessage);
166 }
167 else
168 {
169 setPayload(message);
170 originalPayload = message;
171 }
172 addProperties(inboundProperties, PropertyScope.INBOUND);
173 addProperties(outboundProperties);
174
175
176 if (attachments != null)
177 {
178 inboundAttachments = attachments;
179 }
180
181 resetAccessControl();
182 }
183
184 public DefaultMuleMessage(Object message, MuleMessage previous, MuleContext muleContext)
185 {
186 id = previous.getUniqueId();
187 setMuleContext(muleContext);
188 initAppliedTransformerHashCodes();
189 setEncoding(previous.getEncoding());
190
191 if (message instanceof MuleMessage)
192 {
193 MuleMessage payloadMessage = (MuleMessage) message;
194 setPayload(payloadMessage.getPayload());
195 copyMessageProperties(payloadMessage);
196 }
197 else
198 {
199 setPayload(message);
200 copyMessageProperties(previous);
201 }
202 originalPayload = previous.getPayload();
203
204 if (previous.getExceptionPayload() != null)
205 {
206 setExceptionPayload(previous.getExceptionPayload());
207 }
208
209 copyAttachments(previous);
210
211 resetAccessControl();
212 }
213
214 private void copyMessageProperties(MuleMessage muleMessage)
215 {
216
217 Map<String, Object> inboundProperties =
218 ((DefaultMuleMessage) muleMessage).properties.getScopedProperties(PropertyScope.INBOUND);
219 addInboundProperties(inboundProperties);
220
221 for (PropertyScope scope : PropertyScope.ALL_SCOPES)
222 {
223 try
224 {
225 for (String name : muleMessage.getPropertyNames(scope))
226 {
227 Object value = muleMessage.getProperty(name, scope);
228 if (value != null)
229 {
230 setProperty(name, value, scope);
231 }
232 }
233 }
234 catch (IllegalArgumentException iae)
235 {
236
237 }
238 }
239 }
240
241 private void copyAttachments(MuleMessage previous)
242 {
243 if (previous.getInboundAttachmentNames().size() > 0)
244 {
245 for (String name : previous.getInboundAttachmentNames())
246 {
247 try
248 {
249 inboundAttachments.put(name, previous.getInboundAttachment(name));
250 }
251 catch (Exception e)
252 {
253 throw new MuleRuntimeException(CoreMessages.failedToReadAttachment(name), e);
254 }
255 }
256 }
257
258 if (previous.getOutboundAttachmentNames().size() > 0)
259 {
260 for (String name : previous.getOutboundAttachmentNames())
261 {
262 try
263 {
264 addOutboundAttachment(name, previous.getOutboundAttachment(name));
265 }
266 catch (Exception e)
267 {
268 throw new MuleRuntimeException(CoreMessages.failedToReadAttachment(name), e);
269 }
270 }
271 }
272 }
273
274 public DefaultMuleMessage(MuleMessage message)
275 {
276 this(message.getPayload(), message, message.getMuleContext());
277 }
278
279 private void setMuleContext(MuleContext context)
280 {
281 if (context == null)
282 {
283 throw new IllegalArgumentException(CoreMessages.objectIsNull("muleContext").getMessage());
284 }
285 muleContext = context;
286 }
287
288 @SuppressWarnings("unchecked")
289 private void initAppliedTransformerHashCodes()
290 {
291 appliedTransformerHashCodes = new CopyOnWriteArrayList();
292 }
293
294
295
296
297 public <T> T getPayload(Class<T> outputType) throws TransformerException
298 {
299 return (T) getPayload(DataTypeFactory.create(outputType), getEncoding());
300 }
301
302
303
304
305
306 public <T> T getPayload(DataType<T> outputType) throws TransformerException
307 {
308 return getPayload(outputType, getEncoding());
309 }
310
311 public MuleContext getMuleContext()
312 {
313 return muleContext;
314 }
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 @SuppressWarnings("unchecked")
332 protected <T> T getPayload(DataType<T> resultType, String encoding) throws TransformerException
333 {
334
335 if (resultType == null)
336 {
337 throw new IllegalArgumentException(CoreMessages.objectIsNull("resultType").getMessage());
338 }
339
340 DataType source = DataTypeFactory.createFromObject(this);
341
342
343 if (resultType.isCompatibleWith(source))
344 {
345 return (T) getPayload();
346 }
347
348
349 Transformer transformer = muleContext.getRegistry().lookupTransformer(source, resultType);
350 if (transformer == null)
351 {
352 throw new TransformerException(CoreMessages.noTransformerFoundForMessage(source, resultType));
353 }
354
355
356 Object result = transformer.transform(this, encoding);
357
358
359 if (!resultType.getType().isAssignableFrom(result.getClass()))
360 {
361 throw new TransformerException(CoreMessages.transformOnObjectNotOfSpecifiedType(resultType, result));
362 }
363
364
365
366 if (isPayloadConsumed(source.getType()))
367 {
368 setPayload(result);
369 }
370
371 return (T) result;
372 }
373
374
375
376
377
378
379
380
381
382 protected boolean isPayloadConsumed(Class<?> inputCls)
383 {
384 return InputStream.class.isAssignableFrom(inputCls) || isConsumedFromAdditional(inputCls);
385 }
386
387 private boolean isConsumedFromAdditional(Class<?> inputCls)
388 {
389 if (consumableClasses.isEmpty())
390 {
391 return false;
392 }
393
394 for (Class<?> c : consumableClasses)
395 {
396 if (c.isAssignableFrom(inputCls))
397 {
398 return true;
399 }
400 }
401 return false;
402 }
403
404
405
406
407 public Object getOriginalPayload()
408 {
409 return originalPayload;
410 }
411
412 public void setInboundProperty(String key, Object value)
413 {
414 setProperty(key, value, PropertyScope.INBOUND);
415 }
416
417 public void setInvocationProperty(String key, Object value)
418 {
419 setProperty(key, value, PropertyScope.INVOCATION);
420 }
421
422 public void setOutboundProperty(String key, Object value)
423 {
424 setProperty(key, value, PropertyScope.OUTBOUND);
425 }
426
427 public void setSessionProperty(String key, Object value)
428 {
429 setProperty(key, value, PropertyScope.SESSION);
430 }
431
432
433
434
435 public void setProperty(String key, Object value, PropertyScope scope)
436 {
437 assertAccess(WRITE);
438 if (key != null)
439 {
440 if (value != null)
441 {
442 properties.setProperty(key, value, scope);
443 }
444 else
445 {
446 logger.warn("setProperty(key, value) called with null value; removing key: " + key
447 + "; please report the following stack trace to " + MuleManifest.getDevListEmail(),
448 new Throwable());
449 properties.removeProperty(key);
450 }
451 }
452 else
453 {
454 logger.warn("setProperty(key, value) ignored because of null key for object: " + value
455 + "; please report the following stack trace to " + MuleManifest.getDevListEmail(),
456 new Throwable());
457 }
458 }
459
460
461
462
463 @Deprecated
464 public Object getProperty(String key)
465 {
466 assertAccess(READ);
467 return properties.getProperty(key, PropertyScope.OUTBOUND);
468 }
469
470
471
472
473
474 public Object removeProperty(String key)
475 {
476
477
478
479 assertAccess(WRITE);
480 return properties.removeProperty(key);
481 }
482
483
484
485
486 public Object removeProperty(String key, PropertyScope scope)
487 {
488 assertAccess(WRITE);
489 return properties.removeProperty(key, scope);
490 }
491
492
493
494
495
496
497
498
499
500
501
502
503
504 @Deprecated
505 public void setProperty(String key, Object value)
506 {
507 assertAccess(WRITE);
508 if (key != null)
509 {
510 if (value != null)
511 {
512 properties.setProperty(key, value, PropertyScope.OUTBOUND);
513 }
514 else
515 {
516 logger.warn("setProperty(key, value) called with null value; removing key: " + key
517 + "; please report the following stack trace to " + MuleManifest.getDevListEmail(),
518 new Throwable());
519 properties.removeProperty(key);
520 }
521 }
522 else
523 {
524 logger.warn("setProperty(key, value) ignored because of null key for object: " + value
525 + "; please report the following stack trace to " + MuleManifest.getDevListEmail(),
526 new Throwable());
527 }
528 }
529
530
531
532
533 public final String getPayloadAsString() throws Exception
534 {
535 assertAccess(READ);
536 return getPayloadAsString(getEncoding());
537 }
538
539
540
541
542 public String getPayloadForLogging(String encoding)
543 {
544 try
545 {
546 return getPayloadAsString(encoding);
547 }
548 catch (Exception e)
549 {
550
551 return "[Messaage could not be converted to string]";
552 }
553 }
554
555
556
557
558 public String getPayloadForLogging()
559 {
560 try
561 {
562 return getPayloadAsString();
563 }
564 catch (Exception e)
565 {
566
567 return "[Messaage could not be converted to string]";
568 }
569 }
570
571
572
573
574 public byte[] getPayloadAsBytes() throws Exception
575 {
576 assertAccess(READ);
577 if (cache != null)
578 {
579 return cache;
580 }
581 byte[] result = getPayload(DataType.BYTE_ARRAY_DATA_TYPE);
582 if (muleContext.getConfiguration().isCacheMessageAsBytes())
583 {
584 cache = result;
585 }
586 return result;
587 }
588
589
590
591
592 public String getPayloadAsString(String encoding) throws Exception
593 {
594 assertAccess(READ);
595 if (cache != null)
596 {
597 return new String(cache, encoding);
598 }
599 String result = getPayload(DataType.STRING_DATA_TYPE, encoding);
600 if (muleContext.getConfiguration().isCacheMessageAsBytes())
601 {
602 cache = result.getBytes(encoding);
603 }
604 return result;
605 }
606
607
608
609
610
611
612 @Deprecated
613 public Set<String> getPropertyNames()
614 {
615
616
617 assertAccess(READ);
618 return properties.getPropertyNames();
619 }
620
621
622
623
624 public Set<String> getPropertyNames(PropertyScope scope)
625 {
626 assertAccess(READ);
627 if (PropertyScope.SESSION.equals(scope))
628 {
629 if (RequestContext.getEvent() != null)
630 {
631 return RequestContext.getEvent().getSession().getPropertyNamesAsSet();
632 }
633 else
634 {
635 return Collections.emptySet();
636 }
637 }
638 else
639 {
640 return properties.getScopedProperties(scope).keySet();
641 }
642 }
643
644 public Set<String> getInvocationPropertyNames()
645 {
646 return getPropertyNames(PropertyScope.INVOCATION);
647 }
648
649 public Set<String> getInboundPropertyNames()
650 {
651 return getPropertyNames(PropertyScope.INBOUND);
652 }
653
654 public Set<String> getOutboundPropertyNames()
655 {
656 return getPropertyNames(PropertyScope.OUTBOUND);
657 }
658
659 public Set<String> getSessionPropertyNames()
660 {
661 return getPropertyNames(PropertyScope.SESSION);
662 }
663
664 /
665
666
667
668
669 public String getUniqueId()
670 {
671 assertAccess(READ);
672 return id;
673 }
674
675 public void setUniqueId(String uid)
676 {
677 assertAccess(WRITE);
678 id = uid;
679 }
680
681
682
683
684 public Object getProperty(String name, Object defaultValue)
685 {
686
687
688 assertAccess(READ);
689 return properties.getProperty(name, defaultValue);
690 }
691
692
693
694
695 @SuppressWarnings("unchecked")
696 public <T> T getProperty(String name, PropertyScope scope)
697 {
698 assertAccess(READ);
699 return (T) properties.getProperty(name, scope);
700 }
701
702 public <T> T getInboundProperty(String name, T defaultValue)
703 {
704 return getProperty(name, PropertyScope.INBOUND, defaultValue);
705 }
706
707 public <T> T getInboundProperty(String name)
708 {
709 return getProperty(name, PropertyScope.INBOUND, (T) null);
710 }
711
712 public <T> T getInvocationProperty(String name, T defaultValue)
713 {
714 return getProperty(name, PropertyScope.INVOCATION, defaultValue);
715 }
716
717 public <T> T getInvocationProperty(String name)
718 {
719 return getInvocationProperty(name, (T) null);
720 }
721
722 public <T> T getOutboundProperty(String name, T defaultValue)
723 {
724 return getProperty(name, PropertyScope.OUTBOUND, defaultValue);
725 }
726
727 public <T> T getOutboundProperty(String name)
728 {
729 return getOutboundProperty(name, (T) null);
730 }
731
732 public <T> T getSessionProperty(String name, T defaultValue)
733 {
734 return getProperty(name, PropertyScope.SESSION, defaultValue);
735 }
736
737 public <T> T getSessionProperty(String name)
738 {
739 return getSessionProperty(name, (T) null);
740 }
741
742
743
744
745 @SuppressWarnings("unchecked")
746 public <T> T getProperty(String name, PropertyScope scope, T defaultValue)
747 {
748 assertAccess(READ);
749 T result;
750
751
752
753 if (defaultValue instanceof Boolean)
754 {
755 result = (T) (Boolean) ObjectUtils.getBoolean(getProperty(name, scope), (Boolean) defaultValue);
756 }
757 else if (defaultValue instanceof Byte)
758 {
759 result = (T) (Byte) ObjectUtils.getByte(getProperty(name, scope), (Byte) defaultValue);
760 }
761 else if (defaultValue instanceof Integer)
762 {
763 result = (T) (Integer) ObjectUtils.getInt(getProperty(name, scope), (Integer) defaultValue);
764 }
765 else if (defaultValue instanceof Short)
766 {
767 result = (T) (Short) ObjectUtils.getShort(getProperty(name, scope), (Short) defaultValue);
768 }
769 else if (defaultValue instanceof Long)
770 {
771 result = (T) (Long) ObjectUtils.getLong(getProperty(name, scope), (Long) defaultValue);
772 }
773 else if (defaultValue instanceof Float)
774 {
775 result = (T) (Float) ObjectUtils.getFloat(getProperty(name, scope), (Float) defaultValue);
776 }
777 else if (defaultValue instanceof Double)
778 {
779 result = (T) (Double) ObjectUtils.getDouble(getProperty(name, scope), (Double) defaultValue);
780 }
781 else if (defaultValue instanceof String)
782 {
783 result = (T) (String) ObjectUtils.getString(getProperty(name, scope), (String) defaultValue);
784 }
785 else
786 {
787 Object temp = getProperty(name, scope);
788 if (temp == null)
789 {
790 return defaultValue;
791 }
792 else if (defaultValue == null)
793 {
794 return (T) temp;
795 }
796
797 else if (defaultValue.getClass().isAssignableFrom(temp.getClass()))
798 {
799 result = (T) temp;
800 }
801 else
802 {
803 throw new IllegalArgumentException(CoreMessages.objectNotOfCorrectType(temp.getClass(), defaultValue.getClass()).getMessage());
804 }
805 }
806 return result;
807 }
808
809
810
811
812 public void setCorrelationId(String id)
813 {
814 assertAccess(WRITE);
815 if (StringUtils.isNotBlank(id))
816 {
817 setProperty(MuleProperties.MULE_CORRELATION_ID_PROPERTY, id, PropertyScope.OUTBOUND);
818 }
819 else
820 {
821 removeProperty(MuleProperties.MULE_CORRELATION_ID_PROPERTY);
822 }
823 }
824
825
826
827
828 public String getCorrelationId()
829 {
830 assertAccess(READ);
831 String correlationId = getOutboundProperty(MuleProperties.MULE_CORRELATION_ID_PROPERTY);
832 if (correlationId == null)
833 {
834 correlationId = getInboundProperty(MuleProperties.MULE_CORRELATION_ID_PROPERTY);
835 }
836
837 return correlationId;
838 }
839
840
841
842
843 public void setReplyTo(Object replyTo)
844 {
845 assertAccess(WRITE);
846 if (replyTo != null)
847 {
848 setProperty(MuleProperties.MULE_REPLY_TO_PROPERTY, replyTo, PropertyScope.OUTBOUND);
849 }
850 else
851 {
852 removeProperty(MuleProperties.MULE_REPLY_TO_PROPERTY);
853 removeProperty(MuleProperties.MULE_REPLY_TO_PROPERTY, PropertyScope.INBOUND);
854 }
855 }
856
857
858
859
860 public Object getReplyTo()
861 {
862 assertAccess(READ);
863 Object replyTo = getProperty(MuleProperties.MULE_REPLY_TO_PROPERTY, PropertyScope.OUTBOUND);
864 if (replyTo == null)
865 {
866
867 replyTo = getProperty(MuleProperties.MULE_REPLY_TO_PROPERTY, PropertyScope.INBOUND);
868 }
869 return replyTo;
870 }
871
872
873
874
875 public int getCorrelationSequence()
876 {
877 assertAccess(READ);
878
879 Object correlationSequence = findPropertyInSpecifiedScopes(MuleProperties.MULE_CORRELATION_SEQUENCE_PROPERTY,
880 PropertyScope.OUTBOUND,
881 PropertyScope.INBOUND);
882 return ObjectUtils.getInt(correlationSequence, -1);
883 }
884
885
886
887
888 public void setCorrelationSequence(int sequence)
889 {
890 assertAccess(WRITE);
891 setOutboundProperty(MuleProperties.MULE_CORRELATION_SEQUENCE_PROPERTY, sequence);
892 }
893
894
895
896
897 public int getCorrelationGroupSize()
898 {
899 assertAccess(READ);
900
901 Object correlationGroupSize = findPropertyInSpecifiedScopes(MuleProperties.MULE_CORRELATION_GROUP_SIZE_PROPERTY,
902 PropertyScope.OUTBOUND,
903 PropertyScope.INBOUND);
904 return ObjectUtils.getInt(correlationGroupSize, -1);
905 }
906
907
908
909
910 public void setCorrelationGroupSize(int size)
911 {
912 assertAccess(WRITE);
913 setOutboundProperty(MuleProperties.MULE_CORRELATION_GROUP_SIZE_PROPERTY, size);
914 }
915
916
917
918
919 public ExceptionPayload getExceptionPayload()
920 {
921 assertAccess(READ);
922 return exceptionPayload;
923 }
924
925
926
927
928 public void setExceptionPayload(ExceptionPayload exceptionPayload)
929 {
930 assertAccess(WRITE);
931 this.exceptionPayload = exceptionPayload;
932 }
933
934 @Override
935 public String toString()
936 {
937 assertAccess(READ);
938 StringBuffer buf = new StringBuffer(120);
939 final String nl = System.getProperty("line.separator");
940
941
942 buf.append(nl);
943 buf.append(getClass().getName());
944 buf.append(nl);
945 buf.append("{");
946 buf.append(nl);
947 buf.append(" id=").append(getUniqueId());
948 buf.append(nl);
949 buf.append(" payload=").append(getPayload().getClass().getName());
950 buf.append(nl);
951 buf.append(" correlationId=").append(StringUtils.defaultString(getCorrelationId(), NOT_SET));
952 buf.append(nl);
953 buf.append(" correlationGroup=").append(getCorrelationGroupSize());
954 buf.append(nl);
955 buf.append(" correlationSeq=").append(getCorrelationSequence());
956 buf.append(nl);
957 buf.append(" encoding=").append(getEncoding());
958 buf.append(nl);
959 buf.append(" exceptionPayload=").append(ObjectUtils.defaultIfNull(exceptionPayload, NOT_SET));
960 buf.append(nl);
961 buf.append(StringMessageUtils.headersToString(this));
962
963 buf.append('}');
964 return buf.toString();
965 }
966
967
968
969
970 @Deprecated
971 public void addAttachment(String name, DataHandler dataHandler) throws Exception
972 {
973 logger.warn("MuleMessage.addAttachment() method is deprecated, use MuleMessage.addOutboundAttachment() instead. This method will be removed in the next point release");
974 addOutboundAttachment(name, dataHandler);
975 }
976
977
978
979
980 @Deprecated
981 public void removeAttachment(String name) throws Exception
982 {
983 logger.warn("MuleMessage.removeAttachment() method is deprecated, use MuleMessage.removeOutboundAttachment() instead. This method will be removed in the next point release");
984 removeOutboundAttachment(name);
985 }
986
987
988
989
990 @Deprecated
991 public DataHandler getAttachment(String name)
992 {
993 logger.warn("MuleMessage.getAttachment() method is deprecated, use MuleMessage.getInboundAttachment() instead. This method will be removed in the next point release");
994 return getInboundAttachment(name);
995 }
996
997
998
999
1000 @Deprecated
1001 public Set<String> getAttachmentNames()
1002 {
1003 logger.warn("MuleMessage.getAttachmentNames() method is deprecated, use MuleMessage.getInboundAttachmentNames() instead. This method will be removed in the next point release");
1004 return getInboundAttachmentNames();
1005 }
1006
1007 public void addOutboundAttachment(String name, DataHandler dataHandler) throws Exception
1008 {
1009 assertAccess(WRITE);
1010 outboundAttachments.put(name, dataHandler);
1011 }
1012
1013
1014
1015
1016 public void addInboundAttachment(String name, DataHandler dataHandler) throws Exception
1017 {
1018 assertAccess(WRITE);
1019 inboundAttachments.put(name, dataHandler);
1020 }
1021
1022 public void addOutboundAttachment(String name, Object object, String contentType) throws Exception
1023 {
1024 assertAccess(WRITE);
1025 DataHandler dh;
1026 if (object instanceof File)
1027 {
1028 if (contentType != null)
1029 {
1030 dh = new DataHandler(new FileInputStream((File) object), contentType);
1031
1032 }
1033 else
1034 {
1035 dh = new DataHandler(new FileDataSource((File) object));
1036 }
1037 }
1038 else if (object instanceof URL)
1039 {
1040 if (contentType != null)
1041 {
1042 dh = new DataHandler(((URL) object).openStream(), contentType);
1043 }
1044 else
1045 {
1046 dh = new DataHandler((URL) object);
1047 }
1048 }
1049 else
1050 {
1051 dh = new DataHandler(object, contentType);
1052 }
1053 outboundAttachments.put(name, dh);
1054 }
1055
1056 public void removeOutboundAttachment(String name) throws Exception
1057 {
1058 assertAccess(WRITE);
1059 outboundAttachments.remove(name);
1060 }
1061
1062 public DataHandler getInboundAttachment(String name)
1063 {
1064 assertAccess(READ);
1065 return inboundAttachments.get(name);
1066 }
1067
1068 public DataHandler getOutboundAttachment(String name)
1069 {
1070 assertAccess(READ);
1071 return outboundAttachments.get(name);
1072 }
1073
1074 public Set<String> getInboundAttachmentNames()
1075 {
1076 assertAccess(READ);
1077 return Collections.unmodifiableSet(inboundAttachments.keySet());
1078 }
1079
1080 public Set<String> getOutboundAttachmentNames()
1081 {
1082 assertAccess(READ);
1083 return Collections.unmodifiableSet(outboundAttachments.keySet());
1084 }
1085
1086 @SuppressWarnings("unchecked")
1087 public <T> T findPropertyInAnyScope(String name, T defaultValue)
1088 {
1089 Object value = findPropertyInSpecifiedScopes(name,
1090 PropertyScope.OUTBOUND,
1091 PropertyScope.INVOCATION,
1092 PropertyScope.SESSION,
1093 PropertyScope.INBOUND);
1094 if (value == null)
1095 {
1096 return defaultValue;
1097 }
1098 return (T) value;
1099 }
1100
1101
1102
1103
1104 public String getEncoding()
1105 {
1106 assertAccess(READ);
1107 String encoding = null;
1108 if (dataType != null)
1109 {
1110 encoding = dataType.getEncoding();
1111 }
1112 if (encoding != null)
1113 {
1114 return encoding;
1115 }
1116 encoding = getOutboundProperty(MuleProperties.MULE_ENCODING_PROPERTY);
1117 if (encoding != null)
1118 {
1119 return encoding;
1120 }
1121 else
1122 {
1123 return System.getProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY);
1124 }
1125 }
1126
1127
1128
1129
1130 public void setEncoding(String encoding)
1131 {
1132 assertAccess(WRITE);
1133 if (encoding != null)
1134 {
1135 setOutboundProperty(MuleProperties.MULE_ENCODING_PROPERTY, encoding);
1136 }
1137 }
1138
1139
1140
1141
1142
1143 public void setMimeType(String mimeType)
1144 {
1145 assertAccess(WRITE);
1146 if (mimeType != null && !mimeType.equals(MimeTypes.ANY))
1147 {
1148 String encoding = getEncoding();
1149 if (encoding != null)
1150 {
1151 mimeType = mimeType + ";charset=" + encoding;
1152 }
1153 setOutboundProperty(MuleProperties.CONTENT_TYPE_PROPERTY, mimeType);
1154 }
1155 }
1156
1157
1158
1159
1160 public void addProperties(Map<String, Object> props)
1161 {
1162 addProperties(props, properties.getDefaultScope());
1163 }
1164
1165
1166
1167
1168 public void addProperties(Map<String, Object> props, PropertyScope scope)
1169 {
1170 assertAccess(WRITE);
1171 if (props != null)
1172 {
1173 synchronized (props)
1174 {
1175 for (Map.Entry<String, Object> entry : props.entrySet())
1176 {
1177 setProperty(entry.getKey(), entry.getValue(), scope);
1178 }
1179 }
1180 }
1181 }
1182
1183 public void addInboundProperties(Map<String, Object> props)
1184 {
1185 properties.addInboundProperties(props);
1186 }
1187
1188
1189
1190
1191 public void clearProperties()
1192 {
1193 assertAccess(WRITE);
1194
1195 properties.clearProperties(PropertyScope.INVOCATION);
1196 properties.clearProperties(PropertyScope.OUTBOUND);
1197 }
1198
1199
1200
1201
1202 public void clearProperties(PropertyScope scope)
1203 {
1204 assertAccess(WRITE);
1205 properties.clearProperties(scope);
1206 }
1207
1208
1209
1210
1211
1212 public Object getPayload()
1213 {
1214 return payload;
1215 }
1216
1217
1218
1219
1220 public synchronized void setPayload(Object payload)
1221 {
1222 if (payload == null)
1223 {
1224 this.payload = NullPayload.getInstance();
1225 }
1226 else
1227 {
1228 this.payload = payload;
1229 }
1230 cache = null;
1231 }
1232
1233
1234
1235
1236 public void release()
1237 {
1238 cache = null;
1239 appliedTransformerHashCodes.clear();
1240 }
1241
1242
1243
1244
1245 public void applyTransformers(MuleEvent event, List<? extends Transformer> transformers) throws MuleException
1246 {
1247 applyTransformers(event, transformers, null);
1248 }
1249
1250
1251
1252
1253 public void applyTransformers(MuleEvent event, Transformer... transformers) throws MuleException
1254 {
1255 applyTransformers(event, Arrays.asList(transformers), null);
1256 }
1257
1258 public void applyTransformers(MuleEvent event, List<? extends Transformer> transformers, Class<?> outputType) throws MuleException
1259 {
1260 if (!transformers.isEmpty() && !appliedTransformerHashCodes.contains(transformers.hashCode()))
1261 {
1262 applyAllTransformers(event, transformers);
1263 appliedTransformerHashCodes.add(transformers.hashCode());
1264 }
1265
1266 if (null != outputType && !getPayload().getClass().isAssignableFrom(outputType))
1267 {
1268 setPayload(getPayload(DataTypeFactory.create(outputType)));
1269 }
1270 }
1271
1272 protected void applyAllTransformers(MuleEvent event, List<? extends Transformer> transformers) throws MuleException
1273 {
1274 if (!transformers.isEmpty())
1275 {
1276 for (Transformer transformer : transformers)
1277 {
1278 if (getPayload() == null)
1279 {
1280 if (transformer.isAcceptNull())
1281 {
1282 setPayload(NullPayload.getInstance());
1283 setDataType(null);
1284 }
1285 else
1286 {
1287 if (logger.isDebugEnabled())
1288 {
1289 logger.debug("Transformer " + transformer +
1290 " doesn't support the null payload, exiting from transformer chain.");
1291 }
1292 break;
1293 }
1294 }
1295
1296 Class<?> srcCls = getPayload().getClass();
1297 if (transformer.isSourceDataTypeSupported(DataTypeFactory.create(srcCls)))
1298 {
1299 Object result;
1300 if (transformer instanceof MessageTransformer)
1301 {
1302 result = ((MessageTransformer) transformer).transform(this, event);
1303 }
1304 else
1305 {
1306 result = transformer.transform(this);
1307 }
1308
1309 RequestContext.internalRewriteEvent(this, false);
1310
1311 if (originalPayload == null && muleContext.getConfiguration().isCacheMessageOriginalPayload())
1312 {
1313 originalPayload = payload;
1314 }
1315
1316 if (result instanceof MuleMessage)
1317 {
1318 synchronized (this)
1319 {
1320 MuleMessage resultMessage = (MuleMessage) result;
1321 setPayload(resultMessage.getPayload());
1322 originalPayload = resultMessage.getOriginalPayload();
1323 copyMessageProperties(resultMessage);
1324 copyAttachments(resultMessage);
1325 }
1326 }
1327 else
1328 {
1329 setPayload(result);
1330 }
1331 setDataType(transformer.getReturnDataType());
1332 }
1333 else
1334 {
1335 if (logger.isDebugEnabled())
1336 {
1337 logger.debug("Transformer " + transformer + " doesn't support the source payload: " + srcCls);
1338 }
1339 if (!transformer.isIgnoreBadInput())
1340 {
1341 if (logger.isDebugEnabled())
1342 {
1343 logger.debug("Exiting from transformer chain (ignoreBadInput = false)");
1344 }
1345 break;
1346 }
1347 }
1348 }
1349 }
1350 }
1351
1352 protected void setDataType(DataType<?> dt)
1353 {
1354 dataType = dt;
1355 setEncoding(dt == null ? null : dt.getEncoding());
1356 setMimeType(dt == null ? null : dt.getMimeType());
1357 }
1358
1359
1360
1361
1362
1363
1364 public ThreadSafeAccess newThreadCopy()
1365 {
1366 return new DefaultMuleMessage(this);
1367 }
1368
1369
1370
1371
1372 public void resetAccessControl()
1373 {
1374
1375
1376 if (ownerThread != null)
1377 {
1378 ownerThread.set(null);
1379 }
1380 if (mutable != null)
1381 {
1382 mutable.set(true);
1383 }
1384 }
1385
1386
1387
1388
1389 public void assertAccess(boolean write)
1390 {
1391 if (AccessControl.isAssertMessageAccess())
1392 {
1393 initAccessControl();
1394 setOwner();
1395 checkMutable(write);
1396 }
1397 }
1398
1399 private synchronized void initAccessControl()
1400 {
1401 if (null == ownerThread)
1402 {
1403 ownerThread = new AtomicReference();
1404 }
1405 if (null == mutable)
1406 {
1407 mutable = new AtomicBoolean(true);
1408 }
1409 }
1410
1411 private void setOwner()
1412 {
1413 if (null == ownerThread.get())
1414 {
1415 ownerThread.compareAndSet(null, Thread.currentThread());
1416 }
1417 }
1418
1419 private void checkMutable(boolean write)
1420 {
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441 Thread currentThread = Thread.currentThread();
1442 if (currentThread.equals(ownerThread.get()))
1443 {
1444 if (write && !mutable.get())
1445 {
1446 if (isDisabled())
1447 {
1448 logger.warn("Writing to immutable message (exception disabled)");
1449 }
1450 else
1451 {
1452 throw newException("Cannot write to immutable message");
1453 }
1454 }
1455 }
1456 else
1457 {
1458 if (write)
1459 {
1460 if (isDisabled())
1461 {
1462 logger.warn("Non-owner writing to message (exception disabled)");
1463 }
1464 else
1465 {
1466 throw newException("Only owner thread can write to message: "
1467 + ownerThread.get() + "/" + Thread.currentThread());
1468 }
1469 }
1470 }
1471 }
1472
1473 protected boolean isDisabled()
1474 {
1475 return !AccessControl.isFailOnMessageScribbling();
1476 }
1477
1478 protected IllegalStateException newException(String message)
1479 {
1480 IllegalStateException exception = new IllegalStateException(message);
1481 logger.warn("Message access violation", exception);
1482 return exception;
1483 }
1484
1485
1486
1487
1488
1489
1490 public boolean isConsumable()
1491 {
1492 return isConsumedFromAdditional(this.getPayload().getClass());
1493 }
1494
1495 private void writeObject(ObjectOutputStream out) throws Exception
1496 {
1497 out.defaultWriteObject();
1498
1499 if (payload instanceof Serializable)
1500 {
1501 out.writeBoolean(true);
1502 out.writeObject(payload);
1503 }
1504 else
1505 {
1506 out.writeBoolean(false);
1507 byte[] serializablePayload = getPayloadAsBytes();
1508 out.writeInt(serializablePayload.length);
1509 out.write(serializablePayload);
1510 }
1511
1512
1513 }
1514
1515 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
1516 {
1517 in.defaultReadObject();
1518
1519 boolean payloadWasSerialized = in.readBoolean();
1520 if (payloadWasSerialized)
1521 {
1522 payload = in.readObject();
1523 }
1524 else
1525 {
1526 int payloadSize = in.readInt();
1527 byte[] serializedPayload = new byte[payloadSize];
1528 in.read(serializedPayload);
1529 payload = serializedPayload;
1530 }
1531 }
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544 public void initAfterDeserialisation(MuleContext muleContext) throws MuleException
1545 {
1546 this.muleContext = muleContext;
1547 }
1548
1549 public DataType<?> getDataType()
1550 {
1551 return dataType;
1552 }
1553
1554
1555
1556
1557 @Deprecated
1558 public int getIntProperty(String name, int defaultValue)
1559 {
1560 assertAccess(READ);
1561 logger.warn("MuleMessage.getIntProperty() method is deprecated, use MuleMessage.getInboundProperty() instead. This method will be removed in the next point release");
1562 return getInboundProperty(name, defaultValue);
1563 }
1564
1565
1566
1567
1568 @Deprecated
1569 public long getLongProperty(String name, long defaultValue)
1570 {
1571 assertAccess(READ);
1572 logger.warn("MuleMessage.getLongProperty() method is deprecated, use MuleMessage.getInboundProperty() instead. This method will be removed in the next point release");
1573 return getInboundProperty(name, defaultValue);
1574 }
1575
1576
1577
1578
1579 @Deprecated
1580 public double getDoubleProperty(String name, double defaultValue)
1581 {
1582 assertAccess(READ);
1583 logger.warn("MuleMessage.getDoubleProperty() method is deprecated, use MuleMessage.getInboundProperty() instead. This method will be removed in the next point release");
1584 return getInboundProperty(name, defaultValue);
1585 }
1586
1587
1588
1589
1590 @Deprecated
1591 public boolean getBooleanProperty(String name, boolean defaultValue)
1592 {
1593 assertAccess(READ);
1594 logger.warn("MuleMessage.getBooleanProperty() method is deprecated, use MuleMessage.getInboundProperty() instead. This method will be removed in the next point release");
1595 return getInboundProperty(name, defaultValue);
1596 }
1597
1598
1599
1600
1601 @Deprecated
1602 public void setBooleanProperty(String name, boolean value)
1603 {
1604 assertAccess(WRITE);
1605 logger.warn("MuleMessage.setBooleanProperty() method is deprecated, use MuleMessage.setOutboundProperty() instead. This method will be removed in the next point release");
1606 setOutboundProperty(name, value);
1607 }
1608
1609
1610
1611
1612 @Deprecated
1613 public void setIntProperty(String name, int value)
1614 {
1615 assertAccess(WRITE);
1616 logger.warn("MuleMessage.setIntProperty() method is deprecated, use MuleMessage.setOutboundProperty() instead. This method will be removed in the next point release");
1617 setOutboundProperty(name, value);
1618 }
1619
1620
1621
1622
1623 @Deprecated
1624 public void setLongProperty(String name, long value)
1625 {
1626 assertAccess(WRITE);
1627 logger.warn("MuleMessage.setLongProperty() method is deprecated, use MuleMessage.setOutboundProperty() instead. This method will be removed in the next point release");
1628 setOutboundProperty(name, value);
1629 }
1630
1631
1632
1633
1634 @Deprecated
1635 public void setDoubleProperty(String name, double value)
1636 {
1637 assertAccess(WRITE);
1638 logger.warn("MuleMessage.setDoubleProperty() method is deprecated, use MuleMessage.setOutboundProperty() instead. This method will be removed in the next point release");
1639 setOutboundProperty(name, value);
1640 }
1641
1642
1643
1644
1645 @Deprecated
1646 public String getStringProperty(String name, String defaultValue)
1647 {
1648 assertAccess(READ);
1649 logger.warn("MuleMessage.getStringProperty() method is deprecated, use MuleMessage.getInboundProperty() instead. This method will be removed in the next point release");
1650 return getInboundProperty(name, defaultValue);
1651 }
1652
1653
1654
1655
1656 @Deprecated
1657 public void setStringProperty(String name, String value)
1658 {
1659 assertAccess(WRITE);
1660 logger.warn("MuleMessage.setStringProperty() method is deprecated, use MuleMessage.setOutboundProperty() instead. This method will be removed in the next point release");
1661 setOutboundProperty(name, value);
1662 }
1663
1664
1665
1666
1667 @SuppressWarnings("unchecked")
1668 public <T> T findPropertyInSpecifiedScopes(String name, PropertyScope... scopesToSearch)
1669 {
1670 for (PropertyScope scope : scopesToSearch)
1671 {
1672 Object result = getProperty(name, scope);
1673 if (result != null)
1674 {
1675 return (T) result;
1676 }
1677 }
1678 return null;
1679 }
1680
1681
1682
1683
1684 public MuleMessage createInboundMessage() throws Exception
1685 {
1686 DefaultMuleMessage newMessage = new DefaultMuleMessage(getPayload(), this, getMuleContext());
1687 copyToInbound(newMessage);
1688 return newMessage;
1689 }
1690
1691
1692
1693
1694 protected void copyToInbound(DefaultMuleMessage newMessage) throws Exception
1695 {
1696
1697
1698
1699
1700 Map<String, DataHandler> attachments = new HashMap<String, DataHandler>(3);
1701 for (String name : getOutboundAttachmentNames())
1702 {
1703 attachments.put(name, getOutboundAttachment(name));
1704 }
1705
1706 Map<String, Object> properties = new HashMap<String, Object>(3);
1707 for (String name : getOutboundPropertyNames())
1708 {
1709 properties.put(name, getOutboundProperty(name));
1710 }
1711
1712 newMessage.clearProperties(PropertyScope.INBOUND);
1713 newMessage.clearProperties(PropertyScope.INVOCATION);
1714 newMessage.clearProperties(PropertyScope.OUTBOUND);
1715
1716 for (String s : properties.keySet())
1717 {
1718 newMessage.setInboundProperty(s, properties.get(s));
1719 }
1720
1721 newMessage.inboundAttachments.clear();
1722 newMessage.outboundAttachments.clear();
1723
1724 for (String s : attachments.keySet())
1725 {
1726 newMessage.addInboundAttachment(s, attachments.get(s));
1727 }
1728
1729 newMessage.setCorrelationId(getCorrelationId());
1730 newMessage.setCorrelationGroupSize(getCorrelationGroupSize());
1731 newMessage.setCorrelationSequence(getCorrelationSequence());
1732 newMessage.setReplyTo(getReplyTo());
1733 newMessage.setEncoding(getEncoding());
1734 }
1735 }