View Javadoc

1   /*
2    * $Id: OptimisedMuleProxy.java 7976 2007-08-21 14:26:13Z 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.impl.model.seda.optimised;
12  
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.impl.ImmutableMuleDescriptor;
15  import org.mule.impl.MuleDescriptor;
16  import org.mule.impl.MuleMessage;
17  import org.mule.impl.RequestContext;
18  import org.mule.impl.model.MuleProxy;
19  import org.mule.management.stats.ComponentStatistics;
20  import org.mule.management.stats.SedaComponentStatistics;
21  import org.mule.umo.MessagingException;
22  import org.mule.umo.UMOEvent;
23  import org.mule.umo.UMOEventContext;
24  import org.mule.umo.UMOException;
25  import org.mule.umo.UMOImmutableDescriptor;
26  import org.mule.umo.UMOMessage;
27  import org.mule.umo.lifecycle.Callable;
28  import org.mule.umo.lifecycle.Disposable;
29  import org.mule.umo.lifecycle.Startable;
30  import org.mule.umo.lifecycle.Stoppable;
31  import org.mule.umo.model.ModelException;
32  import org.mule.util.ObjectPool;
33  import org.mule.util.queue.QueueSession;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  
38  /**
39   * <code>MuleProxy</code> is a proxy to a UMO. It is a poolable object that can be
40   * executed in its own thread.
41   */
42  
43  public class OptimisedMuleProxy implements MuleProxy
44  {
45      /**
46       * logger used by this class
47       */
48      private static Log logger = LogFactory.getLog(OptimisedMuleProxy.class);
49  
50      /**
51       * Holds the current event being processed
52       */
53      private UMOEvent event;
54  
55      /**
56       * holds the UMO descriptor
57       */
58      private ImmutableMuleDescriptor descriptor;
59  
60      /**
61       * Determines if the proxy is suspended
62       */
63      private boolean suspended = true;
64  
65      private ObjectPool proxyPool;
66  
67      private ComponentStatistics stat = null;
68  
69      private Callable umo;
70  
71      private boolean started = false;
72      private boolean disposed = false;
73  
74      /**
75       * Constructs a Proxy using the UMO's AbstractMessageDispatcher and the UMO
76       * itself
77       * 
78       * @param component the underlying object that with receive events
79       * @param descriptor the UMOComponent descriptor associated with the component
80       */
81      public OptimisedMuleProxy(Callable component, MuleDescriptor descriptor, ObjectPool proxyPool)
82          throws UMOException
83      {
84          this.descriptor = new ImmutableMuleDescriptor(descriptor);
85          this.proxyPool = proxyPool;
86          umo = component;
87      }
88  
89      public void start() throws UMOException
90      {
91          checkDisposed();
92          if (!started && umo instanceof Startable)
93          {
94              try
95              {
96                  ((Startable) umo).start();
97                  started = true;
98              }
99              catch (Exception e)
100             {
101                 throw new ModelException(
102                     CoreMessages.failedToStart("Component '" + descriptor.getName() + "'"), e);
103             }
104         }
105 
106     }
107 
108     public boolean isStarted()
109     {
110         return started;
111     }
112 
113     public void stop() throws UMOException
114     {
115         checkDisposed();
116 
117         if (started && umo instanceof Stoppable)
118         {
119             started = false;
120             try
121             {
122                 ((Stoppable) umo).stop();
123             }
124             catch (Exception e)
125             {
126                 throw new ModelException(
127                     CoreMessages.failedToStop("Component '" + descriptor.getName() + "'"), e);
128             }
129         }
130     }
131 
132     public void dispose()
133     {
134         checkDisposed();
135         if (umo instanceof Disposable)
136         {
137             ((Disposable) umo).dispose();
138             disposed = true;
139         }
140     }
141 
142     private void checkDisposed()
143     {
144         if (disposed)
145         {
146             throw new IllegalStateException("Components Disposed Of");
147         }
148     }
149 
150     /**
151      * Sets the current event being processed
152      * 
153      * @param event the event being processed
154      */
155     public void onEvent(QueueSession session, UMOEvent event)
156     {
157         this.event = event;
158     }
159 
160     public ComponentStatistics getStatistics()
161     {
162         return stat;
163     }
164 
165     public void setStatistics(ComponentStatistics stat)
166     {
167         this.stat = stat;
168     }
169 
170     /**
171      * Makes a synchronous call on the UMO
172      * 
173      * @param event the event to pass to the UMO
174      * @return the return event from the UMO
175      * @throws org.mule.umo.UMOException if the call fails
176      */
177     public Object onCall(UMOEvent event) throws UMOException
178     {
179         if (logger.isTraceEnabled())
180         {
181             logger.trace("MuleProxy: sync call for Mule UMO " + descriptor.getName());
182         }
183 
184         UMOMessage returnMessage = null;
185         try
186         {
187             if (event.getEndpoint().canReceive())
188             {
189                 // RequestContext.setEvent(event);
190                 // Object replyTo = event.getMessage().getReplyTo();
191                 // ReplyToHandler replyToHandler = null;
192                 // if (replyTo != null) {
193                 // replyToHandler = ((AbstractConnector)
194                 // event.getEndpoint().getConnector()).getReplyToHandler();
195                 // }
196 
197                 // stats
198                 long startTime = 0;
199                 if (stat.isEnabled())
200                 {
201                     startTime = System.currentTimeMillis();
202                 }
203                 returnMessage = invokeUmo(RequestContext.getEventContext());
204                 // stats
205                 if (stat.isEnabled())
206                 {
207                     stat.addExecutionTime(System.currentTimeMillis() - startTime);
208                 }
209                 // this is the request event
210                 event = RequestContext.getEvent();
211                 if (event.isStopFurtherProcessing())
212                 {
213                     logger.debug("Event stop further processing has been set, no outbound routing will be performed.");
214                 }
215                 if (returnMessage != null && !event.isStopFurtherProcessing())
216                 {
217                     // Map context = RequestContext.clearProperties();
218                     // if (context != null) {
219                     // returnMessage.addProperties(context);
220                     // }
221                     if (descriptor.getOutboundRouter().hasEndpoints())
222                     {
223                         UMOMessage outboundReturnMessage = descriptor.getOutboundRouter().route(
224                             returnMessage, event.getSession(), event.isSynchronous());
225                         if (outboundReturnMessage != null)
226                         {
227                             returnMessage = outboundReturnMessage;
228                         }
229                     }
230                     else
231                     {
232                         logger.debug("Outbound router on component '" + descriptor.getName()
233                                      + "' doesn't have any endpoints configured.");
234                     }
235                 }
236 
237                 // Process Response Router
238                 // if (returnMessage != null && descriptor.getResponseRouter() !=
239                 // null) {
240                 // logger.debug("Waiting for response router message");
241                 // returnMessage =
242                 // descriptor.getResponseRouter().getResponse(returnMessage);
243                 // }
244                 //
245                 // // process repltyTo if there is one
246                 // if (returnMessage != null && replyToHandler != null) {
247                 // String requestor = (String)
248                 // returnMessage.getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY);
249                 // if ((requestor != null && !requestor.equals(descriptor.getName()))
250                 // || requestor == null) {
251                 // replyToHandler.processReplyTo(event, returnMessage, replyTo);
252                 // }
253                 // }
254 
255             }
256             else
257             {
258                 returnMessage = event.getSession().sendEvent(event);
259                 // processReplyTo(returnMessage);
260             }
261 
262             // stats
263             if (stat.isEnabled())
264             {
265                 stat.incSentEventSync();
266             }
267         }
268         catch (Exception e)
269         {
270             event.getSession().setValid(false);
271             if (e instanceof UMOException)
272             {
273                 handleException(e);
274             }
275             else
276             {
277                 handleException(
278                     new MessagingException(
279                         CoreMessages.eventProcessingFailedFor(descriptor.getName()), 
280                         event.getMessage(), e));
281             }
282         }
283         return returnMessage;
284     }
285 
286     protected UMOMessage invokeUmo(UMOEventContext context) throws Exception
287     {
288         Object result = umo.onCall(RequestContext.getEventContext());
289         if (result != null)
290         {
291             if (result instanceof UMOMessage)
292             {
293                 return (UMOMessage) result;
294             }
295             else
296             {
297                 return new MuleMessage(result, context.getMessage());
298             }
299         }
300         return null;
301     }
302 
303     /**
304      * When an exception occurs this method can be called to invoke the configured
305      * UMOExceptionStrategy on the UMO
306      * 
307      * @param exception If the UMOExceptionStrategy implementation fails
308      */
309     public void handleException(Exception exception)
310     {
311         descriptor.getExceptionListener().exceptionThrown(exception);
312     }
313 
314     public String toString()
315     {
316         return "optimised proxy for: " + descriptor.toString();
317     }
318 
319     /**
320      * Determines if the proxy is suspended
321      * 
322      * @return true if the proxy (and the UMO) are suspended
323      */
324     public boolean isSuspended()
325     {
326         return suspended;
327     }
328 
329     /**
330      * Controls the suspension of the UMO event processing
331      */
332     public void suspend()
333     {
334         suspended = true;
335     }
336 
337     /**
338      * Triggers the UMO to resume processing of events if it is suspended
339      */
340     public void resume()
341     {
342         suspended = false;
343     }
344 
345     // private void processReplyTo(UMOMessage returnMessage) throws UMOException
346     // {
347     // if (returnMessage != null && returnMessage.getReplyTo() != null) {
348     // logger.info("sending reply to: " + returnMessage.getReplyTo());
349     // UMOEndpointURI endpointUri = new
350     // MuleEndpointURI(returnMessage.getReplyTo().toString());
351     //
352     // // get the endpointUri for this uri
353     // UMOEndpoint endpoint = MuleEndpoint.getOrCreateEndpointForUri(endpointUri,
354     // UMOEndpoint.ENDPOINT_TYPE_SENDER);
355     //
356     // // Create the replyTo event asynchronous
357     // UMOEvent replyToEvent = new MuleEvent(returnMessage, endpoint,
358     // event.getSession(), false);
359     // // make sure remove the replyTo property as not cause a a forever
360     // // replyto loop
361     // replyToEvent.removeProperty(MuleProperties.MULE_REPLY_TO_PROPERTY);
362     //
363     // // queue the event
364     // onEvent(queueSession, replyToEvent);
365     // logger.info("reply to sent: " + returnMessage.getReplyTo());
366     // if (stat.isEnabled()) {
367     // stat.incSentReplyToEvent();
368     // }
369     // }
370     // }
371 
372     public void run()
373     {
374         if (logger.isTraceEnabled())
375         {
376             logger.trace("MuleProxy: async onEvent for Mule UMO " + descriptor.getName());
377         }
378 
379         try
380         {
381             if (event.getEndpoint().canReceive())
382             {
383                 // dispatch the next receiver
384                 event = RequestContext.setEvent(event);
385                 // Object replyTo = event.getMessage().getReplyTo();
386                 // ReplyToHandler replyToHandler = null;
387                 // if (replyTo != null) {
388                 // replyToHandler = ((AbstractConnector)
389                 // event.getEndpoint().getConnector()).getReplyToHandler();
390                 // }
391                 // InterceptorsInvoker invoker = new
392                 // InterceptorsInvoker(interceptorList, descriptor,
393                 // event.getMessage());
394 
395                 // do stats
396                 long startTime = 0;
397                 if (stat.isEnabled())
398                 {
399                     startTime = System.currentTimeMillis();
400                 }
401                 UMOMessage result = invokeUmo(RequestContext.getEventContext());
402                 if (stat.isEnabled())
403                 {
404                     stat.addExecutionTime(System.currentTimeMillis() - startTime);
405                 }
406                 // processResponse(result, replyTo, replyToHandler);
407                 event = RequestContext.getEvent();
408                 if (result != null && !event.isStopFurtherProcessing())
409                 {
410                     descriptor.getOutboundRouter().route(result, event.getSession(), event.isSynchronous());
411                 }
412 
413                 // process repltyTo if there is one
414                 // if (result != null && replyToHandler != null) {
415                 // String requestor = (String)
416                 // result.getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY);
417                 // if ((requestor != null && !requestor.equals(descriptor.getName()))
418                 // || requestor == null) {
419                 // replyToHandler.processReplyTo(event, result, replyTo);
420                 // }
421                 // }
422             }
423             else
424             {
425                 event.getEndpoint().dispatch(event);
426             }
427 
428             if (stat.isEnabled())
429             {
430                 stat.incSentEventASync();
431             }
432         }
433         catch (Exception e)
434         {
435             event.getSession().setValid(false);
436             if (e instanceof UMOException)
437             {
438                 handleException(e);
439             }
440             else
441             {
442                 handleException(
443                     new MessagingException(
444                         CoreMessages.eventProcessingFailedFor(descriptor.getName()), 
445                         event.getMessage(), e));
446             }
447         }
448         finally
449         {
450 
451             try
452             {
453                 proxyPool.returnObject(this);
454             }
455             catch (Exception e2)
456             {
457                 // TODO MULE-863: If this is an error, do something about it
458                 logger.error("Failed to return proxy: " + e2.getMessage(), e2);
459             }
460             //TODO RM* clean this up
461             if (getStatistics() instanceof SedaComponentStatistics)
462             {
463                 ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
464             }
465         }
466     }
467 
468     public void release()
469     {
470         // nothing to do
471     }
472 
473     public UMOImmutableDescriptor getDescriptor()
474     {
475         return descriptor;
476     }
477 }