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