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