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