View Javadoc

1   /*
2    * $Id: DefaultMuleEvent.java 22700 2011-08-19 01:24:24Z dfeist $
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.DefaultMuleException;
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.MuleSession;
19  import org.mule.api.ThreadSafeAccess;
20  import org.mule.api.config.MuleProperties;
21  import org.mule.api.construct.FlowConstruct;
22  import org.mule.api.construct.Pipeline;
23  import org.mule.api.endpoint.InboundEndpoint;
24  import org.mule.api.security.Credentials;
25  import org.mule.api.transformer.DataType;
26  import org.mule.api.transformer.TransformerException;
27  import org.mule.api.transport.PropertyScope;
28  import org.mule.api.transport.ReplyToHandler;
29  import org.mule.config.i18n.CoreMessages;
30  import org.mule.management.stats.ProcessingTime;
31  import org.mule.processor.strategy.SynchronousProcessingStrategy;
32  import org.mule.security.MuleCredentials;
33  import org.mule.session.DefaultMuleSession;
34  import org.mule.transformer.types.DataTypeFactory;
35  import org.mule.transport.DefaultReplyToHandler;
36  import org.mule.util.store.DeserializationPostInitialisable;
37  
38  import java.io.OutputStream;
39  import java.net.URI;
40  import java.util.EventObject;
41  import java.util.Iterator;
42  
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  
46  /**
47   * <code>DefaultMuleEvent</code> represents any data event occurring in the Mule environment. All data sent or
48   * received within the Mule environment will be passed between components as an MuleEvent.
49   * <p/>
50   * The MuleEvent holds some data and provides helper methods for obtaining the data in a format that the
51   * receiving Mule component understands. The event can also maintain any number of properties that can be set
52   * and retrieved by Mule components.
53   */
54  
55  public class DefaultMuleEvent extends EventObject
56      implements MuleEvent, ThreadSafeAccess, DeserializationPostInitialisable
57  {
58      private static final long serialVersionUID = 1L;
59  
60      private static Log logger = LogFactory.getLog(DefaultMuleEvent.class);
61  
62      /** Immutable MuleEvent state **/
63  
64      /** The Universally Unique ID for the event */
65      private final String id;
66      private final MuleMessage message;
67      private final MuleSession session;
68  
69      private final Credentials credentials;
70      private final String encoding;
71      private final MessageExchangePattern exchangePattern;
72      private final URI messageSourceURI;
73      private final String messageSourceName;
74      private final ReplyToHandler replyToHandler;
75      private final boolean transacted;
76      private final boolean synchronous;
77  
78      /** Mutable MuleEvent state **/
79      private boolean stopFurtherProcessing = false;
80      private int timeout = TIMEOUT_NOT_SET_VALUE;
81      private transient ResponseOutputStream outputStream;
82      private final ProcessingTime processingTime;
83      private Object replyToDestination;
84  
85      protected String[] ignoredPropertyOverrides = new String[]{MuleProperties.MULE_METHOD_PROPERTY};
86  
87      // Constructors
88  
89      /**
90       * Constructor used to create a message with no message source with minimal arguments
91       */
92      public DefaultMuleEvent(MuleMessage message, MessageExchangePattern exchangePattern, MuleSession session)
93      {
94          this(message, exchangePattern, session, message.getMuleContext()
95              .getConfiguration()
96              .getDefaultResponseTimeout(), null, null);
97      }
98  
99      /**
100      * Constructor used to create a message with no message source with minimal arguments and
101      * ResponseOutputStream
102      */
103     public DefaultMuleEvent(MuleMessage message,
104                             MessageExchangePattern exchangePattern,
105                             MuleSession session,
106                             ResponseOutputStream outputStream)
107     {
108         this(message, exchangePattern, session, message.getMuleContext()
109             .getConfiguration()
110             .getDefaultResponseTimeout(), null, outputStream);
111     }
112 
113     /**
114      * Constructor used to create a message with no message source with all additional arguments
115      */
116     public DefaultMuleEvent(MuleMessage message,
117                             MessageExchangePattern exchangePattern,
118                             MuleSession session,
119                             int timeout,
120                             Credentials credentials,
121                             ResponseOutputStream outputStream)
122     {
123         this(message, URI.create("none"), exchangePattern, session, timeout, credentials, outputStream);
124     }
125 
126     /**
127      * Constructor used to create a message with a uri that idendifies the message source with minimal
128      * arguments
129      */
130     public DefaultMuleEvent(MuleMessage message,
131                             URI messageSourceURI,
132                             MessageExchangePattern exchangePattern,
133                             MuleSession session)
134     {
135         this(message, messageSourceURI, exchangePattern, session, message.getMuleContext()
136             .getConfiguration()
137             .getDefaultResponseTimeout(), null, null);
138     }
139 
140     /**
141      * Constructor used to create a message with a uri that idendifies the message source with minimal
142      * arguments and ResponseOutputStream
143      */
144     public DefaultMuleEvent(MuleMessage message,
145                             URI messageSourceURI,
146                             MessageExchangePattern exchangePattern,
147                             MuleSession session,
148                             ResponseOutputStream outputStream)
149     {
150         this(message, messageSourceURI, exchangePattern, session, message.getMuleContext()
151             .getConfiguration()
152             .getDefaultResponseTimeout(), null, outputStream);
153     }
154 
155     /**
156      * Constructor used to create a message with a identifiable message source with all additional arguments
157      */
158     public DefaultMuleEvent(MuleMessage message,
159                             URI messageSourceURI,
160                             MessageExchangePattern exchangePattern,
161                             MuleSession session,
162                             int timeout,
163                             Credentials credentials,
164                             ResponseOutputStream outputStream)
165     {
166         super(message.getPayload());
167         this.id = generateEventId(message.getMuleContext());
168         this.message = message;
169         this.session = session;
170         this.exchangePattern = exchangePattern;
171         this.outputStream = outputStream;
172         this.credentials = null;
173         this.encoding = message.getMuleContext().getConfiguration().getDefaultEncoding();
174         this.messageSourceName = messageSourceURI.toString();
175         this.messageSourceURI = messageSourceURI;
176         this.processingTime = ProcessingTime.newInstance(this.session, message.getMuleContext());
177         this.replyToHandler = null;
178         this.replyToDestination = null;
179         this.timeout = timeout;
180         this.transacted = false;
181         this.synchronous = resolveEventSynchronicity();
182     }
183 
184     // Constructors for inbound endpoint
185 
186     public DefaultMuleEvent(MuleMessage message, InboundEndpoint endpoint, MuleSession session)
187     {
188         this(message, endpoint, session, null, null);
189     }
190 
191     public DefaultMuleEvent(MuleMessage message,
192                             InboundEndpoint endpoint,
193                             MuleSession session,
194                             ReplyToHandler replyToHandler,
195                             ResponseOutputStream outputStream)
196     {
197         super(message.getPayload());
198         this.id = generateEventId(message.getMuleContext());
199         this.message = message;
200         this.session = session;
201 
202         this.outputStream = outputStream;
203         this.processingTime = ProcessingTime.newInstance(this.session, message.getMuleContext());
204         this.replyToHandler = replyToHandler;
205         this.credentials = extractCredentials(endpoint);
206         this.encoding = endpoint.getEncoding();
207         this.exchangePattern = endpoint.getExchangePattern();
208         this.messageSourceName = endpoint.getName();
209         this.messageSourceURI = endpoint.getEndpointURI().getUri();
210         this.timeout = endpoint.getResponseTimeout();
211         this.transacted = endpoint.getTransactionConfig().isTransacted();
212         fillProperties(endpoint);
213         this.synchronous = resolveEventSynchronicity();
214     }
215 
216     // Constructors to copy MuleEvent
217 
218     /**
219      * A helper constructor used to rewrite an event payload
220      * 
221      * @param message The message to use as the current payload of the event
222      * @param rewriteEvent the previous event that will be used as a template for this event
223      */
224     public DefaultMuleEvent(MuleMessage message, MuleEvent rewriteEvent)
225     {
226         this(message, rewriteEvent, rewriteEvent.getSession());
227     }
228 
229     public DefaultMuleEvent(MuleMessage message, MuleEvent rewriteEvent, boolean synchronus)
230     {
231         this(message, rewriteEvent, rewriteEvent.getSession(), synchronus);
232     }
233 
234     /**
235      * A helper constructor used to rewrite an event payload
236      * 
237      * @param message The message to use as the current payload of the event
238      * @param rewriteEvent the previous event that will be used as a template for this event
239      */
240     public DefaultMuleEvent(MuleMessage message, MuleEvent rewriteEvent, MuleSession session)
241     {
242         this(message, rewriteEvent, session, rewriteEvent.isSynchronous());
243     }
244 
245     protected DefaultMuleEvent(MuleMessage message,
246                             MuleEvent rewriteEvent,
247                             MuleSession session,
248                             boolean synchronous)
249     {
250         super(message.getPayload());
251         this.id = rewriteEvent.getId();
252         this.message = message;
253         this.session = session;
254 
255         this.credentials = rewriteEvent.getCredentials();
256         this.encoding = rewriteEvent.getEncoding();
257         this.exchangePattern = rewriteEvent.getExchangePattern();
258         this.messageSourceName = rewriteEvent.getMessageSourceName();
259         this.messageSourceURI = rewriteEvent.getMessageSourceURI();
260         this.outputStream = (ResponseOutputStream) rewriteEvent.getOutputStream();
261         if (rewriteEvent instanceof DefaultMuleEvent)
262         {
263             this.processingTime = ((DefaultMuleEvent) rewriteEvent).processingTime;
264         }
265         else
266         {
267             this.processingTime = ProcessingTime.newInstance(this.session, message.getMuleContext());
268         }
269         this.replyToHandler = rewriteEvent.getReplyToHandler();
270         this.replyToDestination = rewriteEvent.getReplyToDestination();
271         this.timeout = rewriteEvent.getTimeout();
272         this.transacted = rewriteEvent.isTransacted();
273         this.synchronous = synchronous;
274     }
275 
276     // Constructor with everything just in case
277 
278     public DefaultMuleEvent(MuleMessage message,
279                             URI messageSourceURI,
280                             String messageSourceName,
281                             MessageExchangePattern exchangePattern,
282                             MuleSession session,
283                             int timeout,
284                             Credentials credentials,
285                             ResponseOutputStream outputStream,
286                             String encoding,
287                             boolean transacted,
288                             boolean synchronous,
289                             Object replyToDestination,
290                             ReplyToHandler replyToHandler)
291     {
292         super(message.getPayload());
293         this.id = generateEventId(message.getMuleContext());
294         this.message = message;
295         this.session = session;
296         this.credentials = credentials;
297         this.encoding = encoding;
298         this.exchangePattern = exchangePattern;
299         this.messageSourceURI = messageSourceURI;
300         this.messageSourceName = messageSourceName;
301         this.processingTime = ProcessingTime.newInstance(this.session, message.getMuleContext());
302         this.replyToHandler = replyToHandler;
303         this.transacted = transacted;
304         this.synchronous = synchronous;
305         this.timeout = timeout;
306         this.outputStream = outputStream;
307         this.replyToDestination = replyToDestination;
308     }
309 
310     protected boolean resolveEventSynchronicity()
311     {
312         boolean syncProcessingStrategy = false;
313         if (session.getFlowConstruct() != null && session.getFlowConstruct() instanceof Pipeline)
314         {
315             syncProcessingStrategy = ((Pipeline) session.getFlowConstruct()).getProcessingStrategy()
316                 .getClass()
317                 .equals(SynchronousProcessingStrategy.class);
318         }
319         return transacted
320                || exchangePattern.hasResponse()
321                || (Boolean) message.getProperty(MuleProperties.MULE_FORCE_SYNC_PROPERTY,
322                    PropertyScope.INBOUND, Boolean.FALSE) || syncProcessingStrategy;
323     }
324 
325     protected void fillProperties(InboundEndpoint endpoint)
326     {
327         if (endpoint != null && endpoint.getProperties() != null)
328         {
329             for (Iterator<?> iterator = endpoint.getProperties().keySet().iterator(); iterator.hasNext();)
330             {
331                 String prop = (String) iterator.next();
332 
333                 // don't overwrite property on the message
334                 if (!ignoreProperty(prop))
335                 {
336                     // inbound endpoint properties are in the invocation scope
337                     Object value = endpoint.getProperties().get(prop);
338                     message.setInvocationProperty(prop, value);
339                 }
340             }
341         }
342     }
343 
344     /**
345      * This method is used to determine if a property on the previous event should be ignored for the next
346      * event. This method is here because we don't have proper scoped handling of meta data yet The rules are
347      * <ol>
348      * <li>If a property is already set on the current event don't overwrite with the previous event value
349      * <li>If the property name appears in the ignoredPropertyOverrides list, then we always set it on the new
350      * event
351      * </ol>
352      * 
353      * @param key The name of the property to ignore
354      * @return true if the property should be ignored, false otherwise
355      */
356     protected boolean ignoreProperty(String key)
357     {
358         if (key == null || key.startsWith(MuleProperties.ENDPOINT_PROPERTY_PREFIX))
359         {
360             return true;
361         }
362 
363         for (int i = 0; i < ignoredPropertyOverrides.length; i++)
364         {
365             if (key.equals(ignoredPropertyOverrides[i]))
366             {
367                 return false;
368             }
369         }
370 
371         return null != message.getOutboundProperty(key);
372     }
373 
374     protected Credentials extractCredentials(InboundEndpoint endpoint)
375     {
376         if (null != endpoint && null != endpoint.getEndpointURI()
377             && null != endpoint.getEndpointURI().getUserInfo())
378         {
379             final String userName = endpoint.getEndpointURI().getUser();
380             final String password = endpoint.getEndpointURI().getPassword();
381             if (password != null && userName != null)
382             {
383                 return new MuleCredentials(userName, password.toCharArray());
384             }
385         }
386         return null;
387     }
388 
389     @Override
390     public Credentials getCredentials()
391     {
392         MuleCredentials creds = message.getOutboundProperty(MuleProperties.MULE_CREDENTIALS_PROPERTY);
393         return (credentials != null ? credentials : creds);
394     }
395 
396     @Override
397     public MuleMessage getMessage()
398     {
399         return message;
400     }
401 
402     @Override
403     public byte[] getMessageAsBytes() throws DefaultMuleException
404     {
405         try
406         {
407             return message.getPayloadAsBytes();
408         }
409         catch (Exception e)
410         {
411             throw new DefaultMuleException(CoreMessages.cannotReadPayloadAsBytes(message.getPayload()
412                 .getClass()
413                 .getName()), e);
414         }
415     }
416 
417     @Override
418     @SuppressWarnings("cast")
419     public <T> T transformMessage(Class<T> outputType) throws TransformerException
420     {
421         return (T) transformMessage(DataTypeFactory.create(outputType));
422     }
423 
424     @Override
425     public <T> T transformMessage(DataType<T> outputType) throws TransformerException
426     {
427         if (outputType == null)
428         {
429             throw new TransformerException(CoreMessages.objectIsNull("outputType"));
430         }
431         return message.getPayload(outputType);
432     }
433 
434     /**
435      * This method will attempt to convert the transformed message into an array of bytes It will first check
436      * if the result of the transformation is a byte array and return that. Otherwise if the the result is a
437      * string it will serialized the CONTENTS of the string not the String object. finally it will check if
438      * the result is a Serializable object and convert that to an array of bytes.
439      * 
440      * @return a byte[] representation of the message
441      * @throws TransformerException if an unsupported encoding is being used or if the result message is not a
442      *             String byte[] or Seializable object
443      * @deprecated use {@link #transformMessage(org.mule.api.transformer.DataType)} instead
444      */
445     @Override
446     @Deprecated
447     public byte[] transformMessageToBytes() throws TransformerException
448     {
449         return transformMessage(DataType.BYTE_ARRAY_DATA_TYPE);
450     }
451 
452     /**
453      * Returns the message transformed into it's recognised or expected format and then into a String. The
454      * transformer used is the one configured on the endpoint through which this event was received.
455      * 
456      * @return the message transformed into it's recognised or expected format as a Strings.
457      * @throws org.mule.api.transformer.TransformerException if a failure occurs in the transformer
458      * @see org.mule.api.transformer.Transformer
459      */
460     @Override
461     public String transformMessageToString() throws TransformerException
462     {
463         return transformMessage(DataTypeFactory.createWithEncoding(String.class, getEncoding()));
464     }
465 
466     @Override
467     public String getMessageAsString() throws MuleException
468     {
469         return getMessageAsString(getEncoding());
470     }
471 
472     /**
473      * Returns the message contents for logging
474      * 
475      * @param encoding the encoding to use when converting bytes to a string, if necessary
476      * @return the message contents as a string
477      * @throws org.mule.api.MuleException if the message cannot be converted into a string
478      */
479     @Override
480     public String getMessageAsString(String encoding) throws MuleException
481     {
482         try
483         {
484             return message.getPayloadForLogging(encoding);
485         }
486         catch (Exception e)
487         {
488             throw new DefaultMuleException(CoreMessages.cannotReadPayloadAsString(message.getClass()
489                 .getName()), e);
490         }
491     }
492 
493     @Override
494     public String getId()
495     {
496         return id;
497     }
498 
499     /**
500      * @see #getMessage()
501      * @deprecated use appropriate scope-aware calls on the MuleMessage (via event.getMessage())
502      */
503     @Override
504     @Deprecated
505     public Object getProperty(String name)
506     {
507         throw new UnsupportedOperationException(
508             "Method's behavior has changed in Mule 3, use "
509                             + "event.getMessage() and suitable scope-aware property access "
510                             + "methods on it");
511     }
512 
513     /**
514      * @see #getMessage()
515      * @deprecated use appropriate scope-aware calls on the MuleMessage (via event.getMessage())
516      */
517     @Override
518     @Deprecated
519     public Object getProperty(String name, Object defaultValue)
520     {
521         throw new UnsupportedOperationException(
522             "Method's behavior has changed in Mule 3, use "
523                             + "event.getMessage() and suitable scope-aware property access "
524                             + "methods on it");
525     }
526 
527     @Override
528     public String toString()
529     {
530         StringBuffer buf = new StringBuffer(64);
531         buf.append("MuleEvent: ").append(getId());
532         buf.append(", stop processing=").append(isStopFurtherProcessing());
533         buf.append(", ").append(messageSourceURI);
534 
535         return buf.toString();
536     }
537 
538     protected String generateEventId(MuleContext context)
539     {
540         return context.getUniqueIdString();
541     }
542 
543     @Override
544     public MuleSession getSession()
545     {
546         return session;
547     }
548 
549     /**
550      * Gets the recipient service of this event
551      */
552     @Override
553     public FlowConstruct getFlowConstruct()
554     {
555         return session.getFlowConstruct();
556     }
557 
558     /**
559      * Determines whether the default processing for this event will be executed
560      * 
561      * @return Returns the stopFurtherProcessing.
562      */
563     @Override
564     public boolean isStopFurtherProcessing()
565     {
566         return stopFurtherProcessing;
567     }
568 
569     /**
570      * Setting this parameter will stop the Mule framework from processing this event in the standard way.
571      * This allow for client code to override default behaviour. The common reasons for doing this are - 1.
572      * The service has more than one send endpoint configured; the service must dispatch to other prviders
573      * programmatically by using the service on the current event 2. The service doesn't send the current
574      * event out through a endpoint. i.e. the processing of the event stops in the uMO.
575      * 
576      * @param stopFurtherProcessing The stopFurtherProcessing to set.
577      */
578     @Override
579     public void setStopFurtherProcessing(boolean stopFurtherProcessing)
580     {
581         this.stopFurtherProcessing = stopFurtherProcessing;
582     }
583 
584     @Override
585     public boolean equals(Object o)
586     {
587         if (this == o)
588         {
589             return true;
590         }
591         if (!(o instanceof DefaultMuleEvent))
592         {
593             return false;
594         }
595 
596         final DefaultMuleEvent event = (DefaultMuleEvent) o;
597 
598         if (message != null ? !message.equals(event.message) : event.message != null)
599         {
600             return false;
601         }
602         return id.equals(event.id);
603     }
604 
605     @Override
606     public int hashCode()
607     {
608         return 29 * id.hashCode() + (message != null ? message.hashCode() : 0);
609     }
610 
611     @Override
612     public int getTimeout()
613     {
614         if (timeout == TIMEOUT_NOT_SET_VALUE)
615         {
616             return message.getMuleContext().getConfiguration().getDefaultResponseTimeout();
617         }
618         else
619         {
620             return timeout;
621         }
622     }
623 
624     @Override
625     public void setTimeout(int timeout)
626     {
627         if (timeout >= 0)
628         {
629             this.timeout = timeout;
630         }
631     }
632 
633     /**
634      * An output stream can optionally be used to write response data to an incoming message.
635      * 
636      * @return an output strem if one has been made available by the message receiver that received the
637      *         message
638      */
639     @Override
640     public OutputStream getOutputStream()
641     {
642         return outputStream;
643     }
644 
645     /**
646      * Invoked after deserialization. This is called when the marker interface
647      * {@link org.mule.util.store.DeserializationPostInitialisable} is used. This will get invoked after the
648      * object has been deserialized passing in the current MuleContext when using either
649      * {@link org.mule.transformer.wire.SerializationWireFormat},
650      * {@link org.mule.transformer.wire.SerializedMuleMessageWireFormat} or the
651      * {@link org.mule.transformer.simple.ByteArrayToSerializable} transformer.
652      * 
653      * @param muleContext the current muleContext instance
654      * @throws MuleException if there is an error initializing
655      */
656     @SuppressWarnings({"unused", "unchecked"})
657     private void initAfterDeserialisation(MuleContext muleContext) throws MuleException
658     {
659         if (session instanceof DefaultMuleSession)
660         {
661             ((DefaultMuleSession) session).initAfterDeserialisation(muleContext);
662         }
663         if (message instanceof DefaultMuleMessage)
664         {
665             ((DefaultMuleMessage) message).initAfterDeserialisation(muleContext);
666         }
667         if (replyToHandler instanceof DefaultReplyToHandler)
668         {
669             ((DefaultReplyToHandler) replyToHandler).initAfterDeserialisation(muleContext);
670         }
671         if (replyToDestination instanceof DeserializationPostInitialisable)
672         {
673             try
674             {
675                 DeserializationPostInitialisable.Implementation.init(replyToDestination, muleContext);
676             }
677             catch (Exception e)
678             {
679                 throw new DefaultMuleException(e);
680             }
681 
682         }
683     }
684 
685     /**
686      * Gets the encoding for this message. First it looks to see if encoding has been set on the endpoint, if
687      * not it will check the message itself and finally it will fall back to the Mule global configuration for
688      * encoding which cannot be null.
689      * 
690      * @return the encoding for the event
691      */
692     @Override
693     public String getEncoding()
694     {
695         if (message.getEncoding() != null)
696         {
697             return message.getEncoding();
698         }
699         else
700         {
701             return encoding;
702         }
703     }
704 
705     @Override
706     public MuleContext getMuleContext()
707     {
708         return message.getMuleContext();
709     }
710 
711     @Override
712     public ThreadSafeAccess newThreadCopy()
713     {
714         if (message instanceof ThreadSafeAccess)
715         {
716             DefaultMuleEvent copy = new DefaultMuleEvent(
717                 (MuleMessage) ((ThreadSafeAccess) message).newThreadCopy(), this);
718             copy.resetAccessControl();
719             return copy;
720         }
721         else
722         {
723             return this;
724         }
725     }
726 
727     @Override
728     public void resetAccessControl()
729     {
730         if (message instanceof ThreadSafeAccess)
731         {
732             ((ThreadSafeAccess) message).resetAccessControl();
733         }
734     }
735 
736     @Override
737     public void assertAccess(boolean write)
738     {
739         if (message instanceof ThreadSafeAccess)
740         {
741             ((ThreadSafeAccess) message).assertAccess(write);
742         }
743     }
744 
745     @Override
746     @Deprecated
747     public Object transformMessage() throws TransformerException
748     {
749         logger.warn("Deprecation warning: MuleEvent.transformMessage does nothing in Mule 3.x.  The message is already transformed before the event reaches a component");
750         return message.getPayload();
751     }
752 
753     @Override
754     public ProcessingTime getProcessingTime()
755     {
756         return processingTime;
757     }
758 
759     @Override
760     public MessageExchangePattern getExchangePattern()
761     {
762         return exchangePattern;
763     }
764 
765     @Override
766     public boolean isTransacted()
767     {
768         return transacted;
769     }
770 
771     @Override
772     public URI getMessageSourceURI()
773     {
774         return messageSourceURI;
775     }
776 
777     @Override
778     public String getMessageSourceName()
779     {
780         return messageSourceName;
781     }
782 
783     @Override
784     public ReplyToHandler getReplyToHandler()
785     {
786         return replyToHandler;
787     }
788 
789     @Override
790     public Object getReplyToDestination()
791     {
792         return replyToDestination;
793     }
794 
795     @Override
796     public void captureReplyToDestination()
797     {
798         if (message != null)
799         {
800             replyToDestination = message.getReplyTo();
801             message.setReplyTo(null);
802         }
803     }
804 
805     @Override
806     public boolean isSynchronous()
807     {
808         return synchronous;
809     }
810 }