Coverage Report - org.mule.impl.model.seda.SedaComponent
 
Classes in this File Line Coverage Branch Coverage Complexity
SedaComponent
53%
117/222
35%
34/98
3.2
 
 1  
 /*
 2  
  * $Id: SedaComponent.java 11728 2008-05-13 07:31:11Z 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;
 12  
 
 13  
 import org.mule.MuleManager;
 14  
 import org.mule.MuleRuntimeException;
 15  
 import org.mule.config.PoolingProfile;
 16  
 import org.mule.config.QueueProfile;
 17  
 import org.mule.config.ThreadingProfile;
 18  
 import org.mule.config.i18n.CoreMessages;
 19  
 import org.mule.impl.FailedToQueueEventException;
 20  
 import org.mule.impl.MuleDescriptor;
 21  
 import org.mule.impl.MuleEvent;
 22  
 import org.mule.impl.model.AbstractComponent;
 23  
 import org.mule.impl.model.DefaultMuleProxy;
 24  
 import org.mule.impl.model.MuleProxy;
 25  
 import org.mule.management.stats.ComponentStatistics;
 26  
 import org.mule.management.stats.SedaComponentStatistics;
 27  
 import org.mule.umo.ComponentException;
 28  
 import org.mule.umo.UMOEvent;
 29  
 import org.mule.umo.UMOException;
 30  
 import org.mule.umo.UMOMessage;
 31  
 import org.mule.umo.lifecycle.InitialisationException;
 32  
 import org.mule.umo.lifecycle.LifecycleException;
 33  
 import org.mule.umo.manager.UMOWorkManager;
 34  
 import org.mule.util.ObjectPool;
 35  
 import org.mule.util.queue.QueueSession;
 36  
 
 37  
 import java.util.ArrayList;
 38  
 import java.util.List;
 39  
 import java.util.NoSuchElementException;
 40  
 
 41  
 import javax.resource.spi.work.Work;
 42  
 import javax.resource.spi.work.WorkEvent;
 43  
 import javax.resource.spi.work.WorkException;
 44  
 import javax.resource.spi.work.WorkListener;
 45  
 import javax.resource.spi.work.WorkManager;
 46  
 
 47  
 /**
 48  
  * A Seda component runs inside a Seda Model and is responsible for managing a Seda
 49  
  * Queue and thread pool for a Mule sevice component. In Seda terms this is
 50  
  * equivilent to a stage.
 51  
  */
 52  4
 public class SedaComponent extends AbstractComponent implements Work, WorkListener
 53  
 {
 54  
     public static final String QUEUE_PROFILE_PROPERTY = "queueProfile";
 55  
     public static final String POOLING_PROFILE_PROPERTY = "poolingProfile";
 56  
     /**
 57  
      * Serial version/
 58  
      */
 59  
     private static final long serialVersionUID = 7711976708670893015L;
 60  
 
 61  
     /**
 62  
      * A pool of available Mule proxies. If component pooling has been disabled on the
 63  
      * SEDAModel, this pool will be null and the 'componentProxy' will be used.
 64  
      */
 65  
     protected ObjectPool proxyPool;
 66  
 
 67  
     /**
 68  
      * Is created only if component pooling is turned off on the SEDAModel. In this
 69  
      * scenario all requests are serviced by this component, unless
 70  
      * {@link #componentPerRequest} flag is set on the model.
 71  
      */
 72  
     protected MuleProxy componentProxy;
 73  
 
 74  
     protected UMOWorkManager workManager;
 75  
 
 76  
     protected String descriptorQueueName;
 77  
 
 78  
     /**
 79  
      * The time out used for taking from the Seda Queue.
 80  
      */
 81  342
     protected int queueTimeout = 0;
 82  
 
 83  
     /**
 84  
      * Whether component objects should be pooled or a single instance should be
 85  
      * used.
 86  
      */
 87  342
     protected boolean enablePooling = true;
 88  
 
 89  
     /**
 90  
      * If this is set to true a new component will be created for every request.
 91  
      */
 92  342
     protected boolean componentPerRequest = false;
 93  
 
 94  
     /**
 95  
      * The pooling configuration used when initialising the component described by
 96  
      * this descriptor.
 97  
      */
 98  
     protected PoolingProfile poolingProfile;
 99  
 
 100  
     /**
 101  
      * The queuing profile for events received for this component.
 102  
      */
 103  
     protected QueueProfile queueProfile;
 104  
 
 105  
     /**
 106  
      * Creates a new SEDA component.
 107  
      * 
 108  
      * @param descriptor The descriptor of the component to creat
 109  
      * @param model the model in which the component is registered
 110  
      */
 111  
     public SedaComponent(MuleDescriptor descriptor, SedaModel model)
 112  
     {
 113  342
         super(descriptor, model);
 114  
 
 115  342
         descriptorQueueName = descriptor.getName() + ".component";
 116  342
         queueTimeout = model.getQueueTimeout();
 117  342
         enablePooling = model.isEnablePooling();
 118  342
         componentPerRequest = model.isComponentPerRequest();
 119  342
         poolingProfile = model.getPoolingProfile();
 120  342
         queueProfile = model.getQueueProfile();
 121  342
     }
 122  
 
 123  
     /**
 124  
      * Initialise the component. The component will first create a Mule UMO from the
 125  
      * UMODescriptor and then initialise a pool based on the attributes in the
 126  
      * UMODescriptor.
 127  
      * 
 128  
      * @throws org.mule.umo.lifecycle.InitialisationException if the component fails
 129  
      *             to initialise
 130  
      * @see org.mule.umo.UMODescriptor
 131  
      */
 132  
     public synchronized void doInitialise() throws InitialisationException
 133  
     {
 134  
         // Create thread pool
 135  34
         ThreadingProfile tp = descriptor.getThreadingProfile();
 136  34
         workManager = tp.createWorkManager(descriptor.getName());
 137  
 
 138  34
         queueProfile = descriptor.getQueueProfile();
 139  34
         if (queueProfile == null)
 140  
         {
 141  0
             queueProfile = ((SedaModel) model).getQueueProfile();
 142  
         }
 143  
 
 144  34
         poolingProfile = descriptor.getPoolingProfile();
 145  34
         if (poolingProfile == null)
 146  
         {
 147  0
             poolingProfile = ((SedaModel) model).getPoolingProfile();
 148  
         }
 149  
 
 150  
         try
 151  
         {
 152  
             // Setup event Queue (used for VM execution)
 153  34
             queueProfile.configureQueue(descriptorQueueName);
 154  
         }
 155  0
         catch (InitialisationException e)
 156  
         {
 157  0
             throw e;
 158  
         }
 159  0
         catch (Throwable e)
 160  
         {
 161  0
             throw new InitialisationException(
 162  
                 CoreMessages.objectFailedToInitialise("Component Queue"), e, this);
 163  34
         }
 164  34
     }
 165  
 
 166  
     protected ComponentStatistics createStatistics()
 167  
     {
 168  34
         return new SedaComponentStatistics(getName(), descriptor.getThreadingProfile().getMaxThreadsActive(),
 169  
             poolingProfile.getMaxActive());
 170  
     }
 171  
 
 172  
     protected ObjectPool createPool() throws InitialisationException
 173  
     {
 174  32
         return getPoolingProfile().getPoolFactory().createPool(descriptor, model,
 175  
             getPoolingProfile());
 176  
     }
 177  
 
 178  
     protected void initialisePool() throws InitialisationException
 179  
     {
 180  
         try
 181  
         {
 182  32
             int initPolicy = getPoolingProfile().getInitialisationPolicy();
 183  32
             if (initPolicy == PoolingProfile.INITIALISE_ALL)
 184  
             {
 185  0
                 int numToBorrow = getPoolingProfile().getMaxActive();
 186  0
                 List holderList = new ArrayList(numToBorrow);
 187  
 
 188  
                 try
 189  
                 {
 190  0
                     for (int t = 0; t < numToBorrow; t++)
 191  
                     {
 192  0
                         holderList.add(proxyPool.borrowObject());
 193  
                     }
 194  
                 }
 195  
                 finally
 196  
                 {
 197  0
                     for (int t = 0; t < holderList.size(); t++)
 198  
                     {
 199  0
                         Object obj = holderList.get(t);
 200  0
                         if (obj != null)
 201  
                         {
 202  
                             try
 203  
                             {
 204  0
                                 proxyPool.returnObject(obj);
 205  
                             }
 206  
                             finally
 207  0
                             {
 208  
                                 // ignore - nothing we can do
 209  0
                             }
 210  
                         }
 211  
                     }
 212  0
                 }
 213  0
             }
 214  32
             else if (initPolicy == PoolingProfile.INITIALISE_ONE)
 215  
             {
 216  32
                 Object obj = null;
 217  
                 try
 218  
                 {
 219  32
                     obj = proxyPool.borrowObject();
 220  
                 }
 221  
                 finally
 222  
                 {
 223  32
                     if (obj != null)
 224  
                     {
 225  22
                         proxyPool.returnObject(obj);
 226  
                     }
 227  
                 }
 228  
             }
 229  
 
 230  22
             poolInitialised.set(true);
 231  
         }
 232  10
         catch (Exception e)
 233  
         {
 234  10
             throw new InitialisationException(
 235  
                 CoreMessages.objectFailedToInitialise("Proxy Pool"), e, this);
 236  22
         }
 237  22
     }
 238  
 
 239  
     protected MuleProxy createComponentProxy() throws InitialisationException
 240  
     {
 241  
         try
 242  
         {
 243  0
             Object component = lookupComponent();
 244  0
             MuleProxy componentProxy = new DefaultMuleProxy(component, descriptor, model);
 245  0
             ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(-1);
 246  0
             componentProxy.setStatistics(getStatistics());
 247  0
             componentProxy.start();
 248  0
             return componentProxy;
 249  
         }
 250  0
         catch (UMOException e)
 251  
         {
 252  0
             throw new InitialisationException(e, this);
 253  
         }
 254  
     }
 255  
 
 256  
     public void doForceStop() throws UMOException
 257  
     {
 258  0
         doStop();
 259  0
     }
 260  
 
 261  
     public void doStop() throws UMOException
 262  
     {
 263  32
         if (MuleManager.getInstance().getQueueManager().getQueueSession().getQueue(
 264  
             descriptor.getName() + ".component").size() > 0)
 265  
         {
 266  
             try
 267  
             {
 268  0
                 stopping.whenFalse(null);
 269  
             }
 270  0
             catch (InterruptedException e)
 271  
             {
 272  
                 // we can ignore this
 273  
                 // TODO MULE-863: Why?
 274  0
             }
 275  
         }
 276  32
         workManager.stop();
 277  32
         if (proxyPool != null)
 278  
         {
 279  
             try
 280  
             {
 281  32
                 proxyPool.stop();
 282  32
                 proxyPool.clearPool();
 283  
             }
 284  0
             catch (Exception e)
 285  
             {
 286  
                 // TODO MULE-863: If this is an error, do something about it
 287  0
                 logger.error("Failed to stop component pool: " + e.getMessage(), e);
 288  32
             }
 289  32
             poolInitialised.set(false);
 290  
         }
 291  0
         else if (componentProxy != null)
 292  
         {
 293  0
             componentProxy.stop();
 294  
         }
 295  32
     }
 296  
 
 297  
     public void doStart() throws UMOException
 298  
     {
 299  
 
 300  
         try
 301  
         {
 302  
             // Need to initialise the pool only after all listerner have
 303  
             // been registered and initialised so we need to delay until now
 304  32
             if (!poolInitialised.get() && enablePooling)
 305  
             {
 306  32
                 proxyPool = this.createPool();
 307  32
                 this.initialisePool();
 308  22
                 proxyPool.start();
 309  
             }
 310  0
             else if (!componentPerRequest)
 311  
             {
 312  0
                 componentProxy = createComponentProxy();
 313  
             }
 314  22
             workManager.start();
 315  22
             workManager.scheduleWork(this, WorkManager.INDEFINITE, null, this);
 316  
         }
 317  10
         catch (Exception e)
 318  
         {
 319  10
             throw new LifecycleException(
 320  
                 CoreMessages.failedToStart("Component: " + descriptor.getName()), e, this);
 321  22
         }
 322  22
     }
 323  
 
 324  
     protected void doDispose()
 325  
     {
 326  
 
 327  
         try
 328  
         {
 329  
             // threadPool.awaitTerminationAfterShutdown();
 330  36
             if (workManager != null)
 331  
             {
 332  32
                 workManager.dispose();
 333  
             }
 334  
         }
 335  0
         catch (Exception e)
 336  
         {
 337  
             // TODO MULE-863: So what are we going to do about it?
 338  0
             logger.error("Component Thread Pool did not close properly: " + e);
 339  36
         }
 340  
         try
 341  
         {
 342  36
             if (proxyPool != null)
 343  
             {
 344  32
                 proxyPool.clearPool();
 345  
             }
 346  4
             else if (componentProxy != null)
 347  
             {
 348  0
                 componentProxy.dispose();
 349  
             }
 350  
         }
 351  0
         catch (Exception e)
 352  
         {
 353  
             // TODO MULE-863: So what are we going to do about it?
 354  0
             logger.error("Proxy Pool did not close properly: " + e);
 355  36
         }
 356  36
     }
 357  
 
 358  
     protected void doDispatch(UMOEvent event) throws UMOException
 359  
     {
 360  
         // Dispatching event to the component
 361  0
         if (stats.isEnabled())
 362  
         {
 363  0
             stats.incReceivedEventASync();
 364  
         }
 365  0
         if (logger.isDebugEnabled())
 366  
         {
 367  0
             logger.debug("Component: " + descriptor.getName() + " has received asynchronous event on: "
 368  
                             + event.getEndpoint().getEndpointURI());
 369  
         }
 370  
 
 371  
         // Block until we can queue the next event
 372  
         try
 373  
         {
 374  0
             enqueue(event);
 375  0
             if (stats.isEnabled())
 376  
             {
 377  0
                 stats.incQueuedEvent();
 378  
             }
 379  
         }
 380  0
         catch (Exception e)
 381  
         {
 382  0
             FailedToQueueEventException e1 = 
 383  
                 new FailedToQueueEventException(
 384  
                     CoreMessages.interruptedQueuingEventFor(this.getName()), 
 385  
                     event.getMessage(), this, e);
 386  0
             handleException(e1);
 387  0
         }
 388  
 
 389  0
         if (logger.isTraceEnabled())
 390  
         {
 391  0
             logger.trace("Event added to queue for: " + descriptor.getName());
 392  
         }
 393  0
     }
 394  
 
 395  
     public UMOMessage doSend(UMOEvent event) throws UMOException
 396  
     {
 397  8
         UMOMessage result = null;
 398  8
         MuleProxy proxy = null;
 399  
         try
 400  
         {
 401  8
             proxy = getProxy();
 402  8
             if (logger.isDebugEnabled())
 403  
             {
 404  0
                 logger.debug(this + " : got proxy for " + event.getId() + " = " + proxy);
 405  
             }
 406  8
             result = (UMOMessage) proxy.onCall(event);
 407  
         }
 408  0
         catch (UMOException e)
 409  
         {
 410  0
             throw e;
 411  
         }
 412  0
         catch (Exception e)
 413  
         {
 414  0
             throw new ComponentException(event.getMessage(), this, e);
 415  
         }
 416  
         // Ensure that any proxy used for this request is released.
 417  
         finally
 418  
         {
 419  8
             releaseProxy(proxy);
 420  8
         }
 421  8
         return result;
 422  
     }
 423  
 
 424  
     /**
 425  
      * @return the pool of Mule UMOs initialised in this component
 426  
      */
 427  
     ObjectPool getProxyPool()
 428  
     {
 429  0
         return proxyPool;
 430  
     }
 431  
 
 432  
     public int getQueueSize()
 433  
     {
 434  0
         QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
 435  0
         return queueSession.getQueue(descriptor.getName()).size();
 436  
     }
 437  
 
 438  
     /**
 439  
      * While the component isn't stopped this runs a continuous loop checking for new
 440  
      * events in the queue.
 441  
      */
 442  
     public void run()
 443  
     {
 444  22
         MuleEvent event = null;
 445  22
         MuleProxy proxy = null;
 446  22
         QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
 447  
 
 448  22
         while (!stopped.get())
 449  
         {
 450  
             try
 451  
             {
 452  
                 // Wait if the component is paused
 453  22
                 paused.whenFalse(null);
 454  
 
 455  
                 // If we're doing a draining stop, read all events from the queue
 456  
                 // before stopping
 457  22
                 if (stopping.get())
 458  
                 {
 459  3
                     if (queueSession == null || queueSession.getQueue(descriptorQueueName).size() == 0)
 460  
                     {
 461  3
                         stopping.set(false);
 462  
                         break;
 463  
                     }
 464  
                 }
 465  
 
 466  19
                 event = (MuleEvent) dequeue();
 467  0
                 if (event != null)
 468  
                 {
 469  0
                     if (stats.isEnabled())
 470  
                     {
 471  0
                         stats.decQueuedEvent();
 472  
                     }
 473  
 
 474  0
                     if (logger.isDebugEnabled())
 475  
                     {
 476  0
                         logger.debug("Component: " + descriptor.getName() + " dequeued event on: "
 477  
                                         + event.getEndpoint().getEndpointURI());
 478  
                     }
 479  
 
 480  0
                     proxy = getProxy();
 481  0
                     proxy.start();
 482  0
                     proxy.onEvent(queueSession, event);
 483  0
                     workManager.scheduleWork(proxy, WorkManager.INDEFINITE, null, this);
 484  
                 }
 485  
             }
 486  19
             catch (Exception e)
 487  
             {
 488  
                 // The proxy did not get created and/or schedule, so ensure it gets
 489  
                 // released.
 490  19
                 releaseProxy(proxy);
 491  
 
 492  19
                 if (e instanceof InterruptedException)
 493  
                 {
 494  19
                     stopping.set(false);
 495  
                     break;
 496  
                 }
 497  0
                 else if (e instanceof NoSuchElementException)
 498  
                 {
 499  0
                     handleException(new ComponentException(CoreMessages.proxyPoolTimedOut(),
 500  
                         (event == null ? null : event.getMessage()), this, e));
 501  
                 }
 502  0
                 else if (e instanceof UMOException)
 503  
                 {
 504  0
                     handleException(e);
 505  
                 }
 506  0
                 else if (e instanceof WorkException)
 507  
                 {
 508  0
                     handleException(
 509  
                         new ComponentException(
 510  
                             CoreMessages.eventProcessingFailedFor(descriptor.getName()),
 511  
                             (event == null ? null : event.getMessage()), this, e));
 512  
                 }
 513  
                 else
 514  
                 {
 515  0
                     handleException(
 516  
                         new ComponentException(
 517  
                             CoreMessages.failedToGetPooledObject(),
 518  
                             (event == null ? null : event.getMessage()), this, e));
 519  
                 }
 520  
             }
 521  
             finally
 522  
             {
 523  22
                 stopping.set(false);
 524  
                 
 525  
                 /* Removed: Since a componentPerRequest proxy is scheduled, it will be disposed by
 526  
                  * {@link #workCompleted(WorkEvent)} or {@link #workRejected(WorkEvent)}}.
 527  
                 if (proxy != null && componentPerRequest)
 528  
                 {
 529  
                     proxy.dispose();
 530  
                 }
 531  
                 */
 532  0
             }
 533  
         }
 534  22
     }
 535  
 
 536  
     /**
 537  
      * The proxy may be one of three types: 1. pooled 2. not pooled 3. per-request
 538  
      */
 539  
     protected MuleProxy getProxy() throws Exception
 540  
     {
 541  
         MuleProxy proxy;
 542  8
         if (proxyPool != null)
 543  
         {
 544  8
             proxy = (MuleProxy) proxyPool.borrowObject();
 545  8
             ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
 546  
         }
 547  0
         else if (componentPerRequest)
 548  
         {
 549  0
             proxy = createComponentProxy();
 550  
         }
 551  
         else
 552  
         {
 553  0
             proxy = componentProxy;
 554  
         }
 555  8
         proxy.setStatistics(getStatistics());
 556  8
         return proxy;
 557  
     }
 558  
     
 559  
     public void release()
 560  
     {
 561  0
         stopping.set(false);
 562  0
     }
 563  
 
 564  
     protected void enqueue(UMOEvent event) throws Exception
 565  
     {
 566  0
         QueueSession session = MuleManager.getInstance().getQueueManager().getQueueSession();
 567  0
         session.getQueue(descriptorQueueName).put(event);
 568  0
     }
 569  
 
 570  
     protected UMOEvent dequeue() throws Exception
 571  
     {
 572  
         // Wait until an event is available
 573  19
         QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
 574  19
         return (UMOEvent) queueSession.getQueue(descriptorQueueName).poll(queueTimeout);
 575  
     }
 576  
 
 577  
     public void workAccepted(WorkEvent event)
 578  
     {
 579  22
         handleWorkException(event, "workAccepted");
 580  22
     }
 581  
 
 582  
     /**
 583  
      * This method ensures that any component proxy associated with this rejected
 584  
      * work is released.
 585  
      *  
 586  
      * @see #workCompleted(WorkEvent)
 587  
      */
 588  
     public void workRejected(WorkEvent event)
 589  
     {
 590  0
         handleWorkException(event, "workRejected");
 591  
 
 592  0
         if (event.getWork() instanceof MuleProxy) 
 593  
         {
 594  0
             releaseProxy((MuleProxy) event.getWork());
 595  
         }
 596  0
     }
 597  
 
 598  
     public void workStarted(WorkEvent event)
 599  
     {
 600  22
         handleWorkException(event, "workStarted");
 601  22
     }
 602  
 
 603  
     /**
 604  
      * There are two units of work that call this method when they complete
 605  
      * (regardless of whether or not they incurred an exception):
 606  
      * 1) This component's queue listener that processes asynchronous events by
 607  
      *    scheduling a component proxy
 608  
      * 2) Each scheduled component proxy
 609  
      * <p>
 610  
      * Generally, #1 occurs each time the component stops and #2 occurs
 611  
      * at the end of each asynchronous event.
 612  
      * <p>
 613  
      * This method is responsible for handling any exceptions that occur for both
 614  
      * #1 and #2 and releasing the proxy from #2. 
 615  
      *    
 616  
      * @see WorkListener#workCompleted(WorkEvent)
 617  
      */
 618  
     public void workCompleted(WorkEvent event)
 619  
     {
 620  22
         handleWorkException(event, "workCompleted");
 621  
 
 622  22
         if (event.getWork() instanceof MuleProxy) 
 623  
         {
 624  0
             releaseProxy((MuleProxy) event.getWork());
 625  
         }
 626  22
     }
 627  
 
 628  
     protected void handleWorkException(WorkEvent event, String type)
 629  
     {
 630  
         Throwable e;
 631  
 
 632  68
         if (event != null && event.getException() != null)
 633  
         {
 634  2
             e = event.getException();
 635  
         }
 636  
         else
 637  
         {
 638  66
             return;
 639  
         }
 640  
 
 641  2
         if (event.getException().getCause() != null)
 642  
         {
 643  2
             e = event.getException().getCause();
 644  
         }
 645  
 
 646  2
         logger.error("Work caused exception on '" + type + "'. Work being executed was: "
 647  
                         + event.getWork().toString());
 648  
 
 649  2
         if (e instanceof Exception)
 650  
         {
 651  0
             handleException((Exception) e);
 652  
         }
 653  
         else
 654  
         {
 655  2
             throw new MuleRuntimeException(
 656  
                 CoreMessages.componentCausedErrorIs(this.getName()), e);
 657  
         }
 658  0
     }
 659  
 
 660  
     public PoolingProfile getPoolingProfile()
 661  
     {
 662  96
         return poolingProfile;
 663  
     }
 664  
 
 665  
     public void setPoolingProfile(PoolingProfile poolingProfile)
 666  
     {
 667  0
         this.poolingProfile = poolingProfile;
 668  0
     }
 669  
 
 670  
     public QueueProfile getQueueProfile()
 671  
     {
 672  0
         return queueProfile;
 673  
     }
 674  
 
 675  
     public void setQueueProfile(QueueProfile queueProfile)
 676  
     {
 677  0
         this.queueProfile = queueProfile;
 678  0
     }
 679  
 
 680  
     /**
 681  
      * This is a helper method that catches any exceptions that occur while
 682  
      * releasing a component proxy and reports them to the component for
 683  
      * handling.
 684  
      * 
 685  
      * @param proxy -
 686  
      *            the proxy that has completed; may be null in which case
 687  
      *            nothing occurs
 688  
      * 
 689  
      * @see #doReleaseProxy(MuleProxy)
 690  
      */
 691  
     private void releaseProxy(MuleProxy proxy) 
 692  
     {
 693  27
         if (proxy == null) 
 694  
         {
 695  19
             return;
 696  
         }
 697  
         
 698  
         try 
 699  
         {
 700  8
             doReleaseProxy(proxy);
 701  
         } 
 702  0
         catch (Exception ex)
 703  
         {
 704  0
             handleException(ex);
 705  8
         }
 706  
         // else, keep the singleton proxy for future use.
 707  8
     }
 708  
     
 709  
     /**
 710  
      * This method is called once when a proxy has finished processing a request
 711  
      * (regardless of success). For every call to
 712  
      * {@link #getProxy()), there will be a corresponding call to this method. 
 713  
      * The default behavior is to return the proxy to the pool, dispose of it,
 714  
      * or reuse it, depending on the configuration.
 715  
      * <p>
 716  
      * <b>NOTE:</b> The implementation of this method must be thread-safe.
 717  
      * 
 718  
      * @param proxy -
 719  
      *            the proxy that has completed; must be non-null.
 720  
      * 
 721  
      * @throws Exception -
 722  
      *             the proxy cannot be released.
 723  
      */
 724  
     protected void doReleaseProxy(MuleProxy proxy) throws Exception
 725  
     {
 726  8
         assert (proxy != null);
 727  
 
 728  8
         if (proxyPool != null) 
 729  
         {
 730  8
             proxyPool.returnObject(proxy);
 731  8
             ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
 732  
         } 
 733  0
         else if (componentPerRequest) 
 734  
         {
 735  0
             proxy.dispose();
 736  
         }
 737  
         // else, keep the singleton proxy for future use.
 738  8
     }
 739  
 }