Coverage Report - org.mule.module.client.MuleClient
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleClient
32%
70/216
25%
19/76
2.409
MuleClient$1
0%
0/2
N/A
2.409
MuleClient$2
0%
0/2
N/A
2.409
 
 1  
 /*
 2  
  * $Id: MuleClient.java 11775 2008-05-15 13:44:09Z 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.module.client;
 12  
 
 13  
 import org.mule.DefaultMuleEvent;
 14  
 import org.mule.DefaultMuleMessage;
 15  
 import org.mule.DefaultMuleSession;
 16  
 import org.mule.MuleServer;
 17  
 import org.mule.api.FutureMessageResult;
 18  
 import org.mule.api.MessagingException;
 19  
 import org.mule.api.MuleContext;
 20  
 import org.mule.api.MuleEvent;
 21  
 import org.mule.api.MuleException;
 22  
 import org.mule.api.MuleMessage;
 23  
 import org.mule.api.MuleSession;
 24  
 import org.mule.api.config.ConfigurationBuilder;
 25  
 import org.mule.api.config.ConfigurationException;
 26  
 import org.mule.api.config.MuleConfiguration;
 27  
 import org.mule.api.config.MuleProperties;
 28  
 import org.mule.api.context.MuleContextBuilder;
 29  
 import org.mule.api.endpoint.EndpointBuilder;
 30  
 import org.mule.api.endpoint.EndpointURI;
 31  
 import org.mule.api.endpoint.ImmutableEndpoint;
 32  
 import org.mule.api.endpoint.InboundEndpoint;
 33  
 import org.mule.api.endpoint.OutboundEndpoint;
 34  
 import org.mule.api.lifecycle.Disposable;
 35  
 import org.mule.api.lifecycle.InitialisationException;
 36  
 import org.mule.api.registry.RegistrationException;
 37  
 import org.mule.api.service.Service;
 38  
 import org.mule.api.transport.DispatchException;
 39  
 import org.mule.api.transport.ReceiveException;
 40  
 import org.mule.config.DefaultMuleConfiguration;
 41  
 import org.mule.config.i18n.CoreMessages;
 42  
 import org.mule.config.spring.SpringXmlConfigurationBuilder;
 43  
 import org.mule.context.DefaultMuleContextBuilder;
 44  
 import org.mule.context.DefaultMuleContextFactory;
 45  
 import org.mule.endpoint.EndpointURIEndpointBuilder;
 46  
 import org.mule.endpoint.MuleEndpointURI;
 47  
 import org.mule.module.client.i18n.ClientMessages;
 48  
 import org.mule.security.MuleCredentials;
 49  
 import org.mule.transformer.TransformerUtils;
 50  
 import org.mule.transport.AbstractConnector;
 51  
 import org.mule.transport.NullPayload;
 52  
 import org.mule.util.StringUtils;
 53  
 
 54  
 import java.util.ArrayList;
 55  
 import java.util.HashMap;
 56  
 import java.util.Iterator;
 57  
 import java.util.LinkedList;
 58  
 import java.util.List;
 59  
 import java.util.Map;
 60  
 
 61  
 import edu.emory.mathcs.backport.java.util.concurrent.Callable;
 62  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 63  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
 64  
 
 65  
 import org.apache.commons.logging.Log;
 66  
 import org.apache.commons.logging.LogFactory;
 67  
 
 68  
 /**
 69  
  * <code>MuleClient</code> is a simple interface for Mule clients to send and
 70  
  * receive events from a Mule Server. In most Mule applications events are triggered
 71  
  * by some external occurrence such as a message being received on a queue or a file
 72  
  * being copied to a directory. The Mule client allows the user to send and receive
 73  
  * events programmatically through its API.
 74  
  * <p>
 75  
  * The client defines a {@link EndpointURI} which is used to determine how a message is
 76  
  * sent of received. The url defines the protocol, the endpointUri destination of the
 77  
  * message and optionally the endpoint to use when dispatching the event. For
 78  
  * example:
 79  
  * <p>
 80  
  * <code>vm://my.object</code> dispatches to a <code>my.object</code> destination
 81  
  * using the VM endpoint. There needs to be a global VM endpoint registered for the
 82  
  * message to be sent.
 83  
  * <p>
 84  
  * <code>jms://jmsProvider/orders.topic</code> dispatches a JMS message via the
 85  
  * globally registered jmsProvider over a topic destination called
 86  
  * <code>orders.topic</code>.
 87  
  * <p>
 88  
  * <code>jms://orders.topic</code> is equivalent to the above except that the
 89  
  * endpoint is determined by the protocol, so the first JMS endpoint is used.
 90  
  * <p>
 91  
  * Note that there must be a configured MuleManager for this client to work. It will
 92  
  * use the one available using <code>muleContext</code>
 93  
  * 
 94  
  * @see org.mule.endpoint.MuleEndpointURI
 95  
  */
 96  
 public class MuleClient implements Disposable
 97  
 {
 98  
     /**
 99  
      * logger used by this class
 100  
      */
 101  2
     protected static final Log logger = LogFactory.getLog(MuleClient.class);
 102  
 
 103  
     /**
 104  
      * the local UMOManager instance
 105  
      */
 106  
     private MuleContext muleContext;
 107  
 
 108  12
     private List dispatchers = new ArrayList();
 109  
 
 110  
     private MuleCredentials user;
 111  
 
 112  12
     private DefaultMuleContextFactory muleContextFactory = new DefaultMuleContextFactory();
 113  
     
 114  12
     private ConcurrentMap inboundEndpointCache = new ConcurrentHashMap();
 115  12
     private ConcurrentMap outboundEndpointCache = new ConcurrentHashMap();
 116  
 
 117  
     /**
 118  
      * Creates a Mule client that will use the default serverEndpoint when connecting to a remote 
 119  
      * server instance.
 120  
      * 
 121  
      * @throws MuleException
 122  
      */
 123  
     public MuleClient() throws MuleException
 124  
     {
 125  12
         this(true);
 126  12
     }
 127  
 
 128  
     public MuleClient(boolean startContext) throws MuleException
 129  12
     {
 130  12
         init(startContext);
 131  12
     }
 132  
 
 133  
     public MuleClient(MuleContext context) throws MuleException
 134  0
     {
 135  0
         this.muleContext = context;
 136  0
         init(false);
 137  0
     }
 138  
 
 139  
     /**
 140  
      * Configures a Mule client instance using the the default
 141  
      * {@link SpringXmlConfigurationBuilder} to parse <code>configResources</code>.
 142  
      * 
 143  
      * @param configResources a config resource location to configure this client
 144  
      *            with
 145  
      * @throws ConfigurationException if there is a {@link MuleContext} instance already
 146  
      *             running in this JVM or if the builder fails to configure the
 147  
      *             Manager
 148  
      */
 149  
     public MuleClient(String configResources) throws MuleException
 150  
     {
 151  0
         this(configResources, new SpringXmlConfigurationBuilder(configResources));
 152  0
     }
 153  
 
 154  
     /**
 155  
      * Configures a new Mule client and either uses an existing Manager running in
 156  
      * this JVM or creates a new empty {@link MuleContext}
 157  
      * 
 158  
      * @param user the username to use when connecting to a remote server instance
 159  
      * @param password the password for the user
 160  
      * @throws MuleException
 161  
      */
 162  
     public MuleClient(String user, String password) throws MuleException
 163  0
     {
 164  0
         init(/* startManager */true);
 165  0
         this.user = new MuleCredentials(user, password.toCharArray());
 166  0
     }
 167  
 
 168  
     /**
 169  
      * Configures a Mule client instance
 170  
      * 
 171  
      * @param configResources a config resource location to configure this client
 172  
      *            with
 173  
      * @param builder the configuration builder to use
 174  
      * @throws ConfigurationException is there is a {@link MuleContext} instance already
 175  
      *             running in this JVM or if the builder fails to configure the
 176  
      *             Manager
 177  
      * @throws InitialisationException
 178  
      */
 179  
     public MuleClient(String configResources, ConfigurationBuilder builder)
 180  
         throws ConfigurationException, InitialisationException
 181  0
     {
 182  0
         if (builder == null)
 183  
         {
 184  0
             logger.info("Builder passed in was null, using default builder: "
 185  
                         + SpringXmlConfigurationBuilder.class.getName());
 186  0
             builder = new SpringXmlConfigurationBuilder(configResources);
 187  
         }
 188  0
         logger.info("Initializing Mule...");
 189  0
         muleContext = muleContextFactory.createMuleContext(builder);
 190  0
     }
 191  
 
 192  
     /**
 193  
      * Configures a Mule client instance
 194  
      * 
 195  
      * @param configResources a config resource location to configure this client
 196  
      *            with
 197  
      * @param builder the configuration builder to use
 198  
      * @param user the username to use when connecting to a remote server instance
 199  
      * @param password the password for the user
 200  
      * @throws ConfigurationException is there is a {@link MuleContext} instance already
 201  
      *             running in this JVM or if the builder fails to configure the
 202  
      *             Manager
 203  
      * @throws InitialisationException
 204  
      */
 205  
     public MuleClient(String configResources, ConfigurationBuilder builder, String user, String password)
 206  
         throws ConfigurationException, InitialisationException
 207  
     {
 208  0
         this(configResources, builder);
 209  0
         this.user = new MuleCredentials(user, password.toCharArray());
 210  0
     }
 211  
 
 212  
     /**
 213  
      * Initialises a default {@link MuleContext} for use by the client.
 214  
      * 
 215  
      * @param startManager start the Mule context if it has not yet been initialised
 216  
      * @throws MuleException
 217  
      */
 218  
     private void init(boolean startManager) throws MuleException
 219  
     {
 220  
         // if we are creating a server for this client then set client mode
 221  
         // this will disable Admin connections by default;
 222  
         // If there is no local muleContext present create a default muleContext
 223  12
         if (muleContext == null)
 224  
         {
 225  12
             muleContext = MuleServer.getMuleContext();
 226  
         }
 227  12
         if (muleContext == null)
 228  
         {
 229  6
             logger.info("No existing ManagementContext found, creating a new Mule instance");
 230  
 
 231  6
             MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
 232  6
             DefaultMuleConfiguration config = new DefaultMuleConfiguration();
 233  6
             config.setClientMode(true);
 234  6
             contextBuilder.setMuleConfiguration(config);
 235  6
             muleContext = muleContextFactory.createMuleContext(contextBuilder);
 236  6
         }
 237  
         else
 238  
         {
 239  6
             logger.info("Using existing MuleContext: " + muleContext);
 240  
         }
 241  
 
 242  12
         if (!muleContext.isStarted() && startManager == true)
 243  
         {
 244  12
             logger.info("Starting Mule...");
 245  12
             muleContext.start();
 246  
         }
 247  12
     }
 248  
 
 249  
     /**
 250  
      * Dispatches an event asynchronously to a endpointUri via a Mule server. The URL
 251  
      * determines where to dispatch the event to.
 252  
      * 
 253  
      * @param url the Mule URL used to determine the destination and transport of the
 254  
      *            message
 255  
      * @param payload the object that is the payload of the event
 256  
      * @param messageProperties any properties to be associated with the payload. In
 257  
      *            the case of JMS you could set the JMSReplyTo property in these
 258  
      *            properties.
 259  
      * @throws org.mule.api.MuleException
 260  
      */
 261  
     public void dispatch(String url, Object payload, Map messageProperties) throws MuleException
 262  
     {
 263  4
         dispatch(url, new DefaultMuleMessage(payload, messageProperties));
 264  4
     }
 265  
 
 266  
     /**
 267  
      * Dispatches an event asynchronously to a endpointUri via a Mule server. The URL
 268  
      * determines where to dispatch the event to.
 269  
      * 
 270  
      * @param url the Mule URL used to determine the destination and transport of the
 271  
      *            message
 272  
      * @param message the message to send
 273  
      * @throws org.mule.api.MuleException
 274  
      */
 275  
     public void dispatch(String url, MuleMessage message) throws MuleException
 276  
     {
 277  4
         MuleEvent event = getEvent(message, url, false);
 278  
         try
 279  
         {
 280  4
             event.getSession().dispatchEvent(event);
 281  
         }
 282  0
         catch (MuleException e)
 283  
         {
 284  0
             throw e;
 285  
         }
 286  0
         catch (Exception e)
 287  
         {
 288  0
             throw new DispatchException(ClientMessages.failedToDispatchClientEvent(), event.getMessage(),
 289  
                 event.getEndpoint(), e);
 290  4
         }
 291  4
     }
 292  
 
 293  
     /**
 294  
      * Sends an event synchronously to a component
 295  
      * 
 296  
      * @param component the name of the Mule component to send to
 297  
      * @param transformers a comma separated list of transformers to apply to the
 298  
      *            result message
 299  
      * @param payload the object that is the payload of the event
 300  
      * @param messageProperties any properties to be associated with the payload. as
 301  
      *            null
 302  
      * @return the result message if any of the invocation
 303  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 304  
      *             transfromers cannot be found
 305  
      */
 306  
     public MuleMessage sendDirect(String component, String transformers, Object payload, Map messageProperties)
 307  
         throws MuleException
 308  
     {
 309  0
         MuleMessage message = new DefaultMuleMessage(payload, messageProperties);
 310  0
         return sendDirect(component, transformers, message);
 311  
     }
 312  
 
 313  
     /**
 314  
      * Sends an event synchronously to a component
 315  
      * 
 316  
      * @param componentName the name of the Mule component to send to
 317  
      * @param transformers a comma separated list of transformers to apply to the
 318  
      *            result message
 319  
      * @param message the message to send
 320  
      * @return the result message if any of the invocation
 321  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 322  
      *             transfromers cannot be found
 323  
      */
 324  
     public MuleMessage sendDirect(String componentName, String transformers, MuleMessage message)
 325  
         throws MuleException
 326  
     {
 327  0
         Service service = muleContext.getRegistry().lookupService(componentName);
 328  0
         if (service == null)
 329  
         {
 330  0
             throw new MessagingException(CoreMessages.objectNotRegistered("Service", componentName),
 331  
                 message);
 332  
         }
 333  0
         List trans = null;
 334  0
         if (transformers != null)
 335  
         {
 336  0
             trans = TransformerUtils.getTransformers(transformers);
 337  
         }
 338  
 
 339  0
         if (!muleContext.getConfiguration().isDefaultSynchronousEndpoints())
 340  
         {
 341  0
             logger.warn("The mule muleContext is not running synchronously, a null message payload will be returned");
 342  
         }
 343  0
         MuleSession session = new DefaultMuleSession(service, muleContext);
 344  0
         ImmutableEndpoint endpoint = getDefaultClientEndpoint(service, message.getPayload());
 345  0
         MuleEvent event = new DefaultMuleEvent(message, endpoint, session, true);
 346  
 
 347  0
         if (logger.isDebugEnabled())
 348  
         {
 349  0
             logger.debug("MuleClient sending event direct to: " + componentName + ". MuleEvent is: " + event);
 350  
         }
 351  
 
 352  0
         MuleMessage result = event.getService().sendEvent(event);
 353  
 
 354  0
         if (logger.isDebugEnabled())
 355  
         {
 356  0
             logger.debug("Result of MuleClient sendDirect is: "
 357  
                          + (result == null ? "null" : result.getPayload()));
 358  
         }
 359  
 
 360  0
         if (result != null && trans != null)
 361  
         {
 362  0
             result.applyTransformers(trans);
 363  
         }
 364  0
         return result;
 365  
     }
 366  
 
 367  
     /**
 368  
      * Dispatches an event asynchronously to a component
 369  
      * 
 370  
      * @param component the name of the Mule components to dispatch to
 371  
      * @param payload the object that is the payload of the event
 372  
      * @param messageProperties any properties to be associated with the payload. as
 373  
      *            null
 374  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 375  
      *             transfromers cannot be found
 376  
      */
 377  
     public void dispatchDirect(String component, Object payload, Map messageProperties) throws MuleException
 378  
     {
 379  0
         dispatchDirect(component, new DefaultMuleMessage(payload, messageProperties));
 380  0
     }
 381  
 
 382  
     /**
 383  
      * Dispatches an event asynchronously to a component
 384  
      * 
 385  
      * @param componentName the name of the Mule components to dispatch to
 386  
      * @param message the message to send
 387  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 388  
      *             transfromers cannot be found
 389  
      */
 390  
     public void dispatchDirect(String componentName, MuleMessage message) throws MuleException
 391  
     {
 392  0
         Service service = muleContext.getRegistry().lookupService(componentName);
 393  0
         if (service == null)
 394  
         {
 395  0
             throw new MessagingException(CoreMessages.objectNotRegistered("Service", componentName),
 396  
                 message);
 397  
         }
 398  0
         MuleSession session = new DefaultMuleSession(service, muleContext);
 399  0
         ImmutableEndpoint endpoint = getDefaultClientEndpoint(service, message.getPayload());
 400  0
         MuleEvent event = new DefaultMuleEvent(message, endpoint, session, true);
 401  
 
 402  0
         if (logger.isDebugEnabled())
 403  
         {
 404  0
             logger.debug("MuleClient dispatching event direct to: " + componentName + ". MuleEvent is: " + event);
 405  
         }
 406  
 
 407  0
         event.getService().dispatchEvent(event);
 408  0
     }
 409  
 
 410  
     /**
 411  
      * Sends an event request to a URL, making the result of the event trigger
 412  
      * available as a Future result that can be accessed later by client code.
 413  
      * 
 414  
      * @param url the url to make a request on
 415  
      * @param payload the object that is the payload of the event
 416  
      * @param messageProperties any properties to be associated with the payload. as
 417  
      *            null
 418  
      * @return the result message if any of the invocation
 419  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 420  
      *             transfromers cannot be found
 421  
      */
 422  
     public FutureMessageResult sendAsync(final String url, final Object payload, final Map messageProperties)
 423  
         throws MuleException
 424  
     {
 425  0
         return sendAsync(url, payload, messageProperties, 0);
 426  
     }
 427  
 
 428  
     /**
 429  
      * Sends an event request to a URL, making the result of the event trigger
 430  
      * available as a Future result that can be accessed later by client code.
 431  
      * 
 432  
      * @param url the URL to make a request on
 433  
      * @param message the message to send
 434  
      * @return the result message if any of the invocation
 435  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 436  
      *             transfromers cannot be found
 437  
      */
 438  
     public FutureMessageResult sendAsync(final String url, final MuleMessage message) throws MuleException
 439  
     {
 440  0
         return sendAsync(url, message, MuleEvent.TIMEOUT_NOT_SET_VALUE);
 441  
     }
 442  
 
 443  
     /**
 444  
      * Sends an event request to a URL, making the result of the event trigger
 445  
      * available as a Future result that can be accessed later by client code.
 446  
      * 
 447  
      * @param url the url to make a request on
 448  
      * @param payload the object that is the payload of the event
 449  
      * @param messageProperties any properties to be associated with the payload. as
 450  
      *            null
 451  
      * @param timeout how long to block in milliseconds waiting for a result
 452  
      * @return the result message if any of the invocation
 453  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 454  
      *             transfromers cannot be found
 455  
      */
 456  
     public FutureMessageResult sendAsync(final String url,
 457  
                                          final Object payload,
 458  
                                          final Map messageProperties,
 459  
                                          final int timeout) throws MuleException
 460  
     {
 461  0
         return sendAsync(url, new DefaultMuleMessage(payload, messageProperties), timeout);
 462  
     }
 463  
 
 464  
     /**
 465  
      * Sends an event request to a URL, making the result of the event trigger
 466  
      * available as a Future result that can be accessed later by client code.
 467  
      * 
 468  
      * @param url the url to make a request on
 469  
      * @param message the message to send
 470  
      * @param timeout how long to block in milliseconds waiting for a result
 471  
      * @return the result message if any of the invocation
 472  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 473  
      *             transfromers cannot be found
 474  
      */
 475  
     public FutureMessageResult sendAsync(final String url, final MuleMessage message, final int timeout)
 476  
         throws MuleException
 477  
     {
 478  0
         Callable call = new Callable()
 479  
         {
 480  0
             public Object call() throws Exception
 481  
             {
 482  0
                 return send(url, message, timeout);
 483  
             }
 484  
         };
 485  
 
 486  0
         FutureMessageResult result = new FutureMessageResult(call);
 487  
 
 488  0
         if (muleContext.getWorkManager() != null)
 489  
         {
 490  0
             result.setExecutor(muleContext.getWorkManager());
 491  
         }
 492  
 
 493  0
         result.execute();
 494  0
         return result;
 495  
     }
 496  
 
 497  
     /**
 498  
      * Sends an event to a component on a local Mule instance, while making the
 499  
      * result of the event trigger available as a Future result that can be accessed
 500  
      * later by client code. Users can specify a url to a remote Mule server in the
 501  
      * constructor of a Mule client, by default the default Mule server url
 502  
      * <code>tcp://localhost:60504</code> is used.
 503  
      * 
 504  
      * @param component the name of the Mule components to send to
 505  
      * @param transformers a comma separated list of transformers to apply to the
 506  
      *            result message
 507  
      * @param payload the object that is the payload of the event
 508  
      * @param messageProperties any properties to be associated with the payload.
 509  
      * @return the result message if any of the invocation
 510  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 511  
      *             transfromers cannot be found
 512  
      */
 513  
     public FutureMessageResult sendDirectAsync(final String component,
 514  
                                                String transformers,
 515  
                                                final Object payload,
 516  
                                                final Map messageProperties) throws MuleException
 517  
     {
 518  0
         return sendDirectAsync(component, transformers, new DefaultMuleMessage(payload, messageProperties));
 519  
     }
 520  
 
 521  
     /**
 522  
      * Snds an event to a component on a local Mule instance, while making the result
 523  
      * of the event trigger available as a Future result that can be accessed later
 524  
      * by client code. Users can specify a url to a remote Mule server in the
 525  
      * constructor of a Mule client, by default the default Mule server url
 526  
      * <code>tcp://localhost:60504</code> is used.
 527  
      * 
 528  
      * @param component the name of the Mule components to send to
 529  
      * @param transformers a comma separated list of transformers to apply to the
 530  
      *            result message
 531  
      * @param message the message to send
 532  
      * @return the result message if any of the invocation
 533  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 534  
      *             transfromers cannot be found
 535  
      */
 536  
     public FutureMessageResult sendDirectAsync(final String component,
 537  
                                                String transformers,
 538  
                                                final MuleMessage message) throws MuleException
 539  
     {
 540  0
         Callable call = new Callable()
 541  
         {
 542  0
             public Object call() throws Exception
 543  
             {
 544  0
                 return sendDirect(component, null, message);
 545  
             }
 546  
         };
 547  
 
 548  0
         FutureMessageResult result = new FutureMessageResult(call);
 549  
 
 550  0
         if (muleContext.getWorkManager() != null)
 551  
         {
 552  0
             result.setExecutor(muleContext.getWorkManager());
 553  
         }
 554  
 
 555  0
         if (StringUtils.isNotBlank(transformers))
 556  
         {
 557  0
             result.setTransformers(TransformerUtils.getTransformers(transformers));
 558  
         }
 559  
 
 560  0
         result.execute();
 561  0
         return result;
 562  
     }
 563  
 
 564  
     /**
 565  
      * Sends an event synchronously to a endpointUri via a Mule server and a
 566  
      * resulting message is returned.
 567  
      * 
 568  
      * @param url the Mule URL used to determine the destination and transport of the
 569  
      *            message
 570  
      * @param payload the object that is the payload of the event
 571  
      * @param messageProperties any properties to be associated with the payload. In
 572  
      *            the case of Jms you could set the JMSReplyTo property in these
 573  
      *            properties.
 574  
      * @return A return message, this could be <code>null</code> if the the components invoked
 575  
      *         explicitly sets a return as <code>null</code>.
 576  
      * @throws org.mule.api.MuleException
 577  
      */
 578  
     public MuleMessage send(String url, Object payload, Map messageProperties) throws MuleException
 579  
     {
 580  4
         return send(url, payload, messageProperties, MuleEvent.TIMEOUT_NOT_SET_VALUE);
 581  
     }
 582  
 
 583  
     /**
 584  
      * Sends an event synchronously to a endpointUri via a Mule server and a
 585  
      * resulting message is returned.
 586  
      * 
 587  
      * @param url the Mule URL used to determine the destination and transport of the
 588  
      *            message
 589  
      * @param message the Message for the event
 590  
      * @return A return message, this could be <code>null</code> if the the components invoked
 591  
      *         explicitly sets a return as <code>null</code>.
 592  
      * @throws org.mule.api.MuleException
 593  
      */
 594  
     public MuleMessage send(String url, MuleMessage message) throws MuleException
 595  
     {
 596  0
         return send(url, message, MuleEvent.TIMEOUT_NOT_SET_VALUE);
 597  
     }
 598  
 
 599  
     /**
 600  
      * Sends an event synchronously to a endpointUri via a mule server and a
 601  
      * resulting message is returned.
 602  
      * 
 603  
      * @param url the Mule URL used to determine the destination and transport of the
 604  
      *            message
 605  
      * @param payload the object that is the payload of the event
 606  
      * @param messageProperties any properties to be associated with the payload. In
 607  
      *            the case of Jms you could set the JMSReplyTo property in these
 608  
      *            properties.
 609  
      * @param timeout The time in milliseconds the the call should block waiting for
 610  
      *            a response
 611  
      * @return A return message, this could be <code>null</code> if the the components invoked
 612  
      *         explicitly sets a return as <code>null</code>.
 613  
      * @throws org.mule.api.MuleException
 614  
      */
 615  
     public MuleMessage send(String url, Object payload, Map messageProperties, int timeout)
 616  
         throws MuleException
 617  
     {
 618  4
         if (messageProperties == null)
 619  
         {
 620  4
             messageProperties = new HashMap();
 621  
         }
 622  4
         if (messageProperties.get(MuleProperties.MULE_REMOTE_SYNC_PROPERTY) == null)
 623  
         {
 624  4
             messageProperties.put(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, "true");
 625  
         }
 626  4
         MuleMessage message = new DefaultMuleMessage(payload, messageProperties);
 627  4
         return send(url, message, timeout);
 628  
     }
 629  
 
 630  
     /**
 631  
      * Sends an event synchronously to a endpointUri via a mule server and a
 632  
      * resulting message is returned.
 633  
      * 
 634  
      * @param url the Mule URL used to determine the destination and transport of the
 635  
      *            message
 636  
      * @param message The message to send
 637  
      * @param timeout The time in milliseconds the the call should block waiting for
 638  
      *            a response
 639  
      * @return A return message, this could be <code>null</code> if the the components invoked
 640  
      *         explicitly sets a return as <code>null</code>.
 641  
      * @throws org.mule.api.MuleException
 642  
      */
 643  
     public MuleMessage send(String url, MuleMessage message, int timeout) throws MuleException
 644  
     {
 645  4
         MuleEvent event = getEvent(message, url, true);
 646  4
         event.setTimeout(timeout);
 647  
 
 648  
         try
 649  
         {
 650  4
             MuleMessage msg = event.getSession().sendEvent(event);
 651  4
             if (msg == null)
 652  
             {
 653  0
                 msg = new DefaultMuleMessage(NullPayload.getInstance());
 654  
             }
 655  4
             return msg;
 656  
         }
 657  0
         catch (MuleException e)
 658  
         {
 659  0
             throw e;
 660  
         }
 661  0
         catch (Exception e)
 662  
         {
 663  0
             throw new DispatchException(ClientMessages.failedToDispatchClientEvent(), event.getMessage(),
 664  
                 event.getEndpoint(), e);
 665  
         }
 666  
     }
 667  
 
 668  
     /**
 669  
      * Will receive an event from an endpointUri determined by the URL.
 670  
      * 
 671  
      * @param url the Mule URL used to determine the destination and transport of the
 672  
      *            message
 673  
      * @param timeout how long to block waiting to receive the event, if set to 0 the
 674  
      *            receive will not wait at all and if set to -1 the receive will wait
 675  
      *            forever
 676  
      * @return the message received or <code>null</code> if no message was received
 677  
      * @throws org.mule.api.MuleException
 678  
      */
 679  
     public MuleMessage request(String url, long timeout) throws MuleException
 680  
     {
 681  0
         InboundEndpoint endpoint = getInboundEndpoint(url);
 682  
         try
 683  
         {
 684  0
             MuleMessage message = endpoint.request(timeout);
 685  0
             if (message != null && endpoint.getTransformers() != null)
 686  
             {
 687  0
                 message.applyTransformers(endpoint.getTransformers());
 688  
             }
 689  0
             return message;
 690  
         }
 691  0
         catch (Exception e)
 692  
         {
 693  0
             throw new ReceiveException(endpoint, timeout, e);
 694  
         }
 695  
     }
 696  
 
 697  
     /**
 698  
      * Will receive an event from an endpointUri determined by the URL
 699  
      * 
 700  
      * @param url the Mule URL used to determine the destination and transport of the
 701  
      *            message
 702  
      * @param transformers A comma separated list of transformers used to apply to
 703  
      *            the result message
 704  
      * @param timeout how long to block waiting to receive the event, if set to 0 the
 705  
      *            receive will not wait at all and if set to -1 the receive will wait
 706  
      *            forever
 707  
      * @return the message received or <code>null</code> if no message was received
 708  
      * @throws org.mule.api.MuleException
 709  
      */
 710  
     public MuleMessage request(String url, String transformers, long timeout) throws MuleException
 711  
     {
 712  0
         return request(url, TransformerUtils.getTransformers(transformers), timeout);
 713  
     }
 714  
 
 715  
     /**
 716  
      * Will receive an event from an endpointUri determined by the URL
 717  
      * 
 718  
      * @param url the Mule URL used to determine the destination and transport of the
 719  
      *            message
 720  
      * @param transformers Transformers used to modify the result message
 721  
      * @param timeout how long to block waiting to receive the event, if set to 0 the
 722  
      *            receive will not wait at all and if set to -1 the receive will wait
 723  
      *            forever
 724  
      * @return the message received or <code>null</code> if no message was received
 725  
      * @throws org.mule.api.MuleException
 726  
      */
 727  
     public MuleMessage request(String url, List transformers, long timeout) throws MuleException
 728  
     {
 729  0
         MuleMessage message = request(url, timeout);
 730  0
         if (message != null && transformers != null)
 731  
         {
 732  0
             message.applyTransformers(transformers);
 733  
         }
 734  0
         return message;
 735  
     }
 736  
 
 737  
     /**
 738  
      * Packages a mule event for the current request
 739  
      * 
 740  
      * @param message the event payload
 741  
      * @param uri the destination endpointUri
 742  
      * @param synchronous whether the event will be synchronously processed
 743  
      * @return the MuleEvent
 744  
      * @throws MuleException
 745  
      */
 746  
     protected MuleEvent getEvent(MuleMessage message, String uri, boolean synchronous)
 747  
         throws MuleException
 748  
     {
 749  8
         ImmutableEndpoint endpoint = getOutboundEndpoint(uri);
 750  8
         if (!endpoint.getConnector().isStarted() && muleContext.isStarted())
 751  
         {
 752  0
             endpoint.getConnector().start();
 753  
         }
 754  
         try
 755  
         {
 756  8
             DefaultMuleSession session = new DefaultMuleSession(message,
 757  
                 ((AbstractConnector) endpoint.getConnector()).getSessionHandler(), muleContext);
 758  
 
 759  8
             if (user != null)
 760  
             {
 761  0
                 message.setProperty(MuleProperties.MULE_USER_PROPERTY, MuleCredentials.createHeader(
 762  
                     user.getUsername(), user.getPassword()));
 763  
             }
 764  8
             DefaultMuleEvent event = new DefaultMuleEvent(message, endpoint, session, synchronous);
 765  8
             return event;
 766  
         }
 767  0
         catch (Exception e)
 768  
         {
 769  0
             throw new DispatchException(CoreMessages.failedToCreate("Client event"), message, endpoint, e);
 770  
         }
 771  
     }
 772  
 
 773  
     protected InboundEndpoint getInboundEndpoint(String uri) throws MuleException
 774  
     {
 775  
         // There was a potential leak here between get() and putIfAbsent(). This
 776  
         // would cause the endpoint that was created to be used rather an endpoint
 777  
         // with the same key that has been created and put in the cache by another
 778  
         // thread. To avoid this we test for the result of putIfAbsent result and if
 779  
         // it is non-null then an endpoint was created and added concurrently and we
 780  
         // return this instance instead.
 781  16
         InboundEndpoint endpoint = (InboundEndpoint) inboundEndpointCache.get(uri);
 782  16
         if (endpoint == null)
 783  
         {
 784  8
             endpoint = muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(uri);
 785  8
             InboundEndpoint concurrentlyAddedEndpoint = (InboundEndpoint) inboundEndpointCache.putIfAbsent(uri, endpoint);
 786  8
             if (concurrentlyAddedEndpoint != null)
 787  
             {
 788  0
                 return concurrentlyAddedEndpoint;
 789  
             }
 790  
         }
 791  16
         return endpoint;
 792  
     }
 793  
 
 794  
     protected OutboundEndpoint getOutboundEndpoint(String uri) throws MuleException
 795  
     {
 796  
         // There was a potential leak here between get() and putIfAbsent(). This
 797  
         // would cause the endpoint that was created to be used rather an endpoint
 798  
         // with the same key that has been created and put in the cache by another
 799  
         // thread. To avoid this we test for the result of putIfAbsent result and if
 800  
         // it is non-null then an endpoint was created and added concurrently and we
 801  
         // return this instance instead.
 802  24
         OutboundEndpoint endpoint = (OutboundEndpoint) outboundEndpointCache.get(uri);
 803  24
         if (endpoint == null)
 804  
         {
 805  12
             endpoint = muleContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(uri);
 806  12
             OutboundEndpoint concurrentlyAddedEndpoint = (OutboundEndpoint) outboundEndpointCache.putIfAbsent(uri, endpoint);
 807  12
             if (concurrentlyAddedEndpoint != null)
 808  
             {
 809  0
                 return concurrentlyAddedEndpoint;
 810  
             }
 811  
         }
 812  24
         return endpoint;
 813  
     }
 814  
 
 815  
     protected ImmutableEndpoint getDefaultClientEndpoint(Service service, Object payload)
 816  
         throws MuleException
 817  
     {
 818  
         // as we are bypassing the message transport layer we need to check that
 819  0
         ImmutableEndpoint endpoint = (ImmutableEndpoint) service.getInboundRouter().getEndpoints().get(0);
 820  0
         if (endpoint != null)
 821  
         {
 822  0
             if (endpoint.getTransformers() != null)
 823  
             {
 824  
                 // the original code here really did just check the first exception
 825  
                 // as far as i can tell
 826  0
                 if (TransformerUtils.isSourceTypeSupportedByFirst(endpoint.getTransformers(),
 827  
                     payload.getClass()))
 828  
                 {
 829  0
                     return endpoint;
 830  
                 }
 831  
                 else
 832  
                 {
 833  0
                     EndpointBuilder builder = new EndpointURIEndpointBuilder(endpoint, muleContext);
 834  0
                     builder.setTransformers(new LinkedList());
 835  0
                     return muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(builder);
 836  
                 }
 837  
             }
 838  
             else
 839  
             {
 840  0
                 return endpoint;
 841  
             }
 842  
         }
 843  
         else
 844  
         {
 845  0
             EndpointBuilder builder = new EndpointURIEndpointBuilder("vm://mule.client", muleContext);
 846  0
             builder.setName("muleClientProvider");
 847  0
             endpoint = muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(builder);
 848  
         }
 849  0
         return endpoint;
 850  
     }
 851  
 
 852  
     /**
 853  
      * Sends an event synchronously to a endpointUri via a Mule server without
 854  
      * waiting for the result.
 855  
      * 
 856  
      * @param url the Mule URL used to determine the destination and transport of the
 857  
      *            message
 858  
      * @param payload the object that is the payload of the event
 859  
      * @param messageProperties any properties to be associated with the payload. In
 860  
      *            the case of Jms you could set the JMSReplyTo property in these
 861  
      *            properties.
 862  
      * @throws org.mule.api.MuleException
 863  
      */
 864  
     public void sendNoReceive(String url, Object payload, Map messageProperties) throws MuleException
 865  
     {
 866  0
         if (messageProperties == null)
 867  
         {
 868  0
             messageProperties = new HashMap();
 869  
         }
 870  0
         messageProperties.put(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, "false");
 871  0
         MuleMessage message = new DefaultMuleMessage(payload, messageProperties);
 872  0
         MuleEvent event = getEvent(message, url, true);
 873  
         try
 874  
         {
 875  0
             event.getSession().sendEvent(event);
 876  
         }
 877  0
         catch (MuleException e)
 878  
         {
 879  0
             throw e;
 880  
         }
 881  0
         catch (Exception e)
 882  
         {
 883  0
             throw new DispatchException(ClientMessages.failedToDispatchClientEvent(), event.getMessage(),
 884  
                 event.getEndpoint(), e);
 885  0
         }
 886  0
     }
 887  
 
 888  
     /**
 889  
      * The overriding method may want to return a custom {@link MuleContext} here
 890  
      * 
 891  
      * @return the UMOManager to use
 892  
      */
 893  
     public MuleContext getMuleContext()
 894  
     {
 895  16
         return muleContext;
 896  
     }
 897  
 
 898  
     /**
 899  
      * Registers a Java object as a component that listens for events on the
 900  
      * given URL. By default the ThreadingProfile for the components will be set so
 901  
      * that there will only be one thread of execution.
 902  
      * 
 903  
      * @param component any java object, Mule will it's endpointUri discovery to
 904  
      *            determine which event to invoke based on the evnet payload type
 905  
      * @param name The identifying name of the components. This can be used to later
 906  
      *            unregister it
 907  
      * @param listenerEndpoint The url endpointUri to listen to
 908  
      * @throws MuleException
 909  
      * @deprecated Use the RegistryContext to get the registry and register the
 910  
      *             service there
 911  
      */
 912  
     public void registerComponent(Object component, String name, EndpointURI listenerEndpoint)
 913  
         throws MuleException
 914  
     {
 915  0
         throw new UnsupportedOperationException("registerComponent");
 916  
         // builder.registerComponentInstance(service, name, listenerEndpoint,
 917  
         // null);
 918  
     }
 919  
 
 920  
     /**
 921  
      * Registers a Java object as a component that listens for and sends events
 922  
      * on the given urls. By default the ThreadingProfile for the components will be
 923  
      * set so that there will only be one thread of execution.
 924  
      * 
 925  
      * @param component any java object, Mule will it's endpointUri discovery to
 926  
      *            determine which event to invoke based on the evnet payload type
 927  
      * @param name The identifying name of the components. This can be used to later
 928  
      *            unregister it
 929  
      * @param listenerEndpoint The url endpointUri to listen to
 930  
      * @param sendEndpoint The url endpointUri to dispatch to
 931  
      * @throws MuleException
 932  
      * @deprecated Use the RegistryContext to get the registry and register the
 933  
      *             service there
 934  
      */
 935  
     public void registerComponent(Object component,
 936  
                                   String name,
 937  
                                   MuleEndpointURI listenerEndpoint,
 938  
                                   MuleEndpointURI sendEndpoint) throws MuleException
 939  
     {
 940  0
         throw new UnsupportedOperationException("registerComponent");
 941  
         // builder.registerComponentInstance(service, name, listenerEndpoint,
 942  
         // sendEndpoint);
 943  
     }
 944  
 
 945  
     /**
 946  
      * Registers a user configured MuleDescriptor of a components to the server. If
 947  
      * users want to register object instances with the server rather than class
 948  
      * names that get created at runtime or reference to objects in the container,
 949  
      * the user must call the descriptors setImplementationInstance() method - <code>
 950  
      * MyBean implementation = new MyBean();
 951  
      * descriptor.setImplementationInstance(implementation);
 952  
      * </code>
 953  
      * Calling this method is equivilent to calling Model.registerComponent(..)
 954  
      * 
 955  
      * @param descriptor the componet descriptor to register
 956  
      * @throws MuleException the descriptor is invalid or cannot be initialised or
 957  
      *             started
 958  
      * @see org.mule.api.model.Model
 959  
      * @deprecated Use the RegistryContext to get the registry and register the
 960  
      *             service there
 961  
      */
 962  
     // public void registerComponent(UMODescriptor descriptor) throws MuleException
 963  
     // {
 964  
     // throw new UnsupportedOperationException("registerComponent");
 965  
     // //builder.registerComponent(descriptor);
 966  
     // }
 967  
     /**
 968  
      * Unregisters a previously register components. This will also unregister any
 969  
      * listeners for the components Calling this method is equivilent to calling
 970  
      * Model.unregisterComponent(..)
 971  
      * 
 972  
      * @param name the name of the componet to unregister
 973  
      * @throws MuleException if unregistering the components fails, i.e. The
 974  
      *             underlying transport fails to unregister a listener. If the
 975  
      *             components does not exist, this method should not throw an
 976  
      *             exception.
 977  
      * @see org.mule.api.model.Model
 978  
      * @deprecated Use the RegistryContext to get the registry and unregister the
 979  
      *             service there
 980  
      */
 981  
     public void unregisterComponent(String name) throws MuleException
 982  
     {
 983  0
         throw new UnsupportedOperationException("registerComponent");
 984  
 
 985  
         // builder.unregisterComponent(name);
 986  
     }
 987  
 
 988  
     public RemoteDispatcher getRemoteDispatcher(String serverEndpoint) throws MuleException
 989  
     {
 990  0
         RemoteDispatcher rd = new RemoteDispatcher(serverEndpoint);
 991  0
         rd.setExecutor(muleContext.getWorkManager());
 992  0
         dispatchers.add(rd);
 993  0
         return rd;
 994  
     }
 995  
 
 996  
     public RemoteDispatcher getRemoteDispatcher(String serverEndpoint, String user, String password)
 997  
         throws MuleException
 998  
     {
 999  0
         RemoteDispatcher rd = new RemoteDispatcher(serverEndpoint, new MuleCredentials(user,
 1000  
             password.toCharArray()));
 1001  0
         rd.setExecutor(muleContext.getWorkManager());
 1002  0
         dispatchers.add(rd);
 1003  0
         return rd;
 1004  
     }
 1005  
 
 1006  
     /**
 1007  
      * Will dispose the MuleManager instance <b>if</b> a new instance was created for this
 1008  
      * client. Otherwise this method only cleans up resources no longer needed
 1009  
      */
 1010  
     public void dispose()
 1011  
     {
 1012  4
         synchronized (dispatchers)
 1013  
         {
 1014  4
             for (Iterator iterator = dispatchers.iterator(); iterator.hasNext();)
 1015  
             {
 1016  0
                 RemoteDispatcher remoteDispatcher = (RemoteDispatcher) iterator.next();
 1017  0
                 remoteDispatcher.dispose();
 1018  0
                 remoteDispatcher = null;
 1019  0
             }
 1020  4
             dispatchers.clear();
 1021  4
         }
 1022  
         // Dispose the muleContext only if the muleContext was created for this
 1023  
         // client
 1024  4
         if (muleContext.getConfiguration().isClientMode())
 1025  
         {
 1026  2
             logger.info("Stopping Mule...");
 1027  2
             muleContext.dispose();
 1028  
         }
 1029  4
     }
 1030  
 
 1031  
     public void setProperty(String key, Object value)
 1032  
     {
 1033  
         try
 1034  
         {
 1035  0
             muleContext.getRegistry().registerObject(key, value);
 1036  
         }
 1037  0
         catch (RegistrationException e)
 1038  
         {
 1039  0
             logger.error(e);
 1040  0
         }
 1041  0
     }
 1042  
 
 1043  
     public Object getProperty(String key)
 1044  
     {
 1045  0
         return muleContext.getRegistry().lookupObject(key);
 1046  
     }
 1047  
 
 1048  
     public MuleConfiguration getConfiguration()
 1049  
     {
 1050  0
         return muleContext.getConfiguration();
 1051  
     }
 1052  
 }