View Javadoc

1   /*
2    * $Id: DefaultMuleEventContext.java 11433 2008-03-20 03:43:57Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.FutureMessageResult;
14  import org.mule.api.MuleContext;
15  import org.mule.api.MuleEvent;
16  import org.mule.api.MuleEventContext;
17  import org.mule.api.MuleException;
18  import org.mule.api.MuleMessage;
19  import org.mule.api.MuleSession;
20  import org.mule.api.config.MuleProperties;
21  import org.mule.api.endpoint.EndpointURI;
22  import org.mule.api.endpoint.InboundEndpoint;
23  import org.mule.api.endpoint.OutboundEndpoint;
24  import org.mule.api.service.Service;
25  import org.mule.api.transaction.Transaction;
26  import org.mule.api.transaction.TransactionException;
27  import org.mule.api.transformer.TransformerException;
28  import org.mule.config.i18n.CoreMessages;
29  import org.mule.transaction.TransactionCoordination;
30  
31  import java.io.OutputStream;
32  
33  import edu.emory.mathcs.backport.java.util.concurrent.Callable;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  
38  /**
39   * <code>DefaultMuleEventContext</code> is the context object for the current request.
40   * Using the context, developers can send/dispatch/receive events programmatically as
41   * well as manage transactions.
42   */
43  public class DefaultMuleEventContext implements MuleEventContext
44  {
45      /**
46       * logger used by this class
47       */
48      protected static final Log logger = LogFactory.getLog(DefaultMuleEventContext.class);
49  
50      private final MuleEvent event;
51      private final MuleSession session;
52  
53      public DefaultMuleEventContext(MuleEvent event)
54      {
55          this.event = event;
56          this.session = event.getSession();
57      }
58  
59      /**
60       * Returns the message payload for this event
61       * 
62       * @return the message payload for this event
63       */
64      public MuleMessage getMessage()
65      {
66          return event.getMessage();
67      }
68  
69      /**
70       * Reterns the conents of the message as a byte array.
71       * 
72       * @return the conents of the message as a byte array
73       * @throws org.mule.api.MuleException if the message cannot be converted into an
74       *             array of bytes
75       */
76      public byte[] getMessageAsBytes() throws MuleException
77      {
78          return event.getMessageAsBytes();
79      }
80  
81      /**
82       * Returns the message transformed into it's recognised or expected format. The
83       * transformer used is the one configured on the endpoint through which this
84       * event was received.
85       * 
86       * @return the message transformed into it's recognised or expected format.
87       * @throws org.mule.api.transformer.TransformerException if a failure occurs in
88       *             the transformer
89       * @see org.mule.api.transformer.Transformer
90       */
91      public Object transformMessage() throws TransformerException
92      {
93          return event.transformMessage();
94      }
95  
96      /**
97       * Returns the message transformed into its recognised or expected format. The
98       * transformer used is the one configured on the endpoint through which this
99       * event was received.
100      * 
101      * @param expectedType The class type required for the return object. This param
102      *            just provides a convienient way to manage type casting of
103      *            transformed objects
104      * @return the message transformed into it's recognised or expected format.
105      * @throws org.mule.api.transformer.TransformerException if a failure occurs or
106      *             if the return type is not the same as the expected type in the
107      *             transformer
108      * @see org.mule.api.transformer.Transformer
109      */
110     public Object transformMessage(Class expectedType) throws TransformerException
111     {
112         return event.transformMessage(expectedType);
113     }
114 
115     /**
116      * Returns the message transformed into it's recognised or expected format and
117      * then into an array of bytes. The transformer used is the one configured on the
118      * endpoint through which this event was received.
119      * 
120      * @return the message transformed into it's recognised or expected format as an
121      *         array of bytes.
122      * @throws org.mule.api.transformer.TransformerException if a failure occurs in
123      *             the transformer
124      * @see org.mule.api.transformer.Transformer
125      */
126     public byte[] transformMessageToBytes() throws TransformerException
127     {
128         return event.transformMessageToBytes();
129     }
130 
131     /**
132      * Returns the message contents as a string
133      * 
134      * @return the message contents as a string
135      * @throws org.mule.api.MuleException if the message cannot be converted into a
136      *             string
137      */
138     public String getMessageAsString(String encoding) throws MuleException
139     {
140         return event.getMessageAsString(encoding);
141     }
142 
143     /**
144      * Returns the message transformed into it's recognised or expected format and
145      * then into a String. The transformer used is the one configured on the endpoint
146      * through which this event was received. This method will use the default
147      * encoding on the event
148      * 
149      * @return the message transformed into it's recognised or expected format as a
150      *         Strings.
151      * @throws org.mule.api.transformer.TransformerException if a failure occurs in
152      *             the transformer
153      * @see org.mule.api.transformer.Transformer
154      */
155     public String transformMessageToString() throws TransformerException
156     {
157         return event.transformMessageToString();
158     }
159 
160     /**
161      * Returns the message contents as a string This method will use the default
162      * encoding on the event
163      * 
164      * @return the message contents as a string
165      * @throws org.mule.api.MuleException if the message cannot be converted into a
166      *             string
167      */
168     public String getMessageAsString() throws MuleException
169     {
170         return event.getMessageAsString();
171     }
172 
173     /**
174      * Returns the current transaction (if any) for the session
175      * 
176      * @return the current transaction for the session or null if there is no
177      *         transaction in progress
178      */
179     public Transaction getCurrentTransaction()
180     {
181         return TransactionCoordination.getInstance().getTransaction();
182     }
183 
184     public void markTransactionForRollback() throws TransactionException
185     {
186         if (getCurrentTransaction() != null)
187         {
188             getCurrentTransaction().setRollbackOnly();
189         }
190     }
191 
192     /**
193      * This will send an event via the configured outbound router on the service
194      * 
195      * @param message the message to send
196      * @return the result of the send if any
197      * @throws org.mule.api.MuleException if there is no outbound endpoint configured
198      *             on the service or the events fails during dispatch
199      */
200     public MuleMessage sendEvent(Object message) throws MuleException
201     {
202         return sendEvent(new DefaultMuleMessage(message, event.getMessage()));
203     }
204 
205     /**
206      * Depending on the session state this methods either Passes an event
207      * synchronously to the next available Mule UMO in the pool or via the endpoint
208      * configured for the event
209      * 
210      * @param message the event message payload to send
211      * @param endpoint The endpoint to disptch the event through.
212      * @return the return Message from the call or null if there was no result
213      * @throws org.mule.api.MuleException if the event fails to be processed by the
214      *             service or the transport for the endpoint
215      */
216     public MuleMessage sendEvent(MuleMessage message, OutboundEndpoint endpoint) throws MuleException
217     {
218         // If synchronous receive has not been explicitly set, default it to true
219         setRemoteSync(message, endpoint);
220         return session.sendEvent(message, endpoint);
221     }
222 
223     /**
224      * Depending on the session state this methods either Passes an event
225      * synchronously to the next available Mule UMO in the pool or via the endpoint
226      * configured for the event
227      * 
228      * @param message the message payload to send
229      * @return the return Message from the call or null if there was no result
230      * @throws org.mule.api.MuleException if the event fails to be processed by the
231      *             service or the transport for the endpoint
232      */
233     public MuleMessage sendEvent(MuleMessage message) throws MuleException
234     {
235         // If synchronous receive has not been explicitly set, default it to
236         // true
237         setRemoteSync(message, (OutboundEndpoint) event.getEndpoint());
238         return session.sendEvent(message);
239     }
240 
241     /**
242      * Depending on the session state this methods either Passes an event
243      * synchronously to the next available Mule UMO in the pool or via the
244      * endpointUri configured for the event
245      * 
246      * @param message the event message payload to send
247      * @param endpointUri The endpointUri to disptch the event through
248      * @return the return Message from the call or null if there was no result
249      * @throws org.mule.api.MuleException if the event fails to be processed by the
250      *             service or the transport for the endpointUri
251      */
252     public MuleMessage sendEvent(MuleMessage message, EndpointURI endpointUri) throws MuleException
253     {
254         OutboundEndpoint endpoint =
255                 getMuleContext().getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointUri);
256 
257         // If synchronous receive has not been explicitly set, default it to
258         // true
259         setRemoteSync(message, endpoint);
260         return session.sendEvent(message, endpoint);
261     }
262 
263     /**
264      * sends an event request via the configured outbound router for this service.
265      * This method return immediately, but the result of the event invocation
266      * available from the returned a Future result that can be accessed later by the
267      * the returned FutureMessageResult. the Future messageResult can be queried at
268      * any time to check that the invocation has completed. A timeout is associated
269      * with the invocation, which is the maximum time in milli-seconds that the
270      * invocation should take to complete
271      * 
272      * @param message the object that is the payload of the event
273      * @param timeout how long to block in milliseconds waiting for a result
274      * @return the result message if any of the invocation
275      * @throws org.mule.api.MuleException if the dispatch fails or the components or
276      *             transfromers cannot be found
277      * @see org.mule.api.FutureMessageResult
278      */
279     public FutureMessageResult sendEventAsync(final Object message, final int timeout) throws MuleException
280     {
281         Callable callable = new Callable()
282         {
283             public Object call() throws Exception
284             {
285                 MuleMessage umoMessage = new DefaultMuleMessage(message, event.getMessage());
286                 umoMessage.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true);
287                 umoMessage.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout);
288                 return sendEvent(umoMessage);
289             }
290         };
291 
292         FutureMessageResult result = new FutureMessageResult(callable);
293         // TODO MULE-732: use injected ExecutorService
294         result.execute();
295         return result;
296     }
297 
298     /**
299      * sends an event request via the configured outbound router for this service.
300      * This method return immediately, but the result of the event invocation
301      * available from the returned a Future result that can be accessed later by the
302      * the returned FutureMessageResult. the Future messageResult can be queried at
303      * any time to check that the invocation has completed. A timeout is associated
304      * with the invocation, which is the maximum time in milli-seconds that the
305      * invocation should take to complete
306      * 
307      * @param message the MuleMessage of the event
308      * @param timeout how long to block in milliseconds waiting for a result
309      * @return the result message if any of the invocation
310      * @throws org.mule.api.MuleException if the dispatch fails or the components or
311      *             transfromers cannot be found
312      * @see org.mule.api.FutureMessageResult
313      */
314     public FutureMessageResult sendEventAsync(final MuleMessage message, final int timeout)
315         throws MuleException
316     {
317         Callable callable = new Callable()
318         {
319             public Object call() throws Exception
320             {
321                 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true);
322                 message.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout);
323                 return sendEvent(message);
324             }
325         };
326 
327         FutureMessageResult result = new FutureMessageResult(callable);
328         // TODO MULE-732: use injected ExecutorService
329         result.execute();
330         return result;
331     }
332 
333     /**
334      * sends an event request via the configured outbound router for this service.
335      * This method return immediately, but the result of the event invocation
336      * available from the returned a Future result that can be accessed later by the
337      * the returned FutureMessageResult. the Future messageResult can be queried at
338      * any time to check that the invocation has completed. A timeout is associated
339      * with the invocation, which is the maximum time in milli-seconds that the
340      * invocation should take to complete
341      * 
342      * @param message the MuleMessage of the event
343      * @param endpointUri the endpointUri to dispatch to
344      * @param timeout how long to block in milliseconds waiting for a result
345      * @return the result message if any of the invocation
346      * @throws org.mule.api.MuleException if the dispatch fails or the components or
347      *             transfromers cannot be found
348      * @see org.mule.api.FutureMessageResult
349      */
350     public FutureMessageResult sendEventAsync(final MuleMessage message,
351                                               final EndpointURI endpointUri,
352                                               final int timeout) throws MuleException
353     {
354         Callable callable = new Callable()
355         {
356             public Object call() throws Exception
357             {
358                 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true);
359                 message.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout);
360                 return sendEvent(message, endpointUri);
361             }
362         };
363 
364         FutureMessageResult result = new FutureMessageResult(callable);
365         // TODO MULE-732: use injected ExecutorService
366         result.execute();
367         return result;
368     }
369 
370     /**
371      * sends an event request via the configured outbound router for this service.
372      * This method return immediately, but the result of the event invocation
373      * available from the returned a Future result that can be accessed later by the
374      * the returned FutureMessageResult. the Future messageResult can be queried at
375      * any time to check that the invocation has completed. A timeout is associated
376      * with the invocation, which is the maximum time in milli-seconds that the
377      * invocation should take to complete
378      * 
379      * @param message the MuleMessage of the event
380      * @param endpointName The endpoint name to disptch the event through. This will
381      *            be looked up first on the service configuration and then on the
382      *            mule manager configuration
383      * @param timeout how long to block in milliseconds waiting for a result
384      * @return the result message if any of the invocation
385      * @throws org.mule.api.MuleException if the dispatch fails or the components or
386      *             transfromers cannot be found
387      * @see org.mule.api.FutureMessageResult
388      */
389     public FutureMessageResult sendEventAsync(final MuleMessage message,
390                                               final String endpointName,
391                                               final int timeout) throws MuleException
392     {
393         Callable callable = new Callable()
394         {
395             public Object call() throws Exception
396             {
397                 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true);
398                 message.setIntProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, timeout);
399                 return sendEvent(message, endpointName);
400             }
401         };
402 
403         FutureMessageResult result = new FutureMessageResult(callable);
404         // TODO MULE-732: use injected ExecutorService
405         result.execute();
406         return result;
407     }
408 
409     /**
410      * Depending on the session state this methods either Passes an event
411      * synchronously to the next available Mule UMO in the pool or via the endpoint
412      * configured for the event
413      * 
414      * @param message the event message payload to send
415      * @param endpointName The endpoint name to disptch the event through. This will
416      *            be looked up first on the service configuration and then on the
417      *            mule manager configuration
418      * @return the return Message from the call or null if there was no result
419      * @throws org.mule.api.MuleException if the event fails to be processed by the
420      *             service or the transport for the endpoint
421      */
422     public MuleMessage sendEvent(MuleMessage message, String endpointName) throws MuleException
423     {
424         OutboundEndpoint endpoint = RegistryContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointName);
425         setRemoteSync(message, endpoint);
426         return session.sendEvent(message, endpoint);
427     }
428 
429     /**
430      * This will dispatch an event asynchronously via the configured outbound
431      * endpoint on the service for this session
432      * 
433      * @param message payload to dispatch
434      * @throws org.mule.api.MuleException if there is no outbound endpoint configured
435      *             on the service or the events fails during dispatch
436      */
437     public void dispatchEvent(Object message) throws MuleException
438     {
439         session.dispatchEvent(new DefaultMuleMessage(message, event.getMessage()));
440     }
441 
442     /**
443      * This will dispatch an event asynchronously via the configured outbound
444      * endpoint on the service for this session
445      * 
446      * @param message the message to send
447      * @throws org.mule.api.MuleException if there is no outbound endpoint configured
448      *             on the service or the events fails during dispatch
449      */
450     public void dispatchEvent(MuleMessage message) throws MuleException
451     {
452         session.dispatchEvent(message);
453     }
454 
455     /**
456      * Depending on the session state this methods either Passes an event
457      * asynchronously to the next available Mule UMO in the pool or via the
458      * endpointUri configured for the event
459      * 
460      * @param message the event message payload to send
461      * @param endpointUri the endpointUri to dispatc the event to first on the
462      *            service configuration and then on the mule manager configuration
463      * @throws org.mule.api.MuleException if the event fails to be processed by the
464      *             service or the transport for the endpointUri
465      */
466     public void dispatchEvent(MuleMessage message, EndpointURI endpointUri) throws MuleException
467     {
468         OutboundEndpoint endpoint =
469                 getMuleContext().getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointUri);
470         session.dispatchEvent(message, endpoint);
471     }
472 
473     /**
474      * Depending on the session state this methods either Passes an event
475      * asynchronously to the next available Mule UMO in the pool or via the endpoint
476      * configured for the event
477      * 
478      * @param message the event message payload to send
479      * @param endpointName The endpoint name to disptch the event through. This will
480      *            be looked up first on the service configuration and then on the
481      *            mule manager configuration
482      * @throws org.mule.api.MuleException if the event fails to be processed by the
483      *             service or the transport for the endpoint
484      */
485     public void dispatchEvent(MuleMessage message, String endpointName) throws MuleException
486     {
487         session.dispatchEvent(message, endpointName);
488     }
489 
490     /**
491      * Depending on the session state this methods either Passes an event
492      * asynchronously to the next available Mule UMO in the pool or via the endpoint
493      * configured for the event
494      * 
495      * @param message the event message payload to send
496      * @param endpoint The endpoint name to disptch the event through.
497      * @throws org.mule.api.MuleException if the event fails to be processed by the
498      *             service or the transport for the endpoint
499      */
500     public void dispatchEvent(MuleMessage message, OutboundEndpoint endpoint) throws MuleException
501     {
502         session.dispatchEvent(message, endpoint);
503     }
504 
505     /**
506      * Requests a synchronous receive of an event on the service
507      * 
508      * @param endpoint the endpoint identifing the endpointUri on ewhich the event
509      *            will be received
510      * @param timeout time in milliseconds before the request timesout
511      * @return The requested event or null if the request times out
512      * @throws org.mule.api.MuleException if the request operation fails
513      */
514     public MuleMessage requestEvent(InboundEndpoint endpoint, long timeout) throws MuleException
515     {
516         return session.requestEvent(endpoint, timeout);
517     }
518 
519     /**
520      * Requests a synchronous receive of an event on the service
521      * 
522      * @param endpointName the endpoint identifing the endpointUri on ewhich the
523      *            event will be received
524      * @param timeout time in milliseconds before the request timesout
525      * @return The requested event or null if the request times out
526      * @throws org.mule.api.MuleException if the request operation fails
527      */
528     public MuleMessage requestEvent(String endpointName, long timeout) throws MuleException
529     {
530         return session.requestEvent(endpointName, timeout);
531     }
532 
533     /**
534      * Requests a synchronous receive of an event on the service
535      * 
536      * @param endpointUri the endpointUri on which the event will be received
537      * @param timeout time in milliseconds before the request timesout
538      * @return The requested event or null if the request times out
539      * @throws org.mule.api.MuleException if the request operation fails
540      */
541     public MuleMessage requestEvent(EndpointURI endpointUri, long timeout) throws MuleException
542     {
543         InboundEndpoint endpoint =
544                 getMuleContext().getRegistry().lookupEndpointFactory().getInboundEndpoint(endpointUri);
545         return session.requestEvent(endpoint, timeout);
546     }
547 
548     /**
549      * @return the service descriptor of the service that received this event
550      */
551     public Service getService()
552     {
553         return event.getService();
554     }
555 
556     /**
557      * Determines whether the default processing for this event will be executed. By
558      * default, the Mule server will route events according to a components
559      * configuration. The user can override this behaviour by obtaining a reference
560      * to the MuleEvent context, either by implementing
561      * <code>org.mule.api.lifecycle.Callable</code> or calling
562      * <code>RequestContext.getEventContext</code> to obtain the MuleEventContext for
563      * the current thread. The user can programmatically control how events are
564      * dispatched.
565      * 
566      * @return Returns true is the user has set stopFurtherProcessing.
567      * @see org.mule.api.MuleEventContext
568      * @see org.mule.api.lifecycle.Callable
569      */
570     public boolean isStopFurtherProcessing()
571     {
572         return RequestContext.getEvent().isStopFurtherProcessing();
573     }
574 
575     /**
576      * Determines whether the default processing for this event will be executed. By
577      * default, the Mule server will route events according to a components
578      * configuration. The user can override this behaviour by obtaining a reference
579      * to the MuleEvent context, either by implementing
580      * <code>org.mule.api.lifecycle.Callable</code> or calling
581      * <code>UMOManager.getEventContext</code> to obtain the MuleEventContext for
582      * the current thread. The user can programmatically control how events are
583      * dispached.
584      * 
585      * @param stopFurtherProcessing the value to set.
586      */
587     public void setStopFurtherProcessing(boolean stopFurtherProcessing)
588     {
589         event.setStopFurtherProcessing(stopFurtherProcessing);
590     }
591 
592     /**
593      * An outputstream the can optionally be used write response data to an incoming
594      * message.
595      * 
596      * @return an output stream if one has been made available by the message receiver
597      *         that received the message
598      */
599     public OutputStream getOutputStream()
600     {
601         return event.getOutputStream();
602     }
603 
604     /**
605      * Determines whether the was sent synchrounously or not
606      * 
607      * @return true if the event is synchronous
608      */
609     public boolean isSynchronous()
610     {
611         return event.isSynchronous();
612     }
613 
614     public EndpointURI getEndpointURI()
615     {
616         return event.getEndpoint().getEndpointURI();
617     }
618 
619     /**
620      * Returns the transaction for the current event or null if there is no
621      * transaction in progresss
622      * 
623      * @return the transaction for the current event or null if there is no
624      *         transaction in progresss
625      */
626     public Transaction getTransaction()
627     {
628         return TransactionCoordination.getInstance().getTransaction();
629     }
630 
631     /**
632      * Get the timeout value associated with the event
633      * 
634      * @return the timeout for the event
635      */
636     public int getTimeout()
637     {
638         return event.getTimeout();
639     }
640 
641     private void setRemoteSync(MuleMessage message, OutboundEndpoint endpoint)
642     {
643         if (endpoint.isRemoteSync())
644         {
645             if (getTransaction() == null)
646             {
647                 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, true);
648             }
649             else
650             {
651                 throw new IllegalStateException(
652                     CoreMessages.cannotUseTxAndRemoteSync().getMessage());
653             }
654         }
655     }
656 
657     /**
658      * Gets the encoding for the current message. For potocols that send encoding
659      * Information with the message, this method should be overriden to expose the
660      * transport encoding, otherwise the default encoding in the Mule configuration
661      * will be used
662      * 
663      * @return the encoding for this message. This method must never return null
664      */
665     public String getEncoding()
666     {
667         return event.getEncoding();
668     }
669 
670     public MuleSession getSession()
671     {
672         return event.getSession();
673     }
674 
675     public String toString()
676     {
677         return event.toString();
678     }
679 
680     public MuleContext getMuleContext()
681     {
682         return event.getMuleContext();
683     }
684 
685 }