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