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