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