Coverage Report - org.mule.module.client.RemoteDispatcher
 
Classes in this File Line Coverage Branch Coverage Complexity
RemoteDispatcher
0%
0/126
0%
0/42
2.208
RemoteDispatcher$1
0%
0/2
N/A
2.208
RemoteDispatcher$2
0%
0/2
N/A
2.208
RemoteDispatcher$3
0%
0/2
N/A
2.208
 
 1  
 /*
 2  
  * $Id: RemoteDispatcher.java 19368 2010-09-05 05:19:34Z mike.schilling $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.MessageExchangePattern;
 16  
 import org.mule.RequestContext;
 17  
 import org.mule.api.FutureMessageResult;
 18  
 import org.mule.api.MuleContext;
 19  
 import org.mule.api.MuleEvent;
 20  
 import org.mule.api.MuleException;
 21  
 import org.mule.api.MuleMessage;
 22  
 import org.mule.api.MuleSession;
 23  
 import org.mule.api.config.MuleProperties;
 24  
 import org.mule.api.endpoint.EndpointBuilder;
 25  
 import org.mule.api.endpoint.EndpointFactory;
 26  
 import org.mule.api.endpoint.ImmutableEndpoint;
 27  
 import org.mule.api.endpoint.OutboundEndpoint;
 28  
 import org.mule.api.lifecycle.Disposable;
 29  
 import org.mule.api.security.Credentials;
 30  
 import org.mule.api.transformer.wire.WireFormat;
 31  
 import org.mule.api.transport.DispatchException;
 32  
 import org.mule.client.DefaultLocalMuleClient.MuleClientFlowConstruct;
 33  
 import org.mule.module.client.i18n.ClientMessages;
 34  
 import org.mule.module.client.remoting.RemoteDispatcherException;
 35  
 import org.mule.module.client.remoting.ServerHandshake;
 36  
 import org.mule.module.client.remoting.UnsupportedWireFormatException;
 37  
 import org.mule.module.client.remoting.notification.RemoteDispatcherNotification;
 38  
 import org.mule.security.MuleCredentials;
 39  
 import org.mule.session.DefaultMuleSession;
 40  
 import org.mule.transformer.TransformerUtils;
 41  
 import org.mule.transport.NullPayload;
 42  
 import org.mule.util.ClassUtils;
 43  
 import org.mule.util.IOUtils;
 44  
 
 45  
 import java.io.ByteArrayInputStream;
 46  
 import java.io.ByteArrayOutputStream;
 47  
 import java.io.InputStream;
 48  
 import java.util.Map;
 49  
 
 50  
 import edu.emory.mathcs.backport.java.util.concurrent.Callable;
 51  
 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
 52  
 
 53  
 import org.apache.commons.lang.SerializationUtils;
 54  
 import org.apache.commons.logging.Log;
 55  
 import org.apache.commons.logging.LogFactory;
 56  
 
 57  
 /**
 58  
  * <code>RemoteDispatcher</code> is used to make and receive requests to a remote
 59  
  * Mule instance. It is used to proxy requests to Mule using the Server URL as the
 60  
  * transport channel.
 61  
  */
 62  
 
 63  
 public class RemoteDispatcher implements Disposable
 64  
 {
 65  
 
 66  
     /**
 67  
      * logger used by this class
 68  
      */
 69  0
     protected static final Log logger = LogFactory.getLog(RemoteDispatcher.class);
 70  
 
 71  
     /**
 72  
      * dispatch destination
 73  
      */
 74  
     private OutboundEndpoint asyncServerEndpoint;
 75  
     private OutboundEndpoint syncServerEndpoint;
 76  0
     private Credentials credentials = null;
 77  
     private MuleContext muleContext;
 78  
 
 79  
     /**
 80  
      * an ExecutorService for async messages (optional)
 81  
      */
 82  
     private Executor asyncExecutor;
 83  
 
 84  
     /**
 85  
      * calls made to a remote server are serialised using a wireformat
 86  
      */
 87  
     private WireFormat wireFormat;
 88  
 
 89  
     protected RemoteDispatcher(String endpoint, Credentials credentials, MuleContext muleContext) throws MuleException
 90  
     {
 91  0
         this(endpoint, muleContext);
 92  0
         this.credentials = credentials;
 93  0
     }
 94  
 
 95  
     protected RemoteDispatcher(String endpoint, MuleContext muleContext) throws MuleException
 96  0
     {
 97  0
         this.muleContext = muleContext;
 98  0
         EndpointFactory endpointFactory = muleContext.getRegistry().lookupEndpointFactory();
 99  0
         asyncServerEndpoint = endpointFactory.getOutboundEndpoint(endpoint);
 100  
 
 101  0
         EndpointBuilder endpointBuilder = endpointFactory.getEndpointBuilder(endpoint);
 102  0
         endpointBuilder.setExchangePattern(MessageExchangePattern.REQUEST_RESPONSE);
 103  0
         syncServerEndpoint = muleContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(
 104  
             endpointBuilder);
 105  
 
 106  0
         wireFormat = requestWireFormat();
 107  0
     }
 108  
 
 109  
     protected WireFormat requestWireFormat() throws MuleException
 110  
     {
 111  0
         MuleMessage msg = new DefaultMuleMessage(ServerHandshake.SERVER_HANDSHAKE_PROPERTY, muleContext);
 112  0
         MuleMessage result = null;
 113  
         
 114  0
         MuleEvent resultEvent = syncServerEndpoint.process(new DefaultMuleEvent(msg, syncServerEndpoint,
 115  
             new DefaultMuleSession(new MuleClientFlowConstruct(muleContext), muleContext)));
 116  0
         if (resultEvent != null)
 117  
         {
 118  0
             result = resultEvent.getMessage();
 119  
         }
 120  
 
 121  0
         if(result==null)
 122  
         {
 123  0
             throw new RemoteDispatcherException(ClientMessages.failedToDispatchActionNoResponseFromServer("request wire format", 5000));
 124  
         }
 125  
 
 126  
         ServerHandshake handshake;
 127  
         try
 128  
         {
 129  0
             ByteArrayInputStream in = new ByteArrayInputStream(result.getPayloadAsBytes());
 130  0
             handshake = (ServerHandshake) SerializationUtils.deserialize(in);
 131  
         }
 132  0
         catch (Exception e)
 133  
         {
 134  0
             throw new RemoteDispatcherException(ClientMessages.failedToDeserializeHandshakeFromServer(), e);
 135  0
         }
 136  
 
 137  
         try
 138  
         {
 139  0
             WireFormat wf = (WireFormat)ClassUtils.instanciateClass(handshake.getWireFormatClass(),
 140  
                     ClassUtils.NO_ARGS, getClass());
 141  
 
 142  0
             wf.setMuleContext(muleContext);
 143  0
             return wf;
 144  
         }
 145  0
         catch (Exception e)
 146  
         {
 147  0
             throw new UnsupportedWireFormatException(handshake.getWireFormatClass(), e);
 148  
         }
 149  
     }
 150  
 
 151  
     protected void setExecutor(Executor e)
 152  
     {
 153  0
         this.asyncExecutor = e;
 154  0
     }
 155  
 
 156  
     /**
 157  
      * Dispatcher an event asynchronously to a components on a remote Mule instance.
 158  
      * Users can endpoint a url to a remote Mule server in the constructor of a Mule
 159  
      * client, by default the default Mule server url tcp://localhost:60504 is used.
 160  
      *
 161  
      * @param component the name of the Mule components to dispatch to
 162  
      * @param payload the object that is the payload of the event
 163  
      * @param messageProperties any properties to be associated with the payload. as
 164  
      *            null
 165  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 166  
      *             transfromers cannot be found
 167  
      */
 168  
     public void dispatchToRemoteComponent(String component, Object payload, Map messageProperties)
 169  
         throws MuleException
 170  
     {
 171  0
         doToRemoteComponent(component, payload, messageProperties, false);
 172  0
     }
 173  
 
 174  
     /**
 175  
      * sends an event synchronously to a components on a remote Mule instance. Users
 176  
      * can endpoint a url to a remote Mule server in the constructor of a Mule
 177  
      * client, by default the default Mule server url tcp://localhost:60504 is used.
 178  
      *
 179  
      * @param component the name of the Mule components to send to
 180  
      * @param payload the object that is the payload of the event
 181  
      * @param messageProperties any properties to be associated with the payload. as
 182  
      *            null
 183  
      * @return the result message if any of the invocation
 184  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 185  
      *             transfromers cannot be found
 186  
      */
 187  
     public MuleMessage sendToRemoteComponent(String component, Object payload, Map messageProperties)
 188  
         throws MuleException
 189  
     {
 190  0
         return doToRemoteComponent(component, payload, messageProperties, true);
 191  
     }
 192  
 
 193  
     /**
 194  
      * sends an event to a components on a remote Mule instance, while making the
 195  
      * result of the event trigger available as a Future result that can be accessed
 196  
      * later by client code. Users can endpoint a url to a remote Mule server in the
 197  
      * constructor of a Mule client, by default the default Mule server url
 198  
      * tcp://localhost:60504 is used.
 199  
      *
 200  
      * @param component the name of the Mule components to send to
 201  
      * @param transformers a comma separated list of transformers to apply to the
 202  
      *            result message
 203  
      * @param payload the object that is the payload of the event
 204  
      * @param messageProperties any properties to be associated with the payload. as
 205  
      *            null
 206  
      * @return the result message if any of the invocation
 207  
      * @throws org.mule.api.MuleException if the dispatch fails or the components or
 208  
      *             transfromers cannot be found
 209  
      */
 210  
     public FutureMessageResult sendAsyncToRemoteComponent(final String component,
 211  
                                                           String transformers,
 212  
                                                           final Object payload,
 213  
                                                           final Map messageProperties) throws MuleException
 214  
     {
 215  0
         Callable callable = new Callable()
 216  0
         {
 217  
             public Object call() throws Exception
 218  
             {
 219  0
                 return doToRemoteComponent(component, payload, messageProperties, true);
 220  
             }
 221  
         };
 222  
 
 223  0
         FutureMessageResult result = new FutureMessageResult(callable, muleContext);
 224  
 
 225  0
         if (asyncExecutor != null)
 226  
         {
 227  0
             result.setExecutor(asyncExecutor);
 228  
         }
 229  
 
 230  0
         if (transformers != null)
 231  
         {
 232  0
             result.setTransformers(TransformerUtils.getTransformers(transformers, muleContext));
 233  
         }
 234  
 
 235  0
         result.execute();
 236  0
         return result;
 237  
     }
 238  
 
 239  
     public MuleMessage sendRemote(String endpoint, Object payload, Map messageProperties, int timeout)
 240  
         throws MuleException
 241  
     {
 242  0
         return doToRemote(endpoint, payload, messageProperties, true, timeout);
 243  
     }
 244  
 
 245  
     public MuleMessage sendRemote(String endpoint, Object payload, Map messageProperties) throws MuleException
 246  
     {
 247  0
         return doToRemote(endpoint, payload, messageProperties, true, 
 248  
             muleContext.getConfiguration().getDefaultResponseTimeout());
 249  
     }
 250  
 
 251  
     public void dispatchRemote(String endpoint, Object payload, Map messageProperties) throws MuleException
 252  
     {
 253  0
         doToRemote(endpoint, payload, messageProperties, false, -1);
 254  0
     }
 255  
 
 256  
     public FutureMessageResult sendAsyncRemote(final String endpoint,
 257  
                                                final Object payload,
 258  
                                                final Map messageProperties) throws MuleException
 259  
     {
 260  0
         Callable callable = new Callable()
 261  0
         {
 262  
             public Object call() throws Exception
 263  
             {
 264  0
                 return doToRemote(endpoint, payload, messageProperties, true, -1);
 265  
             }
 266  
         };
 267  
 
 268  0
         FutureMessageResult result = new FutureMessageResult(callable, muleContext);
 269  
 
 270  0
         if (asyncExecutor != null)
 271  
         {
 272  0
             result.setExecutor(asyncExecutor);
 273  
         }
 274  
 
 275  0
         result.execute();
 276  0
         return result;
 277  
     }
 278  
 
 279  
     public MuleMessage receiveRemote(String endpoint, int timeout) throws MuleException
 280  
     {
 281  0
         RemoteDispatcherNotification action = new RemoteDispatcherNotification(null, RemoteDispatcherNotification.ACTION_RECEIVE, endpoint);
 282  0
         action.setProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, "true");
 283  0
         if (timeout != MuleEvent.TIMEOUT_NOT_SET_VALUE)
 284  
         {
 285  0
             action.setProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, new Long(timeout));
 286  
         }
 287  0
         return dispatchAction(action, true, timeout);
 288  
     }
 289  
 
 290  
     public FutureMessageResult asyncReceiveRemote(final String endpoint, final int timeout)
 291  
         throws MuleException
 292  
     {
 293  0
         Callable callable = new Callable()
 294  0
         {
 295  
             public Object call() throws Exception
 296  
             {
 297  0
                 return receiveRemote(endpoint, timeout);
 298  
             }
 299  
         };
 300  
 
 301  0
         FutureMessageResult result = new FutureMessageResult(callable, muleContext);
 302  
 
 303  0
         if (asyncExecutor != null)
 304  
         {
 305  0
             result.setExecutor(asyncExecutor);
 306  
         }
 307  
 
 308  0
         result.execute();
 309  0
         return result;
 310  
     }
 311  
 
 312  
     protected MuleMessage doToRemoteComponent(String component,
 313  
                                              Object payload,
 314  
                                              Map messageProperties,
 315  
                                              boolean synchronous) throws MuleException
 316  
     {
 317  0
         MuleMessage message = new DefaultMuleMessage(payload, messageProperties, muleContext);
 318  0
         message.setOutboundProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, synchronous);
 319  0
         setCredentials(message);
 320  0
         RemoteDispatcherNotification action = new RemoteDispatcherNotification(message, RemoteDispatcherNotification.ACTION_INVOKE,
 321  
             "mule://" + component);
 322  0
         return dispatchAction(action, synchronous, 
 323  
             muleContext.getConfiguration().getDefaultResponseTimeout());
 324  
     }
 325  
 
 326  
     protected MuleMessage doToRemote(String endpoint,
 327  
                                     Object payload,
 328  
                                     Map messageProperties,
 329  
                                     boolean synchronous,
 330  
                                     int timeout) throws MuleException
 331  
     {
 332  0
         MuleMessage message = new DefaultMuleMessage(payload, messageProperties, muleContext);
 333  0
         message.setOutboundProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, String.valueOf(synchronous));
 334  0
         setCredentials(message);
 335  0
         RemoteDispatcherNotification action = new RemoteDispatcherNotification(message, (synchronous
 336  
                         ? RemoteDispatcherNotification.ACTION_SEND : RemoteDispatcherNotification.ACTION_DISPATCH), endpoint);
 337  
 
 338  0
         return dispatchAction(action, synchronous, timeout);
 339  
     }
 340  
 
 341  
     protected MuleMessage dispatchAction(RemoteDispatcherNotification action, boolean synchronous, int timeout)
 342  
         throws MuleException
 343  
     {
 344  
         OutboundEndpoint serverEndpoint;
 345  0
         if (synchronous)
 346  
         {
 347  0
             serverEndpoint = syncServerEndpoint;
 348  
         }
 349  
         else
 350  
         {
 351  0
             serverEndpoint = asyncServerEndpoint;
 352  
         }
 353  0
         MuleMessage serializeMessage = new DefaultMuleMessage(action, muleContext);
 354  
         
 355  0
         updateContext(serializeMessage, serverEndpoint, synchronous);
 356  
 
 357  0
         ByteArrayOutputStream out = new ByteArrayOutputStream();
 358  0
         wireFormat.write(out, serializeMessage, serverEndpoint.getEncoding());
 359  0
         byte[] payload = out.toByteArray();
 360  
 
 361  0
         MuleMessage message = action.getMessage();
 362  
 
 363  0
         if (message == null)
 364  
         {
 365  0
             message = new DefaultMuleMessage(payload, muleContext);
 366  
         }
 367  
         else
 368  
         {
 369  0
             message = new DefaultMuleMessage(payload, message, muleContext);
 370  
         }
 371  
 
 372  0
         message.addProperties(action.getProperties());
 373  0
         MuleSession session = new DefaultMuleSession(muleContext);
 374  
 
 375  0
         MuleEvent event = new DefaultMuleEvent(message, serverEndpoint, session);
 376  0
         event.setTimeout(timeout);
 377  0
         if (logger.isDebugEnabled())
 378  
         {
 379  0
             logger.debug("MuleClient sending remote call to: " + action.getResourceIdentifier() + ". At "
 380  
                          + serverEndpoint.toString() + " . Event is: " + event);
 381  
         }
 382  
 
 383  
 
 384  0
         MuleMessage result = null;
 385  
 
 386  
         try
 387  
         {
 388  0
             MuleEvent resultEvent = serverEndpoint.process(event);
 389  0
             if (resultEvent != null)
 390  
             {
 391  0
                 result = resultEvent.getMessage();
 392  
             }
 393  
 
 394  0
             if (result != null && result.getPayload() != null)
 395  
             {
 396  0
                 if (result.getPayload() instanceof NullPayload)
 397  
                 {
 398  0
                     return null;
 399  
                 }
 400  
                 
 401  
                 Object response;
 402  0
                 if (result.getPayload() instanceof InputStream)
 403  
                 {
 404  0
                     byte[] b = IOUtils.toByteArray((InputStream)result.getPayload());
 405  0
                     if(b.length==0) return null;
 406  0
                     ByteArrayInputStream in = new ByteArrayInputStream(b);
 407  0
                     response = wireFormat.read(in);
 408  0
                 }
 409  
                 else
 410  
                 {
 411  0
                     ByteArrayInputStream in = new ByteArrayInputStream(result.getPayloadAsBytes());
 412  0
                     response = wireFormat.read(in);
 413  
                 }
 414  
 
 415  0
                 if (response instanceof RemoteDispatcherNotification)
 416  
                 {
 417  0
                     response = ((RemoteDispatcherNotification)response).getMessage();
 418  
                 }
 419  0
                 return (MuleMessage)response;
 420  
             }
 421  
         }
 422  0
         catch (Exception e)
 423  
         {
 424  0
             throw new DispatchException(event, serverEndpoint, e);
 425  0
         }
 426  
 
 427  0
         if (logger.isDebugEnabled())
 428  
         {
 429  0
             logger.debug("Result of MuleClient remote call is: "
 430  
                          + (result == null ? "null" : result.getPayload()));
 431  
         }
 432  
 
 433  0
         return result;
 434  
     }
 435  
 
 436  
     public void dispose()
 437  
     {
 438  
         // nothing to do here
 439  0
     }
 440  
 
 441  
     protected void setCredentials(MuleMessage message)
 442  
     {
 443  0
         if (credentials != null)
 444  
         {
 445  0
             message.setOutboundProperty(MuleProperties.MULE_USER_PROPERTY, MuleCredentials.createHeader(
 446  
                     credentials.getUsername(), credentials.getPassword()));
 447  
         }
 448  0
     }
 449  
 
 450  
     public WireFormat getWireFormat()
 451  
     {
 452  0
         return wireFormat;
 453  
     }
 454  
 
 455  
     public void setWireFormat(WireFormat wireFormat)
 456  
     {
 457  0
         this.wireFormat = wireFormat;
 458  0
     }
 459  
 
 460  
     protected void updateContext(MuleMessage message, ImmutableEndpoint endpoint, boolean synchronous)
 461  
         throws MuleException
 462  
     {
 463  0
         RequestContext.setEvent(new DefaultMuleEvent(message, endpoint, new DefaultMuleSession(muleContext)));
 464  0
     }
 465  
 }