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