Coverage Report - org.mule.module.client.remoting.RemoteDispatcherComponent
 
Classes in this File Line Coverage Branch Coverage Complexity
RemoteDispatcherComponent
0%
0/109
0%
0/28
3.071
 
 1  
 /*
 2  
  * $Id: RemoteDispatcherComponent.java 11517 2008-03-31 21:34:19Z dirk.olmes $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.module.client.remoting;
 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.RequestContext;
 18  
 import org.mule.api.DefaultMuleException;
 19  
 import org.mule.api.MuleContext;
 20  
 import org.mule.api.MuleEvent;
 21  
 import org.mule.api.MuleEventContext;
 22  
 import org.mule.api.MuleException;
 23  
 import org.mule.api.MuleMessage;
 24  
 import org.mule.api.MuleSession;
 25  
 import org.mule.api.config.MuleProperties;
 26  
 import org.mule.api.endpoint.EndpointBuilder;
 27  
 import org.mule.api.endpoint.EndpointFactory;
 28  
 import org.mule.api.endpoint.ImmutableEndpoint;
 29  
 import org.mule.api.endpoint.InboundEndpoint;
 30  
 import org.mule.api.endpoint.OutboundEndpoint;
 31  
 import org.mule.api.lifecycle.Callable;
 32  
 import org.mule.api.lifecycle.Initialisable;
 33  
 import org.mule.api.lifecycle.InitialisationException;
 34  
 import org.mule.api.service.Service;
 35  
 import org.mule.api.transformer.TransformerException;
 36  
 import org.mule.api.transformer.wire.WireFormat;
 37  
 import org.mule.component.SimpleCallableJavaComponent;
 38  
 import org.mule.config.i18n.CoreMessages;
 39  
 import org.mule.endpoint.EndpointURIEndpointBuilder;
 40  
 import org.mule.message.DefaultExceptionPayload;
 41  
 import org.mule.model.seda.SedaService;
 42  
 import org.mule.module.client.remoting.notification.RemoteDispatcherNotification;
 43  
 import org.mule.object.PrototypeObjectFactory;
 44  
 import org.mule.transport.AbstractConnector;
 45  
 import org.mule.transport.NullPayload;
 46  
 import org.mule.util.MapUtils;
 47  
 
 48  
 import java.io.ByteArrayInputStream;
 49  
 import java.util.HashMap;
 50  
 import java.util.LinkedList;
 51  
 import java.util.List;
 52  
 import java.util.Map;
 53  
 
 54  
 import org.apache.commons.io.output.ByteArrayOutputStream;
 55  
 import org.apache.commons.logging.Log;
 56  
 import org.apache.commons.logging.LogFactory;
 57  
 
 58  
 /**
 59  
  * <code>RemoteDispatcherComponent</code> is a MuleManager interal server component
 60  
  * responsible for receiving remote requests and dispatching them locally. This
 61  
  * allows developer to tunnel requests through http ssl to a Mule instance behind a
 62  
  * firewall
 63  
  */
 64  
 
 65  0
 public class RemoteDispatcherComponent implements Callable, Initialisable
 66  
 {
 67  
     /**
 68  
      * logger used by this class
 69  
      */
 70  0
     protected static final Log logger = LogFactory.getLog(RemoteDispatcherComponent.class);
 71  
 
 72  
     public static final String MANAGER_COMPONENT_NAME = "_muleManagerComponent";
 73  
 
 74  
     /**
 75  
      * Use Serialization by default
 76  
      */
 77  
     protected WireFormat wireFormat;
 78  
 
 79  
     protected String encoding;
 80  
 
 81  0
     protected int synchronousEventTimeout = 5000;
 82  
 
 83  
     public void initialise() throws InitialisationException
 84  
     {
 85  0
         if (wireFormat == null)
 86  
         {
 87  0
             throw new InitialisationException(CoreMessages.objectIsNull("wireFormat"), this);
 88  
         }
 89  0
     }
 90  
 
 91  
     public Object onCall(MuleEventContext context) throws Exception
 92  
     {
 93  0
         if(context.transformMessageToString().equals(ServerHandshake.SERVER_HANDSHAKE_PROPERTY))
 94  
         {
 95  0
             return doHandshake(context);
 96  
         }
 97  
 
 98  
         Object result;
 99  0
         logger.debug("Message received by RemoteDispatcherComponent");
 100  0
         ByteArrayInputStream in = new ByteArrayInputStream(context.transformMessageToBytes());
 101  0
         RemoteDispatcherNotification action = (RemoteDispatcherNotification) ((MuleMessage)wireFormat.read(in)).getPayload();
 102  
 
 103  0
         if (RemoteDispatcherNotification.ACTION_INVOKE == action.getAction())
 104  
         {
 105  0
             result = invokeAction(action, context);
 106  
         }
 107  0
         else if (RemoteDispatcherNotification.ACTION_SEND == action.getAction() ||
 108  
                  RemoteDispatcherNotification.ACTION_DISPATCH == action.getAction())
 109  
         {
 110  0
             result = sendAction(action, context);
 111  
         }
 112  0
         else if (RemoteDispatcherNotification.ACTION_RECEIVE == action.getAction())
 113  
         {
 114  0
             result = receiveAction(action, context);
 115  
         }
 116  
         else
 117  
         {
 118  0
             result = handleException(null, new DefaultMuleException(
 119  
                 CoreMessages.eventTypeNotRecognised("RemoteDispatcherNotification:" + action.getAction())));
 120  
         }
 121  0
         return result;
 122  
     }
 123  
 
 124  
     protected ServerHandshake doHandshake(MuleEventContext context) throws TransformerException
 125  
     {
 126  0
         ServerHandshake handshake  = new ServerHandshake();
 127  0
         handshake.setWireFormatClass(wireFormat.getClass().getName());
 128  0
         return handshake;
 129  
     }
 130  
 
 131  
     protected Object invokeAction(RemoteDispatcherNotification action, MuleEventContext context) throws MuleException
 132  
     {
 133  
         String destComponent;
 134  0
         MuleMessage result = null;
 135  0
         String endpoint = action.getResourceIdentifier();
 136  0
         if (action.getResourceIdentifier().startsWith("mule:"))
 137  
         {
 138  0
             destComponent = endpoint.substring(endpoint.lastIndexOf("/") + 1);
 139  
         }
 140  
         else
 141  
         {
 142  0
             destComponent = endpoint;
 143  
         }
 144  
 
 145  0
         if (destComponent != null)
 146  
         {
 147  0
             MuleSession session = 
 148  
                 new DefaultMuleSession(context.getMuleContext().getRegistry().lookupService(destComponent), context.getMuleContext());
 149  
             // Need to do this otherise when the event is invoked the
 150  
             // transformer associated with the Mule Admin queue will be invoked, but
 151  
             // the message will not be of expected type
 152  0
             MuleContext managementContext = MuleServer.getMuleContext();
 153  0
             EndpointBuilder builder = new EndpointURIEndpointBuilder(RequestContext.getEvent().getEndpoint(), managementContext);
 154  
             // TODO - is this correct? it stops any other transformer from being set
 155  0
             builder.setTransformers(new LinkedList());
 156  0
             ImmutableEndpoint ep = managementContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(builder);
 157  0
             MuleEvent event = new DefaultMuleEvent(action.getMessage(), ep, context.getSession(), context.isSynchronous());
 158  0
             event = RequestContext.setEvent(event);
 159  
 
 160  0
             if (context.isSynchronous())
 161  
             {
 162  0
                 result = session.getService().sendEvent(event);
 163  0
                 ByteArrayOutputStream out = new ByteArrayOutputStream();
 164  0
                 wireFormat.write(out, result, getEncoding());
 165  0
                 return out.toByteArray();
 166  
             }
 167  
             else
 168  
             {
 169  0
                 session.getService().dispatchEvent(event);
 170  0
                 return null;
 171  
             }
 172  
         }
 173  
         else
 174  
         {
 175  0
             return handleException(result, new DefaultMuleException(
 176  
                 CoreMessages.couldNotDetermineDestinationComponentFromEndpoint(endpoint)));
 177  
         }
 178  
     }
 179  
 
 180  
     protected Object sendAction(RemoteDispatcherNotification action, MuleEventContext context) throws MuleException
 181  
     {
 182  0
         MuleMessage result = null;
 183  0
         OutboundEndpoint endpoint = null;
 184  0
         MuleContext managementContext = context.getMuleContext();
 185  
         try
 186  
         {
 187  0
             if (RemoteDispatcherNotification.ACTION_DISPATCH == action.getAction())
 188  
             {
 189  0
                 endpoint = managementContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(
 190  
                     action.getResourceIdentifier());
 191  0
                 context.dispatchEvent(action.getMessage(), endpoint);
 192  0
                 return null;
 193  
             }
 194  
             else
 195  
             {
 196  0
                 EndpointFactory endpointFactory = managementContext.getRegistry().lookupEndpointFactory();
 197  0
                 EndpointBuilder endpointBuilder = endpointFactory.getEndpointBuilder(action.getResourceIdentifier());
 198  0
                 endpointBuilder.setRemoteSync(true);
 199  0
                 endpoint = managementContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(endpointBuilder);
 200  0
                 result = context.sendEvent(action.getMessage(), endpoint);
 201  0
                 if (result == null)
 202  
                 {
 203  0
                     return null;
 204  
                 }
 205  
                 else
 206  
                 {
 207  0
                     ByteArrayOutputStream out = new ByteArrayOutputStream();
 208  0
                     wireFormat.write(out, result, getEncoding());
 209  0
                     return out.toByteArray();
 210  
                 }
 211  
             }
 212  
         }
 213  0
         catch (Exception e)
 214  
         {
 215  0
             return handleException(result, e);
 216  
         }
 217  
     }
 218  
 
 219  
     protected Object receiveAction(RemoteDispatcherNotification action, MuleEventContext context) throws MuleException
 220  
     {
 221  0
         MuleMessage result = null;
 222  
         try
 223  
         {
 224  0
             ImmutableEndpoint endpoint = context.getMuleContext()
 225  
                 .getRegistry()
 226  
                 .lookupEndpointFactory()
 227  
                 .getOutboundEndpoint(action.getResourceIdentifier());
 228  
 
 229  0
             long timeout = MapUtils.getLongValue(action.getProperties(),
 230  
                 MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, getSynchronousEventTimeout());
 231  
 
 232  0
             result = endpoint.getConnector().request(action.getResourceIdentifier(), timeout);
 233  0
             if (result != null)
 234  
             {
 235  
                 // See if there is a default transformer on the connector
 236  0
                 List transformers = ((AbstractConnector) endpoint.getConnector()).getDefaultInboundTransformers();
 237  0
                 if (transformers != null)
 238  
                 {
 239  0
                     result.applyTransformers(transformers);
 240  
                 }
 241  0
                 ByteArrayOutputStream out = new ByteArrayOutputStream();
 242  0
                 wireFormat.write(out, result, getEncoding());
 243  0
                 return out.toByteArray();
 244  
             }
 245  
             else
 246  
             {
 247  0
                 return null;
 248  
             }
 249  
         }
 250  0
         catch (Exception e)
 251  
         {
 252  0
             return handleException(result, e);
 253  
         }
 254  
 
 255  
     }
 256  
 
 257  
 
 258  
     public static final Service getSerivce(InboundEndpoint endpoint,
 259  
                                                     WireFormat wireFormat,
 260  
                                                     String encoding,
 261  
                                                     int eventTimeout,
 262  
                                                     MuleContext managementContext) throws MuleException
 263  
     {
 264  
         try
 265  
         {
 266  0
             Service service = new SedaService();
 267  0
             service.setName(MANAGER_COMPONENT_NAME);
 268  0
             service.setModel(managementContext.getRegistry().lookupSystemModel());
 269  
 
 270  0
             Map props = new HashMap();
 271  0
             props.put("wireFormat", wireFormat);
 272  0
             props.put("encoding", encoding);
 273  0
             props.put("synchronousEventTimeout", new Integer(eventTimeout));
 274  0
             service.setComponent(new SimpleCallableJavaComponent(new PrototypeObjectFactory(RemoteDispatcherComponent.class, props)));
 275  
 
 276  
 
 277  0
             service.setMuleContext(managementContext);
 278  0
             service.getInboundRouter().addEndpoint(endpoint);
 279  
 
 280  0
             return service;
 281  
         }
 282  0
         catch (Exception e)
 283  
         {
 284  0
             throw new InitialisationException(e, null);
 285  
         }
 286  
     }
 287  
 
 288  
     /**
 289  
      * Wraps an exception into a MuleMessage with an Exception payload and returns
 290  
      * the Xml representation of it
 291  
      * 
 292  
      * @param result the result of the invocation or null if the exception occurred
 293  
      *            before or during the invocation
 294  
      * @param e the Exception thrown
 295  
      * @return an Xml String message result
 296  
      */
 297  
     protected Object handleException(MuleMessage result, Throwable e)
 298  
     {
 299  0
         logger.error("Failed to process admin request: " + e.getMessage(), e);
 300  0
         if (result == null)
 301  
         {
 302  0
             result = new DefaultMuleMessage(NullPayload.getInstance(), (Map) null);
 303  
         }
 304  0
         result.setExceptionPayload(new DefaultExceptionPayload(e));
 305  
         try
 306  
         {
 307  0
             ByteArrayOutputStream out = new ByteArrayOutputStream();
 308  0
             wireFormat.write(out, result, getEncoding());
 309  0
             return out.toByteArray();
 310  
         }
 311  0
         catch (Exception e1)
 312  
         {
 313  
             // TODO MULE-863: Is this sufficient?
 314  
             // log the inner exception here since the earlier exception was logged earlier
 315  0
             logger.error("Failed to format message, using direct string (details at debug level): " + e1.getMessage());
 316  0
             logger.debug(e1.toString(), e1);
 317  0
             return e.getMessage();
 318  
         }
 319  
     }
 320  
 
 321  
     public WireFormat getWireFormat()
 322  
     {
 323  0
         return wireFormat;
 324  
     }
 325  
 
 326  
     public void setWireFormat(WireFormat wireFormat)
 327  
     {
 328  0
         this.wireFormat = wireFormat;
 329  0
     }
 330  
 
 331  
     public String getEncoding()
 332  
     {
 333  0
         return encoding;
 334  
     }
 335  
 
 336  
     public void setEncoding(String encoding)
 337  
     {
 338  0
         this.encoding = encoding;
 339  0
     }
 340  
 
 341  
     public int getSynchronousEventTimeout()
 342  
     {
 343  0
         return synchronousEventTimeout;
 344  
     }
 345  
 
 346  
     public void setSynchronousEventTimeout(int synchronousEventTimeout)
 347  
     {
 348  0
         this.synchronousEventTimeout = synchronousEventTimeout;
 349  0
     }
 350  
 }