Coverage Report - org.mule.providers.AbstractConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractConnector
57%
273/477
46%
80/174
2.585
 
 1  
 /*
 2  
  * $Id: AbstractConnector.java 10724 2008-02-06 15:34:56Z 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.providers;
 12  
 
 13  
 import org.mule.MuleManager;
 14  
 import org.mule.MuleRuntimeException;
 15  
 import org.mule.config.ThreadingProfile;
 16  
 import org.mule.config.i18n.CoreMessages;
 17  
 import org.mule.impl.AlreadyInitialisedException;
 18  
 import org.mule.impl.DefaultExceptionStrategy;
 19  
 import org.mule.impl.ImmutableMuleEndpoint;
 20  
 import org.mule.impl.MuleSessionHandler;
 21  
 import org.mule.impl.internal.notifications.ConnectionNotification;
 22  
 import org.mule.providers.service.TransportFactory;
 23  
 import org.mule.providers.service.TransportServiceDescriptor;
 24  
 import org.mule.providers.service.TransportServiceException;
 25  
 import org.mule.routing.filters.WildcardFilter;
 26  
 import org.mule.umo.MessagingException;
 27  
 import org.mule.umo.UMOComponent;
 28  
 import org.mule.umo.UMOEvent;
 29  
 import org.mule.umo.UMOException;
 30  
 import org.mule.umo.UMOMessage;
 31  
 import org.mule.umo.endpoint.UMOEndpoint;
 32  
 import org.mule.umo.endpoint.UMOEndpointURI;
 33  
 import org.mule.umo.endpoint.UMOImmutableEndpoint;
 34  
 import org.mule.umo.lifecycle.DisposeException;
 35  
 import org.mule.umo.lifecycle.Initialisable;
 36  
 import org.mule.umo.lifecycle.InitialisationException;
 37  
 import org.mule.umo.manager.UMOServerNotification;
 38  
 import org.mule.umo.manager.UMOWorkManager;
 39  
 import org.mule.umo.provider.ConnectorException;
 40  
 import org.mule.umo.provider.DispatchException;
 41  
 import org.mule.umo.provider.UMOConnectable;
 42  
 import org.mule.umo.provider.UMOConnector;
 43  
 import org.mule.umo.provider.UMOMessageAdapter;
 44  
 import org.mule.umo.provider.UMOMessageDispatcher;
 45  
 import org.mule.umo.provider.UMOMessageDispatcherFactory;
 46  
 import org.mule.umo.provider.UMOMessageReceiver;
 47  
 import org.mule.umo.provider.UMOSessionHandler;
 48  
 import org.mule.umo.provider.UMOStreamMessageAdapter;
 49  
 import org.mule.umo.transformer.UMOTransformer;
 50  
 import org.mule.util.ClassUtils;
 51  
 import org.mule.util.CollectionUtils;
 52  
 import org.mule.util.ObjectNameHelper;
 53  
 import org.mule.util.ObjectUtils;
 54  
 import org.mule.util.PropertiesUtils;
 55  
 import org.mule.util.StringUtils;
 56  
 import org.mule.util.concurrent.NamedThreadFactory;
 57  
 import org.mule.util.concurrent.WaitableBoolean;
 58  
 
 59  
 import java.beans.ExceptionListener;
 60  
 import java.io.InputStream;
 61  
 import java.io.OutputStream;
 62  
 import java.util.ArrayList;
 63  
 import java.util.Collections;
 64  
 import java.util.HashMap;
 65  
 import java.util.Iterator;
 66  
 import java.util.List;
 67  
 import java.util.Map;
 68  
 import java.util.Properties;
 69  
 
 70  
 import javax.resource.spi.work.WorkEvent;
 71  
 import javax.resource.spi.work.WorkListener;
 72  
 
 73  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 74  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
 75  
 import edu.emory.mathcs.backport.java.util.concurrent.ScheduledExecutorService;
 76  
 import edu.emory.mathcs.backport.java.util.concurrent.ScheduledThreadPoolExecutor;
 77  
 import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
 78  
 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
 79  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
 80  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
 81  
 
 82  
 import org.apache.commons.beanutils.BeanUtils;
 83  
 import org.apache.commons.logging.Log;
 84  
 import org.apache.commons.logging.LogFactory;
 85  
 import org.apache.commons.pool.KeyedPoolableObjectFactory;
 86  
 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
 87  
 
 88  
 /**
 89  
  * <code>AbstractConnector</code> provides base functionality for all connectors
 90  
  * provided with Mule. Connectors are the mechanism used to connect to external
 91  
  * systems and protocols in order to send and receive data. <p/> The
 92  
  * <code>AbstractConnector</code> provides getter and setter methods for endpoint
 93  
  * name, transport name and protocol. It also provides methods to stop and start
 94  
  * connecotors and sets up a dispatcher threadpool which allows deriving connectors
 95  
  * the possibility to dispatch work to separate threads. This functionality is
 96  
  * controlled with the <i> doThreading</i> property on the threadingProfiles for
 97  
  * dispachers and receivers. The lifecycle for a connector is -
 98  
  * <ol>
 99  
  * <li>Create
 100  
  * <li>Initialise
 101  
  * <li>Connect
 102  
  * <li>Connect receivers
 103  
  * <li>Start
 104  
  * <li>Start Receivers
 105  
  * <li>Stop
 106  
  * <li>Stop Receivers
 107  
  * <li>Disconnect
 108  
  * <li>Disconnect Receivers
 109  
  * <li>Dispose
 110  
  * <li>Dispose Receivers
 111  
  * </ol>
 112  
  */
 113  
 public abstract class AbstractConnector
 114  
     implements UMOConnector, ExceptionListener, UMOConnectable, WorkListener
 115  
 {
 116  
     /**
 117  
      * Default number of concurrent transactional receivers.
 118  
      */
 119  
     public static final int DEFAULT_NUM_CONCURRENT_TX_RECEIVERS = 4;
 120  
 
 121  
     /**
 122  
      * logger used by this class
 123  
      */
 124  778
     protected final Log logger = LogFactory.getLog(getClass());
 125  
 
 126  
     /**
 127  
      * Specifies if the endpoint started
 128  
      */
 129  778
     protected final AtomicBoolean started = new AtomicBoolean(false);
 130  
 
 131  
     /**
 132  
      * True once the endpoint has been initialsed
 133  
      */
 134  778
     protected final AtomicBoolean initialised = new AtomicBoolean(false);
 135  
 
 136  
     /**
 137  
      * The name that identifies the endpoint
 138  
      */
 139  
     protected volatile String name;
 140  
 
 141  
     /**
 142  
      * The exception strategy used by this connector
 143  
      */
 144  
     protected volatile ExceptionListener exceptionListener;
 145  
 
 146  
     /**
 147  
      * Determines in the connector is alive and well
 148  
      */
 149  778
     protected final AtomicBoolean disposed = new AtomicBoolean(false);
 150  
 
 151  
     /**
 152  
      * Determines in connector has been told to dispose
 153  
      */
 154  778
     protected final AtomicBoolean disposing = new AtomicBoolean(false);
 155  
 
 156  
     /**
 157  
      * Factory used to create dispatchers for this connector
 158  
      */
 159  
     protected volatile UMOMessageDispatcherFactory dispatcherFactory;
 160  
 
 161  
     /**
 162  
      * A pool of dispatchers for this connector, keyed by endpoint
 163  
      */
 164  778
     protected final GenericKeyedObjectPool dispatchers = new GenericKeyedObjectPool();
 165  
 
 166  
     /**
 167  
      * The collection of listeners on this connector. Keyed by entrypoint
 168  
      */
 169  778
     protected final ConcurrentMap receivers = new ConcurrentHashMap();
 170  
 
 171  
     /**
 172  
      * Defines the dispatcher threading profile
 173  
      */
 174  778
     private volatile ThreadingProfile dispatcherThreadingProfile = MuleManager.getConfiguration()
 175  
         .getMessageDispatcherThreadingProfile();
 176  
 
 177  
     /**
 178  
      * Defines the receiver threading profile
 179  
      */
 180  778
     private volatile ThreadingProfile receiverThreadingProfile = MuleManager.getConfiguration()
 181  
         .getMessageReceiverThreadingProfile();
 182  
 
 183  
     /**
 184  
      * @see {@link #isCreateMultipleTransactedReceivers()}
 185  
      */
 186  778
     protected volatile boolean createMultipleTransactedReceivers = true;
 187  
 
 188  
     /**
 189  
      * @see {@link #getNumberOfConcurrentTransactedReceivers()}
 190  
      */
 191  778
     protected volatile int numberOfConcurrentTransactedReceivers = DEFAULT_NUM_CONCURRENT_TX_RECEIVERS;
 192  
 
 193  
     /**
 194  
      * The service descriptor can define a default inbound transformer to be used on
 195  
      * an endpoint if no other is set
 196  
      */
 197  
     protected volatile UMOTransformer defaultInboundTransformer;
 198  
 
 199  
     /**
 200  
      * The service descriptor can define a default outbound transformer to be used on
 201  
      * an endpoint if no other is set
 202  
      */
 203  
     protected volatile UMOTransformer defaultOutboundTransformer;
 204  
 
 205  
     /**
 206  
      * For some connectors such as http, a response transformer is required or where
 207  
      * a replyTo needs a trnasformer
 208  
      */
 209  
     protected volatile UMOTransformer defaultResponseTransformer;
 210  
 
 211  
     protected volatile ConnectionStrategy connectionStrategy;
 212  
 
 213  778
     protected final WaitableBoolean connected = new WaitableBoolean(false);
 214  
 
 215  778
     protected final WaitableBoolean connecting = new WaitableBoolean(false);
 216  
 
 217  
     /**
 218  
      * If the connect method was called via the start method, this will be set so
 219  
      * that when the connector comes on line it will be started
 220  
      */
 221  778
     protected final WaitableBoolean startOnConnect = new WaitableBoolean(false);
 222  
 
 223  
     /**
 224  
      * Whether to fire message notifications for every message that is sent or
 225  
      * received from this connector. Default is {@code false}.
 226  
      */
 227  
     private volatile boolean enableMessageEvents;
 228  
 
 229  
     private final List supportedProtocols;
 230  
 
 231  
     /**
 232  
      * A shared work manager for all receivers registered with this connector.
 233  
      */
 234  778
     private final AtomicReference/*<UMOWorkManager>*/ receiverWorkManager = new AtomicReference();
 235  
 
 236  
     /**
 237  
      * A shared work manager for all dispatchers created for this connector.
 238  
      */
 239  778
     private final AtomicReference/*<UMOWorkManager>*/ dispatcherWorkManager = new AtomicReference();
 240  
 
 241  
     /**
 242  
      * A generic scheduling service for tasks that need to be performed periodically.
 243  
      */
 244  778
     private final AtomicReference/*<ScheduledExecutorService>*/ scheduler = new AtomicReference();
 245  
 
 246  
     /**
 247  
      * Holds the service configuration for this connector
 248  
      */
 249  
     protected volatile TransportServiceDescriptor serviceDescriptor;
 250  
 
 251  
     /**
 252  
      * The map of service overrides that can e used to extend the capabilities of the
 253  
      * connector
 254  
      */
 255  
     protected volatile Properties serviceOverrides;
 256  
 
 257  
     /**
 258  
      * The strategy used for reading and writing session information to and fromt he
 259  
      * transport
 260  
      */
 261  778
     protected volatile UMOSessionHandler sessionHandler = new MuleSessionHandler();
 262  
 
 263  
     /** Constructs a new AbstractConnector. */
 264  
     public AbstractConnector()
 265  
     {
 266  778
         super();
 267  
 
 268  
         // make sure we always have an exception strategy
 269  778
         exceptionListener = new DefaultExceptionStrategy();
 270  778
         connectionStrategy = MuleManager.getConfiguration().getConnectionStrategy();
 271  778
         enableMessageEvents = MuleManager.getConfiguration().isEnableMessageEvents();
 272  
 
 273  
         // always add at least the default protocol
 274  778
         supportedProtocols = new ArrayList();
 275  778
         supportedProtocols.add(getProtocol().toLowerCase());
 276  
 
 277  
         // NOTE: testOnBorrow MUST be FALSE. this is a bit of a design bug in
 278  
         // commons-pool since validate is used for both activation and passivation,
 279  
         // but has no way of knowing which way it is going.
 280  778
         dispatchers.setTestOnBorrow(false);
 281  778
         dispatchers.setTestOnReturn(true);
 282  778
     }
 283  
 
 284  
     /** {@inheritDoc} */
 285  
     public String getName()
 286  
     {
 287  368
         return name;
 288  
     }
 289  
 
 290  
     /** {@inheritDoc} */
 291  
     public void setName(String newName)
 292  
     {
 293  820
         if (newName == null)
 294  
         {
 295  0
             throw new IllegalArgumentException(CoreMessages.objectIsNull("Connector name").toString());
 296  
         }
 297  
 
 298  820
         if (logger.isDebugEnabled())
 299  
         {
 300  0
             logger.debug("Set UMOConnector name to: " + newName);
 301  
         }
 302  
 
 303  820
         name = newName;
 304  820
     }
 305  
 
 306  
     /** {@inheritDoc} */
 307  
     public final synchronized void initialise() throws InitialisationException
 308  
     {
 309  22
         if (initialised.get())
 310  
         {
 311  0
             throw new AlreadyInitialisedException("Connector '" + getName() + "'", this);
 312  
         }
 313  
 
 314  22
         if (logger.isInfoEnabled())
 315  
         {
 316  0
             logger.info("Initialising: " + this);
 317  
         }
 318  
 
 319  
         // Initialise the structure of this connector
 320  22
         this.initFromServiceDescriptor();
 321  
 
 322  
         // we clear out any registered dispatchers and receivers without resetting
 323  
         // the actual containers since this it might actually be a re-initialise
 324  
         // (e.g. as in JmsConnector)
 325  22
         this.disposeDispatchers();
 326  22
         this.disposeReceivers();
 327  
 
 328  22
         this.doInitialise();
 329  
 
 330  22
         if (exceptionListener instanceof Initialisable)
 331  
         {
 332  22
             ((Initialisable) exceptionListener).initialise();
 333  
         }
 334  
 
 335  22
         initialised.set(true);
 336  22
     }
 337  
 
 338  
     /** {@inheritDoc} */
 339  
     public final synchronized void startConnector() throws UMOException
 340  
     {
 341  44
         this.checkDisposed();
 342  
 
 343  44
         if (!this.isStarted())
 344  
         {
 345  44
             if (!this.isConnected())
 346  
             {
 347  22
                 startOnConnect.set(true);
 348  
                 // Don't call getConnectionStrategy(), it clones the connection strategy.
 349  
                 // Connectors should have a single reconnection thread, unlike per receiver/dispatcher
 350  22
                 connectionStrategy.connect(this);
 351  
                 // Only start once we are connected
 352  22
                 return;
 353  
             }
 354  
 
 355  22
             if (logger.isInfoEnabled())
 356  
             {
 357  0
                 logger.info("Starting: " + this);
 358  
             }
 359  
 
 360  
             // the scheduler is recreated after stopConnector()
 361  22
             ScheduledExecutorService currentScheduler = (ScheduledExecutorService) scheduler.get();
 362  22
             if (currentScheduler == null || currentScheduler.isShutdown())
 363  
             {
 364  22
                 scheduler.set(this.getScheduler());
 365  
             }
 366  
 
 367  22
             this.doStart();
 368  22
             started.set(true);
 369  
 
 370  22
             if (receivers != null)
 371  
             {
 372  22
                 for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
 373  
                 {
 374  0
                     UMOMessageReceiver mr = (UMOMessageReceiver) iterator.next();
 375  0
                     if (logger.isDebugEnabled())
 376  
                     {
 377  0
                         logger.debug("Starting receiver on endpoint: " + mr.getEndpoint().getEndpointURI());
 378  
                     }
 379  0
                     mr.start();
 380  0
                 }
 381  
             }
 382  
 
 383  22
             if (logger.isInfoEnabled())
 384  
             {
 385  0
                 logger.info("Started: " + this);
 386  
             }
 387  
         }
 388  22
     }
 389  
 
 390  
     /** {@inheritDoc} */
 391  
     public boolean isStarted()
 392  
     {
 393  166
         return started.get();
 394  
     }
 395  
 
 396  
     /** {@inheritDoc} */
 397  
     public final synchronized void stopConnector() throws UMOException
 398  
     {
 399  80
         if (this.isDisposed())
 400  
         {
 401  0
             return;
 402  
         }
 403  
 
 404  80
         if (this.isStarted())
 405  
         {
 406  22
             if (logger.isInfoEnabled())
 407  
             {
 408  0
                 logger.info("Stopping: " + this);
 409  
             }
 410  
 
 411  
             // shutdown our scheduler service
 412  22
             ((ScheduledExecutorService) scheduler.get()).shutdown();
 413  
 
 414  22
             this.doStop();
 415  22
             started.set(false);
 416  
 
 417  
             // Stop all the receivers on this connector (this will cause them to
 418  
             // disconnect too)
 419  22
             if (receivers != null)
 420  
             {
 421  22
                 for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
 422  
                 {
 423  20
                     UMOMessageReceiver mr = (UMOMessageReceiver) iterator.next();
 424  20
                     if (logger.isDebugEnabled())
 425  
                     {
 426  0
                         logger.debug("Stopping receiver on endpoint: " + mr.getEndpoint().getEndpointURI());
 427  
                     }
 428  20
                     mr.stop();
 429  20
                 }
 430  
             }
 431  
         }
 432  
         
 433  80
         if (this.isConnected())
 434  
         {
 435  
             try
 436  
             {
 437  22
                 this.disconnect();
 438  
             }
 439  0
             catch (Exception e)
 440  
             {
 441  
                 // TODO MULE-863: What should we really do?
 442  0
                 logger.error("Failed to disconnect: " + e.getMessage(), e);
 443  22
             }
 444  
         }
 445  
 
 446  
         // make sure the scheduler is gone
 447  80
         scheduler.set(null);
 448  
 
 449  
         // we do not need to stop the work managers because they do no harm (will just be idle)
 450  
         // and will be reused on restart without problems.
 451  
         
 452  80
         this.initialised.set(false);
 453  
         // started=false already issued above right after doStop()
 454  80
         if (logger.isInfoEnabled())
 455  
         {
 456  0
             logger.info("Stopped: " + this);
 457  
         }
 458  80
     }
 459  
 
 460  
     /** {@inheritDoc} */
 461  
     public final synchronized void dispose()
 462  
     {
 463  46
         disposing.set(true);
 464  
 
 465  46
         if (logger.isInfoEnabled())
 466  
         {
 467  0
             logger.info("Disposing: " + this);
 468  
         }
 469  
 
 470  
         try
 471  
         {
 472  46
             this.stopConnector();
 473  
         }
 474  0
         catch (UMOException e)
 475  
         {
 476  0
             logger.warn("Failed to stop during shutdown: " + e.getMessage(), e);
 477  46
         }
 478  
 
 479  46
         this.disposeReceivers();
 480  46
         this.disposeDispatchers();
 481  46
         this.disposeWorkManagers();
 482  
 
 483  46
         this.doDispose();        
 484  46
         disposed.set(true);
 485  
 
 486  46
         if (logger.isInfoEnabled())
 487  
         {
 488  0
             logger.info("Disposed: " + this);
 489  
         }
 490  46
     }
 491  
 
 492  
     protected void disposeWorkManagers()
 493  
     {
 494  46
         logger.debug("Disposing dispatcher work manager");
 495  46
         UMOWorkManager workManager = (UMOWorkManager) dispatcherWorkManager.get();
 496  46
         if (workManager != null)
 497  
         {
 498  0
             workManager.dispose();
 499  
         }
 500  46
         dispatcherWorkManager.set(null);
 501  
 
 502  46
         logger.debug("Disposing receiver work manager");
 503  46
         workManager = (UMOWorkManager) receiverWorkManager.get();
 504  46
         if (workManager != null)
 505  
         {
 506  22
             workManager.dispose();
 507  
         }
 508  46
         receiverWorkManager.set(null);
 509  46
     }
 510  
 
 511  
     protected void disposeReceivers()
 512  
     {
 513  68
         if (receivers != null)
 514  
         {
 515  68
             logger.debug("Disposing Receivers");
 516  
 
 517  68
             for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
 518  
             {
 519  10
                 UMOMessageReceiver receiver = (UMOMessageReceiver) iterator.next();
 520  
 
 521  
                 try
 522  
                 {
 523  10
                     this.destroyReceiver(receiver, receiver.getEndpoint());
 524  
                 }
 525  0
                 catch (Throwable e)
 526  
                 {
 527  
                     // TODO MULE-863: What should we really do?
 528  0
                     logger.error("Failed to destroy receiver: " + receiver, e);
 529  10
                 }
 530  10
             }
 531  
 
 532  68
             receivers.clear();
 533  68
             logger.debug("Receivers Disposed");
 534  
         }
 535  68
     }
 536  
 
 537  
     protected void disposeDispatchers()
 538  
     {
 539  68
         if (dispatchers != null)
 540  
         {
 541  68
             logger.debug("Disposing Dispatchers");
 542  68
             dispatchers.clear();
 543  68
             logger.debug("Dispatchers Disposed");
 544  
         }
 545  68
     }
 546  
 
 547  
     /** {@inheritDoc} */
 548  
     public boolean isDisposed()
 549  
     {
 550  178
         return disposed.get();
 551  
     }
 552  
 
 553  
     /** {@inheritDoc} */
 554  
     public void handleException(Exception exception)
 555  
     {
 556  0
         if (exceptionListener == null)
 557  
         {
 558  0
             throw new MuleRuntimeException(
 559  
                 CoreMessages.exceptionOnConnectorNotExceptionListener(this.getName()), exception);
 560  
         }
 561  
         else
 562  
         {
 563  0
             exceptionListener.exceptionThrown(exception);
 564  
         }
 565  0
     }
 566  
 
 567  
     /** {@inheritDoc} */
 568  
     public void exceptionThrown(Exception e)
 569  
     {
 570  0
         handleException(e);
 571  0
     }
 572  
 
 573  
     /**
 574  
      * @return the ExceptionStrategy for this endpoint
 575  
      * @see ExceptionListener
 576  
      */
 577  
     public ExceptionListener getExceptionListener()
 578  
     {
 579  4
         return exceptionListener;
 580  
     }
 581  
 
 582  
     /**
 583  
      * @param listener the ExceptionStrategy to use with this endpoint
 584  
      * @see ExceptionListener
 585  
      */
 586  
     public void setExceptionListener(ExceptionListener listener)
 587  
     {
 588  0
         exceptionListener = listener;
 589  0
     }
 590  
 
 591  
     /**
 592  
      * @return Returns the dispatcherFactory.
 593  
      */
 594  
     public UMOMessageDispatcherFactory getDispatcherFactory()
 595  
     {
 596  0
         return dispatcherFactory;
 597  
     }
 598  
 
 599  
     /**
 600  
      * @param dispatcherFactory The dispatcherFactory to set.
 601  
      */
 602  
     public void setDispatcherFactory(UMOMessageDispatcherFactory dispatcherFactory)
 603  
     {
 604  
         KeyedPoolableObjectFactory poolFactory;
 605  
 
 606  778
         if (dispatcherFactory instanceof KeyedPoolableObjectFactory)
 607  
         {
 608  0
             poolFactory = (KeyedPoolableObjectFactory) dispatcherFactory;
 609  
         }
 610  
         else
 611  
         {
 612  
             // need to adapt the UMOMessageDispatcherFactory for use by commons-pool
 613  778
             poolFactory = new KeyedPoolMessageDispatcherFactoryAdapter(dispatcherFactory);
 614  
         }
 615  
 
 616  778
         this.dispatchers.setFactory(poolFactory);
 617  
 
 618  
         // we keep a reference to the unadapted factory, otherwise people might end
 619  
         // up with ClassCastExceptions on downcast to their implementation (sigh)
 620  778
         this.dispatcherFactory = dispatcherFactory;
 621  778
     }
 622  
 
 623  
     /**
 624  
      * Returns the maximum number of dispatchers that can be concurrently active per
 625  
      * endpoint.
 626  
      *
 627  
      * @return max. number of active dispatchers
 628  
      */
 629  
     public int getMaxDispatchersActive()
 630  
     {
 631  0
         return this.dispatchers.getMaxActive();
 632  
     }
 633  
 
 634  
     /**
 635  
      * Configures the maximum number of dispatchers that can be concurrently active
 636  
      * per endpoint
 637  
      *
 638  
      * @param maxActive max. number of active dispatchers
 639  
      */
 640  
     public void setMaxDispatchersActive(int maxActive)
 641  
     {
 642  0
         this.dispatchers.setMaxActive(maxActive);
 643  
         // adjust maxIdle in tandem to avoid thrashing
 644  0
         this.dispatchers.setMaxIdle(maxActive);
 645  0
     }
 646  
 
 647  
     private UMOMessageDispatcher getDispatcher(UMOImmutableEndpoint endpoint) throws UMOException
 648  
     {
 649  10
         this.checkDisposed();
 650  
 
 651  10
         if (endpoint == null)
 652  
         {
 653  0
             throw new IllegalArgumentException("Endpoint must not be null");
 654  
         }
 655  
 
 656  10
         if (!this.supportsProtocol(endpoint.getConnector().getProtocol()))
 657  
         {
 658  0
             throw new IllegalArgumentException(
 659  
                 CoreMessages.connectorSchemeIncompatibleWithEndpointScheme(this.getProtocol(), 
 660  
                     endpoint.getEndpointURI().toString()).getMessage());
 661  
         }
 662  
 
 663  
         try
 664  
         {
 665  10
             if (logger.isDebugEnabled())
 666  
             {
 667  0
                 logger.debug("Borrowing a dispatcher for endpoint: " + endpoint.getEndpointURI());
 668  
             }
 669  
         }
 670  0
         catch (Exception ex)
 671  
         {
 672  0
             throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
 673  10
         }
 674  
 
 675  10
         UMOMessageDispatcher dispatcher = null;
 676  
 
 677  
         try
 678  
         {
 679  10
             dispatcher = (UMOMessageDispatcher) dispatchers.borrowObject(endpoint);
 680  10
             return dispatcher;
 681  
         }
 682  0
         catch (Exception ex)
 683  
         {
 684  0
             throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
 685  
         }
 686  
         finally
 687  
         {
 688  0
             try
 689  
             {
 690  10
                 if (logger.isDebugEnabled())
 691  
                 {
 692  0
                     logger.debug("Borrowed dispatcher: " + ObjectUtils.toString(dispatcher, "null"));
 693  
                 }
 694  
             }
 695  0
             catch (Exception ex)
 696  
             {
 697  0
                 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
 698  10
             }
 699  
         }
 700  
     }
 701  
 
 702  
     private void returnDispatcher(UMOImmutableEndpoint endpoint, UMOMessageDispatcher dispatcher)
 703  
     {
 704  10
         if (endpoint != null && dispatcher != null)
 705  
         {
 706  
             try
 707  
             {
 708  10
                 if (logger.isDebugEnabled())
 709  
                 {
 710  0
                     logger.debug("Returning dispatcher for endpoint: " + endpoint.getEndpointURI() + " = "
 711  
                                     + ObjectUtils.toString(dispatcher, "null"));
 712  
                 }
 713  
             }
 714  0
             catch (Exception ex)
 715  
             {
 716  
                 // TODO MULE-863: What should we really do?
 717  
                 // ignore - if the dispatcher is broken, it will likely get cleaned
 718  
                 // up by the factory
 719  
             }
 720  
             finally
 721  
             {
 722  0
                 try
 723  
                 {
 724  10
                     dispatchers.returnObject(endpoint, dispatcher);
 725  
                 }
 726  0
                 catch (Exception ex)
 727  
                 {
 728  
                     // TODO MULE-863: What should we really do?
 729  
                     // returnObject() never throws; this will go away in commons-pool
 730  10
                 }
 731  0
             }
 732  
         }
 733  10
     }
 734  
 
 735  
     protected void checkDisposed() throws DisposeException
 736  
     {
 737  98
         if (this.isDisposed())
 738  
         {
 739  0
             throw new DisposeException(CoreMessages.cannotUseDisposedConnector(), this);
 740  
         }
 741  98
     }
 742  
 
 743  
     /** {@inheritDoc} */
 744  
     public UMOMessageReceiver registerListener(UMOComponent component, UMOEndpoint endpoint) throws Exception
 745  
     {
 746  22
         if (endpoint == null)
 747  
         {
 748  0
             throw new IllegalArgumentException("The endpoint cannot be null when registering a listener");
 749  
         }
 750  
 
 751  22
         if (component == null)
 752  
         {
 753  0
             throw new IllegalArgumentException("The component cannot be null when registering a listener");
 754  
         }
 755  
 
 756  22
         UMOEndpointURI endpointUri = endpoint.getEndpointURI();
 757  22
         if (endpointUri == null)
 758  
         {
 759  0
             throw new ConnectorException(CoreMessages.endpointIsNullForListener(), this);
 760  
         }
 761  
 
 762  22
         logger.info("Registering listener: " + component.getDescriptor().getName() + " on endpointUri: "
 763  
                         + endpointUri.toString());
 764  
 
 765  22
         UMOMessageReceiver receiver = this.getReceiver(component, endpoint);
 766  
 
 767  22
         if (receiver != null)
 768  
         {
 769  0
             throw new ConnectorException(CoreMessages.listenerAlreadyRegistered(endpointUri), this);
 770  
         }
 771  
         else
 772  
         {
 773  22
             receiver = this.createReceiver(component, endpoint);
 774  22
             Object receiverKey = getReceiverKey(component, endpoint);
 775  22
             receiver.setReceiverKey(receiverKey.toString());
 776  22
             receivers.put(receiverKey, receiver);
 777  
             // receivers.put(getReceiverKey(component, endpoint), receiver);
 778  
         }
 779  
 
 780  22
         return receiver;
 781  
     }
 782  
 
 783  
     /**
 784  
      * The method determines the key used to store the receiver against.
 785  
      *
 786  
      * @param component the component for which the endpoint is being registered
 787  
      * @param endpoint the endpoint being registered for the component
 788  
      * @return the key to store the newly created receiver against
 789  
      */
 790  
     protected Object getReceiverKey(UMOComponent component, UMOEndpoint endpoint)
 791  
     {
 792  90
         return StringUtils.defaultIfEmpty(endpoint.getEndpointURI().getFilterAddress(), endpoint
 793  
             .getEndpointURI().getAddress());
 794  
     }
 795  
 
 796  
     /** {@inheritDoc} */
 797  
     public final void unregisterListener(UMOComponent component, UMOEndpoint endpoint) throws Exception
 798  
     {
 799  22
         if (component == null)
 800  
         {
 801  0
             throw new IllegalArgumentException(
 802  
                 "The component must not be null when you unregister a listener");
 803  
         }
 804  
 
 805  22
         if (endpoint == null)
 806  
         {
 807  0
             throw new IllegalArgumentException("The endpoint must not be null when you unregister a listener");
 808  
         }
 809  
 
 810  22
         UMOEndpointURI endpointUri = endpoint.getEndpointURI();
 811  22
         if (endpointUri == null)
 812  
         {
 813  0
             throw new IllegalArgumentException(
 814  
                 "The endpointUri must not be null when you unregister a listener");
 815  
         }
 816  
 
 817  22
         if (logger.isInfoEnabled())
 818  
         {
 819  0
             logger.info("Removing listener on endpointUri: " + endpointUri);
 820  
         }
 821  
 
 822  22
         if (receivers != null && !receivers.isEmpty())
 823  
         {
 824  12
             UMOMessageReceiver receiver = (UMOMessageReceiver) receivers.remove(this.getReceiverKey(component,
 825  
                 endpoint));
 826  12
             if (receiver != null)
 827  
             {
 828  12
                 this.destroyReceiver(receiver, endpoint);
 829  
             }
 830  
         }
 831  22
     }
 832  
 
 833  
     /**
 834  
      * Getter for property 'dispatcherThreadingProfile'.
 835  
      *
 836  
      * @return Value for property 'dispatcherThreadingProfile'.
 837  
      */
 838  
     public ThreadingProfile getDispatcherThreadingProfile()
 839  
     {
 840  8
         return dispatcherThreadingProfile;
 841  
     }
 842  
 
 843  
     /**
 844  
      * Setter for property 'dispatcherThreadingProfile'.
 845  
      *
 846  
      * @param dispatcherThreadingProfile Value to set for property
 847  
      *            'dispatcherThreadingProfile'.
 848  
      */
 849  
     public void setDispatcherThreadingProfile(ThreadingProfile dispatcherThreadingProfile)
 850  
     {
 851  0
         this.dispatcherThreadingProfile = dispatcherThreadingProfile;
 852  0
     }
 853  
 
 854  
     /**
 855  
      * Getter for property 'receiverThreadingProfile'.
 856  
      *
 857  
      * @return Value for property 'receiverThreadingProfile'.
 858  
      */
 859  
     public ThreadingProfile getReceiverThreadingProfile()
 860  
     {
 861  44
         return receiverThreadingProfile;
 862  
     }
 863  
 
 864  
     /**
 865  
      * Setter for property 'receiverThreadingProfile'.
 866  
      *
 867  
      * @param receiverThreadingProfile Value to set for property
 868  
      *            'receiverThreadingProfile'.
 869  
      */
 870  
     public void setReceiverThreadingProfile(ThreadingProfile receiverThreadingProfile)
 871  
     {
 872  0
         this.receiverThreadingProfile = receiverThreadingProfile;
 873  0
     }
 874  
 
 875  
     protected void destroyReceiver(UMOMessageReceiver receiver, UMOEndpoint endpoint) throws Exception
 876  
     {
 877  0
         receiver.dispose();
 878  0
     }
 879  
 
 880  
     protected abstract void doInitialise() throws InitialisationException;
 881  
 
 882  
     /**
 883  
      * Template method to perform any work when destroying the connectoe
 884  
      */
 885  
     protected abstract void doDispose();
 886  
 
 887  
     /**
 888  
      * Template method to perform any work when starting the connectoe
 889  
      *
 890  
      * @throws UMOException if the method fails
 891  
      */
 892  
     protected abstract void doStart() throws UMOException;
 893  
 
 894  
     /**
 895  
      * Template method to perform any work when stopping the connectoe
 896  
      *
 897  
      * @throws UMOException if the method fails
 898  
      */
 899  
     protected abstract void doStop() throws UMOException;
 900  
 
 901  
     /**
 902  
      * Getter for property 'defaultInboundTransformer'.
 903  
      *
 904  
      * @return Value for property 'defaultInboundTransformer'.
 905  
      */
 906  
     public UMOTransformer getDefaultInboundTransformer()
 907  
     {
 908  72
         if (defaultInboundTransformer != null)
 909  
         {
 910  
             try
 911  
             {
 912  0
                 return (UMOTransformer) defaultInboundTransformer.clone();
 913  
             }
 914  0
             catch (CloneNotSupportedException e)
 915  
             {
 916  
                 // TODO MULE-863: What should we really do?
 917  0
                 logger.error("Failed to clone default Inbound transformer");
 918  
             }
 919  
         }
 920  
 
 921  72
         return null;
 922  
     }
 923  
 
 924  
     /**
 925  
      * Setter for property 'defaultInboundTransformer'.
 926  
      *
 927  
      * @param defaultInboundTransformer Value to set for property
 928  
      *            'defaultInboundTransformer'.
 929  
      */
 930  
     public void setDefaultInboundTransformer(UMOTransformer defaultInboundTransformer)
 931  
     {
 932  0
         this.defaultInboundTransformer = defaultInboundTransformer;
 933  0
     }
 934  
 
 935  
     /**
 936  
      * Getter for property 'defaultResponseTransformer'.
 937  
      *
 938  
      * @return Value for property 'defaultResponseTransformer'.
 939  
      */
 940  
     public UMOTransformer getDefaultResponseTransformer()
 941  
     {
 942  72
         if (defaultResponseTransformer != null)
 943  
         {
 944  
             try
 945  
             {
 946  0
                 return (UMOTransformer) defaultResponseTransformer.clone();
 947  
             }
 948  0
             catch (CloneNotSupportedException e)
 949  
             {
 950  
                 // TODO MULE-863: What should we really do?
 951  0
                 logger.error("Failed to clone default Outbound transformer");
 952  
             }
 953  
         }
 954  
 
 955  72
         return null;
 956  
     }
 957  
 
 958  
     /**
 959  
      * Getter for property 'defaultOutboundTransformer'.
 960  
      *
 961  
      * @return Value for property 'defaultOutboundTransformer'.
 962  
      */
 963  
     public UMOTransformer getDefaultOutboundTransformer()
 964  
     {
 965  412
         if (defaultOutboundTransformer != null)
 966  
         {
 967  
             try
 968  
             {
 969  0
                 return (UMOTransformer) defaultOutboundTransformer.clone();
 970  
             }
 971  0
             catch (CloneNotSupportedException e)
 972  
             {
 973  
                 // TODO MULE-863: What should we really do?
 974  0
                 logger.error("Failed to clone default Outbound transformer");
 975  
             }
 976  
         }
 977  
 
 978  412
         return null;
 979  
     }
 980  
 
 981  
     /**
 982  
      * Setter for property 'defaultOutboundTransformer'.
 983  
      *
 984  
      * @param defaultOutboundTransformer Value to set for property
 985  
      *            'defaultOutboundTransformer'.
 986  
      */
 987  
     public void setDefaultOutboundTransformer(UMOTransformer defaultOutboundTransformer)
 988  
     {
 989  0
         this.defaultOutboundTransformer = defaultOutboundTransformer;
 990  0
     }
 991  
 
 992  
     /**
 993  
      * Setter for property 'defaultResponseTransformer'.
 994  
      *
 995  
      * @param defaultResponseTransformer Value to set for property
 996  
      *            'defaultResponseTransformer'.
 997  
      */
 998  
     public void setDefaultResponseTransformer(UMOTransformer defaultResponseTransformer)
 999  
     {
 1000  0
         this.defaultResponseTransformer = defaultResponseTransformer;
 1001  0
     }
 1002  
 
 1003  
     /**
 1004  
      * Getter for property 'replyToHandler'.
 1005  
      *
 1006  
      * @return Value for property 'replyToHandler'.
 1007  
      */
 1008  
     public ReplyToHandler getReplyToHandler()
 1009  
     {
 1010  0
         return new DefaultReplyToHandler(defaultResponseTransformer);
 1011  
     }
 1012  
 
 1013  
     /**
 1014  
      * Fires a server notification to all registered
 1015  
      * {@link org.mule.impl.internal.notifications.CustomNotificationListener}
 1016  
      * eventManager.
 1017  
      *
 1018  
      * @param notification the notification to fire. This must be of type
 1019  
      *            {@link org.mule.impl.internal.notifications.CustomNotification}
 1020  
      *            otherwise an exception will be thrown.
 1021  
      * @throws UnsupportedOperationException if the notification fired is not a
 1022  
      *             {@link org.mule.impl.internal.notifications.CustomNotification}
 1023  
      */
 1024  
     public void fireNotification(UMOServerNotification notification)
 1025  
     {
 1026  90
         MuleManager.getInstance().fireNotification(notification);
 1027  90
     }
 1028  
 
 1029  
     /**
 1030  
      * Getter for property 'connectionStrategy'.
 1031  
      *
 1032  
      * @return Value for property 'connectionStrategy'.
 1033  
      */
 1034  
     public ConnectionStrategy getConnectionStrategy()
 1035  
     {
 1036  
         // not happy with this but each receiver needs its own instance
 1037  
         // of the connection strategy and using a factory just introduces extra
 1038  
         // implementation
 1039  
         try
 1040  
         {
 1041  26
             return (ConnectionStrategy) BeanUtils.cloneBean(connectionStrategy);
 1042  
         }
 1043  0
         catch (Exception e)
 1044  
         {
 1045  0
             throw new MuleRuntimeException(CoreMessages.failedToClone("connectionStrategy"), e);
 1046  
         }
 1047  
     }
 1048  
 
 1049  
     /**
 1050  
      * Setter for property 'connectionStrategy'.
 1051  
      *
 1052  
      * @param connectionStrategy Value to set for property 'connectionStrategy'.
 1053  
      */
 1054  
     public void setConnectionStrategy(ConnectionStrategy connectionStrategy)
 1055  
     {
 1056  0
         this.connectionStrategy = connectionStrategy;
 1057  0
     }
 1058  
 
 1059  
     /** {@inheritDoc} */
 1060  
     public boolean isDisposing()
 1061  
     {
 1062  0
         return disposing.get();
 1063  
     }
 1064  
 
 1065  
     /** {@inheritDoc} */
 1066  
     public boolean isRemoteSyncEnabled()
 1067  
     {
 1068  74
         return false;
 1069  
     }
 1070  
 
 1071  
     public UMOMessageReceiver getReceiver(UMOComponent component, UMOEndpoint endpoint)
 1072  
     {
 1073  56
         return (UMOMessageReceiver) receivers.get(this.getReceiverKey(component, endpoint));
 1074  
     }
 1075  
 
 1076  
     /**
 1077  
      * Getter for property 'receivers'.
 1078  
      *
 1079  
      * @return Value for property 'receivers'.
 1080  
      */
 1081  
     public Map getReceivers()
 1082  
     {
 1083  12
         return Collections.unmodifiableMap(receivers);
 1084  
     }
 1085  
 
 1086  
     public UMOMessageReceiver lookupReceiver(String key)
 1087  
     {
 1088  0
         if (key != null)
 1089  
         {
 1090  0
             return (UMOMessageReceiver) receivers.get(key);
 1091  
         }
 1092  
         else
 1093  
         {
 1094  0
             throw new IllegalArgumentException("Receiver key must not be null");
 1095  
         }
 1096  
     }
 1097  
 
 1098  
     public UMOMessageReceiver[] getReceivers(String wildcardExpression)
 1099  
     {
 1100  0
         WildcardFilter filter = new WildcardFilter(wildcardExpression);
 1101  0
         filter.setCaseSensitive(false);
 1102  
 
 1103  0
         List found = new ArrayList();
 1104  
 
 1105  0
         for (Iterator iterator = receivers.entrySet().iterator(); iterator.hasNext();)
 1106  
         {
 1107  0
             Map.Entry e = (Map.Entry) iterator.next();
 1108  0
             if (filter.accept(e.getKey()))
 1109  
             {
 1110  0
                 found.add(e.getValue());
 1111  
             }
 1112  0
         }
 1113  
 
 1114  0
         return (UMOMessageReceiver[]) CollectionUtils.toArrayOfComponentType(found,
 1115  0
             UMOMessageReceiver.class);
 1116  
     }
 1117  
 
 1118  
     /** {@inheritDoc} */
 1119  
     public void connect() throws Exception
 1120  
     {
 1121  44
         this.checkDisposed();
 1122  
 
 1123  44
         if (connected.get())
 1124  
         {
 1125  0
             return;
 1126  
         }
 1127  
 
 1128  
         /*
 1129  
             Until the recursive startConnector() -> connect() -> doConnect() -> connect()
 1130  
             calls are unwound between a connector and connection strategy, this call has
 1131  
             to be here, and not below (commented out currently). Otherwise, e.g. WebspherMQ
 1132  
             goes into an endless reconnect thrashing loop, see MULE-1150 for more details.
 1133  
         */
 1134  
         try
 1135  
         {
 1136  44
             if (connecting.get())
 1137  
             {
 1138  22
                 this.doConnect();
 1139  
             }
 1140  
 
 1141  44
             if (connecting.compareAndSet(false, true))
 1142  
             {
 1143  22
                 if (logger.isDebugEnabled())
 1144  
                 {
 1145  0
                     logger.debug("Connecting: " + this);
 1146  
                 }
 1147  
 
 1148  22
                 connectionStrategy.connect(this);
 1149  
 
 1150  22
                 logger.info("Connected: " + getConnectionDescription());
 1151  
                 // This method calls itself so the connecting flag is set first, then
 1152  
                 // the connection is made on the second call
 1153  22
                 return;
 1154  
             }
 1155  
 
 1156  
 
 1157  
             // see the explanation above
 1158  
             //this.doConnect();
 1159  22
             connected.set(true);
 1160  22
             connecting.set(false);
 1161  
 
 1162  22
             this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
 1163  
                 ConnectionNotification.CONNECTION_CONNECTED));
 1164  
         }
 1165  0
         catch (Exception e)
 1166  
         {
 1167  0
             connected.set(false);
 1168  0
             connecting.set(false);
 1169  
 
 1170  0
             this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
 1171  
                 ConnectionNotification.CONNECTION_FAILED));
 1172  
 
 1173  0
             if (e instanceof ConnectException || e instanceof FatalConnectException)
 1174  
             {
 1175  
                 // rethrow
 1176  0
                 throw e;
 1177  
             }
 1178  
             else
 1179  
             {
 1180  0
                 throw new ConnectException(e, this);
 1181  
             }
 1182  22
         }
 1183  
 
 1184  22
         if (startOnConnect.get())
 1185  
         {
 1186  22
             this.startConnector();
 1187  
         }
 1188  
         else
 1189  
         {
 1190  0
             for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
 1191  
             {
 1192  0
                 UMOMessageReceiver receiver = (UMOMessageReceiver) iterator.next();
 1193  0
                 if (logger.isDebugEnabled())
 1194  
                 {
 1195  0
                     logger.debug("Connecting receiver on endpoint: "
 1196  
                                     + receiver.getEndpoint().getEndpointURI());
 1197  
                 }
 1198  0
                 receiver.connect();
 1199  0
             }
 1200  
         }
 1201  22
     }
 1202  
 
 1203  
     /** {@inheritDoc} */
 1204  
     public void disconnect() throws Exception
 1205  
     {
 1206  22
         startOnConnect.set(this.isStarted());
 1207  
 
 1208  22
         this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
 1209  
             ConnectionNotification.CONNECTION_DISCONNECTED));
 1210  
 
 1211  22
         connected.set(false);
 1212  
 
 1213  
         try
 1214  
         {
 1215  22
             this.doDisconnect();
 1216  
         }
 1217  
         finally
 1218  
         {
 1219  22
             this.stopConnector();
 1220  22
         }
 1221  
 
 1222  22
         logger.info("Disconnected: " + this.getConnectionDescription());
 1223  22
     }
 1224  
 
 1225  
     /** {@inheritDoc} */
 1226  
     public String getConnectionDescription()
 1227  
     {
 1228  44
         return this.toString();
 1229  
     }
 1230  
 
 1231  
     /** {@inheritDoc} */
 1232  
     public final boolean isConnected()
 1233  
     {
 1234  124
         return connected.get();
 1235  
     }
 1236  
 
 1237  
     /**
 1238  
      * Template method where any connections should be made for the connector
 1239  
      *
 1240  
      * @throws Exception
 1241  
      */
 1242  
     protected abstract void doConnect() throws Exception;
 1243  
 
 1244  
     /**
 1245  
      * Template method where any connected resources used by the connector should be
 1246  
      * disconnected
 1247  
      *
 1248  
      * @throws Exception
 1249  
      */
 1250  
     protected abstract void doDisconnect() throws Exception;
 1251  
 
 1252  
     /**
 1253  
      * The resource id used when firing ConnectEvents from this connector
 1254  
      *
 1255  
      * @return the resource id used when firing ConnectEvents from this connector
 1256  
      */
 1257  
     protected String getConnectEventId()
 1258  
     {
 1259  44
         return getName();
 1260  
     }
 1261  
 
 1262  
     /**
 1263  
      * For better throughput when using TransactedMessageReceivers this will enable a
 1264  
      * number of concurrent receivers, based on the value returned by
 1265  
      * {@link #getNumberOfConcurrentTransactedReceivers()}. This property is used by
 1266  
      * transports that support transactions, specifically receivers that extend the
 1267  
      * TransactedPollingMessageReceiver.
 1268  
      *
 1269  
      * @return true if multiple receivers will be enabled for this connection
 1270  
      */
 1271  
     public boolean isCreateMultipleTransactedReceivers()
 1272  
     {
 1273  0
         return createMultipleTransactedReceivers;
 1274  
     }
 1275  
 
 1276  
     /**
 1277  
      * @see {@link #isCreateMultipleTransactedReceivers()}
 1278  
      * @param createMultipleTransactedReceivers if true, multiple receivers will be
 1279  
      *            created for this connection
 1280  
      */
 1281  
     public void setCreateMultipleTransactedReceivers(boolean createMultipleTransactedReceivers)
 1282  
     {
 1283  0
         this.createMultipleTransactedReceivers = createMultipleTransactedReceivers;
 1284  0
     }
 1285  
 
 1286  
     /**
 1287  
      * Returns the number of concurrent receivers that will be launched when
 1288  
      * {@link #isCreateMultipleTransactedReceivers()} returns <code>true</code>.
 1289  
      *
 1290  
      * @see #DEFAULT_NUM_CONCURRENT_TX_RECEIVERS
 1291  
      */
 1292  
     public int getNumberOfConcurrentTransactedReceivers()
 1293  
     {
 1294  0
         return numberOfConcurrentTransactedReceivers;
 1295  
     }
 1296  
 
 1297  
     /**
 1298  
      * @see {@link #getNumberOfConcurrentTransactedReceivers()}
 1299  
      * @param count the number of concurrent transacted receivers to start
 1300  
      */
 1301  
     public void setNumberOfConcurrentTransactedReceivers(int count)
 1302  
     {
 1303  0
         numberOfConcurrentTransactedReceivers = count;
 1304  0
     }
 1305  
 
 1306  
     /**
 1307  
      * Whether to fire message notifications for every message that is sent or
 1308  
      * received from this connector
 1309  
      */
 1310  
     public boolean isEnableMessageEvents()
 1311  
     {
 1312  10
         return enableMessageEvents;
 1313  
     }
 1314  
 
 1315  
     /**
 1316  
      * Whether to fire message notifications for every message that is sent or
 1317  
      * received from this connector
 1318  
      *
 1319  
      * @param enableMessageEvents
 1320  
      */
 1321  
     public void setEnableMessageEvents(boolean enableMessageEvents)
 1322  
     {
 1323  0
         this.enableMessageEvents = enableMessageEvents;
 1324  0
     }
 1325  
 
 1326  
     /**
 1327  
      * Registers other protocols 'understood' by this connector. These must contain
 1328  
      * scheme meta info. Any protocol registered must begin with the protocol of this
 1329  
      * connector, i.e. If the connector is axis the protocol for jms over axis will
 1330  
      * be axis:jms. Here, 'axis' is the scheme meta info and 'jms' is the protocol.
 1331  
      * If the protocol argument does not start with the connector's protocol, it will
 1332  
      * be appended.
 1333  
      *
 1334  
      * @param protocol the supported protocol to register
 1335  
      */
 1336  
     public void registerSupportedProtocol(String protocol)
 1337  
     {
 1338  0
         protocol = protocol.toLowerCase();
 1339  0
         if (protocol.startsWith(getProtocol().toLowerCase()))
 1340  
         {
 1341  0
             registerSupportedProtocolWithoutPrefix(protocol);
 1342  
         }
 1343  
         else
 1344  
         {
 1345  0
             supportedProtocols.add(getProtocol().toLowerCase() + ":" + protocol);
 1346  
         }
 1347  0
     }
 1348  
 
 1349  
     /**
 1350  
      * Registers other protocols 'understood' by this connector. These must contain
 1351  
      * scheme meta info. Unlike the {@link #registerSupportedProtocol(String)} method,
 1352  
      * this allows you to register protocols that are not prefixed with the connector
 1353  
      * protocol. This is useful where you use a Service Finder to discover which
 1354  
      * Transport implementation to use. For example the 'wsdl' transport is a generic
 1355  
      * 'finder' transport that will use Axis, Xfire or Glue to create the WSDL
 1356  
      * client. These transport protocols would be wsdl-axis, wsdl-xfire and
 1357  
      * wsdl-glue, but they can all support 'wsdl' protocol too.
 1358  
      *
 1359  
      * @param protocol the supported protocol to register
 1360  
      */
 1361  
     protected void registerSupportedProtocolWithoutPrefix(String protocol)
 1362  
     {
 1363  0
         supportedProtocols.add(protocol.toLowerCase());
 1364  0
     }
 1365  
 
 1366  
     public void unregisterSupportedProtocol(String protocol)
 1367  
     {
 1368  0
         protocol = protocol.toLowerCase();
 1369  0
         if (protocol.startsWith(getProtocol().toLowerCase()))
 1370  
         {
 1371  0
             supportedProtocols.remove(protocol);
 1372  
         }
 1373  
         else
 1374  
         {
 1375  0
             supportedProtocols.remove(getProtocol().toLowerCase() + ":" + protocol);
 1376  
         }
 1377  0
     }
 1378  
 
 1379  
     /**
 1380  
      * @return true if the protocol is supported by this connector.
 1381  
      */
 1382  
     public boolean supportsProtocol(String protocol)
 1383  
     {
 1384  932
         return supportedProtocols.contains(protocol.toLowerCase());
 1385  
     }
 1386  
 
 1387  
     /**
 1388  
      * Returns an unmodifiable list of the protocols supported by this connector
 1389  
      *
 1390  
      * @return an unmodifiable list of the protocols supported by this connector
 1391  
      */
 1392  
     public List getSupportedProtocols()
 1393  
     {
 1394  0
         return Collections.unmodifiableList(supportedProtocols);
 1395  
     }
 1396  
 
 1397  
     /**
 1398  
      * Sets A list of protocols that the connector can accept
 1399  
      *
 1400  
      * @param supportedProtocols
 1401  
      */
 1402  
     public void setSupportedProtocols(List supportedProtocols)
 1403  
     {
 1404  0
         for (Iterator iterator = supportedProtocols.iterator(); iterator.hasNext();)
 1405  
         {
 1406  0
             String s = (String) iterator.next();
 1407  0
             registerSupportedProtocol(s);
 1408  0
         }
 1409  0
     }
 1410  
 
 1411  
     /**
 1412  
      * Returns a work manager for message receivers.
 1413  
      */
 1414  
     protected UMOWorkManager getReceiverWorkManager(String receiverName) throws UMOException
 1415  
     {
 1416  
         // lazily created because ThreadingProfile was not yet set in Constructor
 1417  22
         if (receiverWorkManager.get() == null)
 1418  
         {
 1419  22
             UMOWorkManager newWorkManager = this.getReceiverThreadingProfile().createWorkManager(
 1420  
                 this.getName() + '.' + receiverName);
 1421  
 
 1422  22
             if (receiverWorkManager.compareAndSet(null, newWorkManager))
 1423  
             {
 1424  22
                 newWorkManager.start();
 1425  
             }
 1426  
         }
 1427  
 
 1428  22
         return (UMOWorkManager) receiverWorkManager.get();
 1429  
     }
 1430  
 
 1431  
     /**
 1432  
      * Returns a work manager for message dispatchers.
 1433  
      *
 1434  
      * @throws UMOException in case of error
 1435  
      */
 1436  
     protected UMOWorkManager getDispatcherWorkManager() throws UMOException
 1437  
     {
 1438  
         // lazily created because ThreadingProfile was not yet set in Constructor
 1439  4
         if (dispatcherWorkManager.get() == null)
 1440  
         {
 1441  4
             UMOWorkManager newWorkManager = this.getDispatcherThreadingProfile().createWorkManager(
 1442  
                 getName() + ".dispatcher");
 1443  
 
 1444  4
             if (dispatcherWorkManager.compareAndSet(null, newWorkManager))
 1445  
             {
 1446  4
                 newWorkManager.start();
 1447  
             }
 1448  
         }
 1449  
 
 1450  4
         return (UMOWorkManager) dispatcherWorkManager.get();
 1451  
     }
 1452  
 
 1453  
     /** {@inheritDoc} */
 1454  
     public ScheduledExecutorService getScheduler()
 1455  
     {
 1456  22
         if (scheduler.get() == null)
 1457  
         {
 1458  22
             ThreadFactory threadFactory = new NamedThreadFactory(this.getName() + ".scheduler");
 1459  22
             ScheduledThreadPoolExecutor newExecutor = new ScheduledThreadPoolExecutor(4, threadFactory);
 1460  22
             newExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
 1461  22
             newExecutor.setKeepAliveTime(this.getReceiverThreadingProfile().getThreadTTL(),
 1462  
                 TimeUnit.MILLISECONDS);
 1463  22
             newExecutor.allowCoreThreadTimeOut(true);
 1464  
 
 1465  22
             if (!scheduler.compareAndSet(null, newExecutor))
 1466  
             {
 1467  
                 // someone else was faster, ditch our copy.
 1468  0
                 newExecutor.shutdown();
 1469  
             }
 1470  
         }
 1471  
 
 1472  22
         return (ScheduledExecutorService) scheduler.get();
 1473  
     }
 1474  
 
 1475  
     /**
 1476  
      * Getter for property 'sessionHandler'.
 1477  
      *
 1478  
      * @return Value for property 'sessionHandler'.
 1479  
      */
 1480  
     public UMOSessionHandler getSessionHandler()
 1481  
     {
 1482  10
         return sessionHandler;
 1483  
     }
 1484  
 
 1485  
     /**
 1486  
      * Setter for property 'sessionHandler'.
 1487  
      *
 1488  
      * @param sessionHandler Value to set for property 'sessionHandler'.
 1489  
      */
 1490  
     public void setSessionHandler(UMOSessionHandler sessionHandler)
 1491  
     {
 1492  0
         this.sessionHandler = sessionHandler;
 1493  0
     }
 1494  
 
 1495  
     /** {@inheritDoc} */
 1496  
     public void workAccepted(WorkEvent event)
 1497  
     {
 1498  0
         this.handleWorkException(event, "workAccepted");
 1499  0
     }
 1500  
 
 1501  
     /** {@inheritDoc} */
 1502  
     public void workRejected(WorkEvent event)
 1503  
     {
 1504  0
         this.handleWorkException(event, "workRejected");
 1505  0
     }
 1506  
 
 1507  
     /** {@inheritDoc} */
 1508  
     public void workStarted(WorkEvent event)
 1509  
     {
 1510  0
         this.handleWorkException(event, "workStarted");
 1511  0
     }
 1512  
 
 1513  
     /** {@inheritDoc} */
 1514  
     public void workCompleted(WorkEvent event)
 1515  
     {
 1516  0
         this.handleWorkException(event, "workCompleted");
 1517  0
     }
 1518  
 
 1519  
     protected void handleWorkException(WorkEvent event, String type)
 1520  
     {
 1521  2
         if (event == null)
 1522  
         {
 1523  0
             return;
 1524  
         }
 1525  
 
 1526  2
         Throwable e = event.getException();
 1527  
 
 1528  2
         if (e == null)
 1529  
         {
 1530  0
             return;
 1531  
         }
 1532  
 
 1533  2
         if (e.getCause() != null)
 1534  
         {
 1535  2
             e = e.getCause();
 1536  
         }
 1537  
 
 1538  2
         logger.error("Work caused exception on '" + type + "'. Work being executed was: "
 1539  
                         + event.getWork().toString());
 1540  
 
 1541  2
         if (e instanceof Exception)
 1542  
         {
 1543  0
             this.handleException((Exception) e);
 1544  
         }
 1545  
         else
 1546  
         {
 1547  2
             throw new MuleRuntimeException(CoreMessages.connectorCausedError(this.getName()), e);
 1548  
         }
 1549  0
     }
 1550  
 
 1551  
     // TODO the following methods should probably be lifecycle-enabled;
 1552  
     // for now they are only stubs to get the refactoring going.
 1553  
 
 1554  
     /** {@inheritDoc} */
 1555  
     public void dispatch(UMOImmutableEndpoint endpoint, UMOEvent event) throws DispatchException
 1556  
     {
 1557  0
         UMOMessageDispatcher dispatcher = null;
 1558  
 
 1559  
         try
 1560  
         {
 1561  0
             dispatcher = this.getDispatcher(endpoint);
 1562  0
             dispatcher.dispatch(event);
 1563  
         }
 1564  0
         catch (DispatchException dex)
 1565  
         {
 1566  0
             throw dex;
 1567  
         }
 1568  0
         catch (UMOException ex)
 1569  
         {
 1570  0
             throw new DispatchException(event.getMessage(), endpoint, ex);
 1571  
         }
 1572  
         finally
 1573  
         {
 1574  0
             this.returnDispatcher(endpoint, dispatcher);
 1575  0
         }
 1576  0
     }
 1577  
 
 1578  
     /** {@inheritDoc} */
 1579  
     public UMOMessage receive(UMOEndpointURI endpointUri, long timeout) throws Exception
 1580  
     {
 1581  0
         return this.receive(new ImmutableMuleEndpoint(endpointUri.toString(), true), timeout);
 1582  
     }
 1583  
 
 1584  
     /** {@inheritDoc} */
 1585  
     public UMOMessage receive(UMOImmutableEndpoint endpoint, long timeout) throws Exception
 1586  
     {
 1587  0
         UMOMessageDispatcher dispatcher = null;
 1588  
 
 1589  
         try
 1590  
         {
 1591  0
             dispatcher = this.getDispatcher(endpoint);
 1592  0
             return dispatcher.receive(timeout);
 1593  
         }
 1594  
         finally
 1595  
         {
 1596  0
             this.returnDispatcher(endpoint, dispatcher);
 1597  
         }
 1598  
     }
 1599  
 
 1600  
     /** {@inheritDoc} */
 1601  
     public UMOMessage send(UMOImmutableEndpoint endpoint, UMOEvent event) throws DispatchException
 1602  
     {
 1603  10
         UMOMessageDispatcher dispatcher = null;
 1604  
 
 1605  
         try
 1606  
         {
 1607  10
             dispatcher = this.getDispatcher(endpoint);
 1608  10
             return dispatcher.send(event);
 1609  
         }
 1610  0
         catch (DispatchException dex)
 1611  
         {
 1612  0
             throw dex;
 1613  
         }
 1614  0
         catch (UMOException ex)
 1615  
         {
 1616  0
             throw new DispatchException(event.getMessage(), endpoint, ex);
 1617  
         }
 1618  
         finally
 1619  
         {
 1620  10
             this.returnDispatcher(endpoint, dispatcher);
 1621  
         }
 1622  
     }
 1623  
 
 1624  
     // -------- Methods from the removed AbstractServiceEnabled Connector
 1625  
 
 1626  
     /**
 1627  
      * When this connector is created via the
 1628  
      * {@link org.mule.providers.service.TransportFactory} the endpoint used to
 1629  
      * determine the connector type is passed to this method so that any properties
 1630  
      * set on the endpoint that can be used to initialise the connector are made
 1631  
      * available.
 1632  
      *
 1633  
      * @param endpointUri the {@link UMOEndpointURI} use to create this connector
 1634  
      * @throws InitialisationException If there are any problems with the
 1635  
      *             configuration set on the Endpoint or if another exception is
 1636  
      *             thrown it is wrapped in an InitialisationException.
 1637  
      */
 1638  
     public void initialiseFromUrl(UMOEndpointURI endpointUri) throws InitialisationException
 1639  
     {
 1640  42
         if (!supportsProtocol(endpointUri.getFullScheme()))
 1641  
         {
 1642  0
             throw new InitialisationException(
 1643  
                 CoreMessages.schemeNotCompatibleWithConnector(endpointUri.getFullScheme(), 
 1644  
                     this.getClass()), this);
 1645  
         }
 1646  42
         Properties props = new Properties();
 1647  42
         props.putAll(endpointUri.getParams());
 1648  
         // auto set username and password
 1649  42
         if (endpointUri.getUserInfo() != null)
 1650  
         {
 1651  0
             props.setProperty("username", endpointUri.getUsername());
 1652  0
             String passwd = endpointUri.getPassword();
 1653  0
             if (passwd != null)
 1654  
             {
 1655  0
                 props.setProperty("password", passwd);
 1656  
             }
 1657  
         }
 1658  42
         String host = endpointUri.getHost();
 1659  42
         if (host != null)
 1660  
         {
 1661  42
             props.setProperty("hostname", host);
 1662  42
             props.setProperty("host", host);
 1663  
         }
 1664  42
         if (endpointUri.getPort() > -1)
 1665  
         {
 1666  0
             props.setProperty("port", String.valueOf(endpointUri.getPort()));
 1667  
         }
 1668  
 
 1669  42
         org.mule.util.BeanUtils.populateWithoutFail(this, props, true);
 1670  
 
 1671  42
         setName(ObjectNameHelper.getConnectorName(this));
 1672  42
     }
 1673  
 
 1674  
     /**
 1675  
      * Initialises this connector from its {@link TransportServiceDescriptor} This
 1676  
      * will be called before the {@link #doInitialise()} method is called.
 1677  
      *
 1678  
      * @throws InitialisationException InitialisationException If there are any
 1679  
      *             problems with the configuration or if another exception is thrown
 1680  
      *             it is wrapped in an InitialisationException.
 1681  
      */
 1682  
     protected synchronized void initFromServiceDescriptor() throws InitialisationException
 1683  
     {
 1684  
         try
 1685  
         {
 1686  22
             serviceDescriptor = TransportFactory.getServiceDescriptor(getProtocol().toLowerCase(),
 1687  
                 serviceOverrides);
 1688  
 
 1689  22
             if (serviceDescriptor.getDispatcherFactory() != null)
 1690  
             {
 1691  0
                 logger.debug("Loading DispatcherFactory: " + serviceDescriptor.getDispatcherFactory());
 1692  0
                 this.setDispatcherFactory(serviceDescriptor.createDispatcherFactory());
 1693  
             }
 1694  
 
 1695  22
             defaultInboundTransformer = serviceDescriptor.createInboundTransformer();
 1696  22
             defaultOutboundTransformer = serviceDescriptor.createOutboundTransformer();
 1697  22
             defaultResponseTransformer = serviceDescriptor.createResponseTransformer();
 1698  
 
 1699  22
             sessionHandler = serviceDescriptor.createSessionHandler();
 1700  
 
 1701  
             // Set any manager default properties for the connector. These are set on
 1702  
             // the Manager with a protocol e.g. jms.specification=1.1
 1703  
             // This provides a really convenient way to set properties on an object
 1704  
             // from unit tests
 1705  22
             Map props = new HashMap();
 1706  22
             PropertiesUtils.getPropertiesWithPrefix(MuleManager.getInstance().getProperties(), getProtocol()
 1707  
                 .toLowerCase(), props);
 1708  22
             if (props.size() > 0)
 1709  
             {
 1710  0
                 props = PropertiesUtils.removeNamespaces(props);
 1711  0
                 org.mule.util.BeanUtils.populateWithoutFail(this, props, true);
 1712  
             }
 1713  
         }
 1714  0
         catch (Exception e)
 1715  
         {
 1716  0
             throw new InitialisationException(e, this);
 1717  22
         }
 1718  22
     }
 1719  
 
 1720  
     /**
 1721  
      * Get the {@link TransportServiceDescriptor} for this connector. This will be
 1722  
      * null if the connector was created by the developer. To create a connector the
 1723  
      * proper way the developer should use the {@link TransportFactory} and pass in
 1724  
      * an endpoint.
 1725  
      *
 1726  
      * @return the {@link TransportServiceDescriptor} for this connector
 1727  
      */
 1728  
     protected TransportServiceDescriptor getServiceDescriptor()
 1729  
     {
 1730  0
         if (serviceDescriptor == null)
 1731  
         {
 1732  0
             throw new IllegalStateException("This connector has not yet been initialised: " + name);
 1733  
         }
 1734  0
         return serviceDescriptor;
 1735  
     }
 1736  
 
 1737  
     /**
 1738  
      * Create a Message receiver for this connector
 1739  
      *
 1740  
      * @param component the component that will receive events from this receiver,
 1741  
      *            the listener
 1742  
      * @param endpoint the endpoint that defies this inbound communication
 1743  
      * @return an instance of the message receiver defined in this connectors'
 1744  
      *         {@link org.mule.providers.service.TransportServiceDescriptor}
 1745  
      *         initialised using the component and endpoint.
 1746  
      * @throws Exception if there is a problem creating the receiver. This exception
 1747  
      *             really depends on the underlying transport, thus any exception
 1748  
      *             could be thrown
 1749  
      */
 1750  
     protected UMOMessageReceiver createReceiver(UMOComponent component, UMOEndpoint endpoint)
 1751  
         throws Exception
 1752  
     {
 1753  0
         return getServiceDescriptor().createMessageReceiver(this, component, endpoint);
 1754  
     }
 1755  
 
 1756  
     /**
 1757  
      * Gets a <code>UMOMessageAdapter</code> for the endpoint for the given message
 1758  
      * (data)
 1759  
      *
 1760  
      * @param message the data with which to initialise the
 1761  
      *            <code>UMOMessageAdapter</code>
 1762  
      * @return the <code>UMOMessageAdapter</code> for the endpoint
 1763  
      * @throws org.mule.umo.MessagingException if the message parameter is not
 1764  
      *             supported
 1765  
      * @see org.mule.umo.provider.UMOMessageAdapter
 1766  
      */
 1767  
     public UMOMessageAdapter getMessageAdapter(Object message) throws MessagingException
 1768  
     {
 1769  
         try
 1770  
         {
 1771  0
             return serviceDescriptor.createMessageAdapter(message);
 1772  
         }
 1773  0
         catch (TransportServiceException e)
 1774  
         {
 1775  0
             throw new MessagingException(CoreMessages.failedToCreate("Message Adapter"),
 1776  
                 message, e);
 1777  
         }
 1778  
     }
 1779  
 
 1780  
     /**
 1781  
      * Gets a {@link UMOStreamMessageAdapter} from the connector for the given
 1782  
      * message. This Adapter will correctly handle data streaming for this type of
 1783  
      * connector
 1784  
      *
 1785  
      * @param in the input stream to read the data from
 1786  
      * @param out the outputStream to write data to. This can be null.
 1787  
      * @return the {@link UMOStreamMessageAdapter} for the endpoint
 1788  
      * @throws MessagingException if the message parameter is not supported
 1789  
      * @see UMOStreamMessageAdapter
 1790  
      */
 1791  
     public UMOStreamMessageAdapter getStreamMessageAdapter(InputStream in, OutputStream out)
 1792  
         throws MessagingException
 1793  
     {
 1794  
         try
 1795  
         {
 1796  0
             return serviceDescriptor.createStreamMessageAdapter(in, out);
 1797  
         }
 1798  0
         catch (TransportServiceException e)
 1799  
         {
 1800  0
             throw new MessagingException(CoreMessages.failedToCreate("Stream Message Adapter"),
 1801  
                 in, e);
 1802  
         }
 1803  
     }
 1804  
 
 1805  
     /**
 1806  
      * A map of fully qualified class names that should override those in the
 1807  
      * connectors' service descriptor This map will be null if there are no overrides
 1808  
      *
 1809  
      * @return a map of override values or null
 1810  
      */
 1811  
     public Map getServiceOverrides()
 1812  
     {
 1813  124
         return serviceOverrides;
 1814  
     }
 1815  
 
 1816  
     /**
 1817  
      * Set the Service overrides on this connector.
 1818  
      *
 1819  
      * @param serviceOverrides the override values to use
 1820  
      */
 1821  
     public void setServiceOverrides(Map serviceOverrides)
 1822  
     {
 1823  0
         this.serviceOverrides = new Properties();
 1824  0
         this.serviceOverrides.putAll(serviceOverrides);
 1825  0
     }
 1826  
 
 1827  
     /**
 1828  
      * Will get the output stream for this type of transport. Typically this
 1829  
      * will be called only when Streaming is being used on an outbound endpoint.
 1830  
      * If Streaming is not supported by this transport an {@link UnsupportedOperationException}
 1831  
      * is thrown.   Note that the stream MUST release resources on close.  For help doing so, see
 1832  
      * {@link org.mule.impl.model.streaming.CallbackOutputStream}.
 1833  
      *
 1834  
      * @param endpoint the endpoint that releates to this Dispatcher
 1835  
      * @param message the current message being processed
 1836  
      * @return the output stream to use for this request
 1837  
      * @throws UMOException in case of any error
 1838  
      */
 1839  
     public OutputStream getOutputStream(UMOImmutableEndpoint endpoint, UMOMessage message)
 1840  
         throws UMOException
 1841  
     {
 1842  0
         throw new UnsupportedOperationException(
 1843  
             CoreMessages.streamingNotSupported(this.getProtocol()).toString());
 1844  
     }
 1845  
 
 1846  
     // @Override
 1847  
     public String toString()
 1848  
     {
 1849  100
         final StringBuffer sb = new StringBuffer(120);
 1850  100
         sb.append(ClassUtils.getSimpleName(this.getClass()));
 1851  100
         sb.append("{this=").append(Integer.toHexString(System.identityHashCode(this)));
 1852  100
         sb.append(", started=").append(started);
 1853  100
         sb.append(", initialised=").append(initialised);
 1854  100
         sb.append(", name='").append(name).append('\'');
 1855  100
         sb.append(", disposed=").append(disposed);
 1856  100
         sb.append(", numberOfConcurrentTransactedReceivers=").append(numberOfConcurrentTransactedReceivers);
 1857  100
         sb.append(", createMultipleTransactedReceivers=").append(createMultipleTransactedReceivers);
 1858  100
         sb.append(", connected=").append(connected);
 1859  100
         sb.append(", supportedProtocols=").append(supportedProtocols);
 1860  100
         sb.append(", serviceOverrides=").append(serviceOverrides);
 1861  100
         sb.append('}');
 1862  100
         return sb.toString();
 1863  
     }
 1864  
 }