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