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