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