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