Coverage Report - org.mule.transport.AbstractMessageDispatcher
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractMessageDispatcher
19%
16/85
10%
4/40
4.7
AbstractMessageDispatcher$Worker
0%
0/16
0%
0/4
4.7
 
 1  
 /*
 2  
  * $Id: AbstractMessageDispatcher.java 12247 2008-07-07 21:25:01Z dfeist $
 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.transport;
 12  
 
 13  
 import org.mule.OptimizedRequestContext;
 14  
 import org.mule.RequestContext;
 15  
 import org.mule.api.MuleEvent;
 16  
 import org.mule.api.MuleException;
 17  
 import org.mule.api.MuleMessage;
 18  
 import org.mule.api.config.MuleProperties;
 19  
 import org.mule.api.endpoint.ImmutableEndpoint;
 20  
 import org.mule.api.endpoint.OutboundEndpoint;
 21  
 import org.mule.api.routing.ResponseRouterCollection;
 22  
 import org.mule.api.transaction.Transaction;
 23  
 import org.mule.api.transaction.TransactionException;
 24  
 import org.mule.api.transport.DispatchException;
 25  
 import org.mule.api.transport.MessageDispatcher;
 26  
 import org.mule.context.notification.EndpointMessageNotification;
 27  
 import org.mule.context.notification.SecurityNotification;
 28  
 import org.mule.transaction.TransactionCoordination;
 29  
 
 30  
 import javax.resource.spi.work.Work;
 31  
 import javax.resource.spi.work.WorkManager;
 32  
 
 33  
 /**
 34  
  * Provide a default dispatch (client) support for handling threads lifecycle and validation.
 35  
  */
 36  
 public abstract class AbstractMessageDispatcher extends AbstractConnectable implements MessageDispatcher
 37  
 {
 38  
 
 39  
     public AbstractMessageDispatcher(OutboundEndpoint endpoint)
 40  
     {
 41  2
         super(endpoint);
 42  2
     }
 43  
 
 44  
     /*
 45  
      * (non-Javadoc)
 46  
      * 
 47  
      * @see org.mule.api.transport.MessageDispatcher#dispatch(org.mule.api.MuleEvent)
 48  
      */
 49  
     public final void dispatch(MuleEvent event) throws DispatchException
 50  
     {
 51  0
         event.setSynchronous(false);
 52  0
         event.getMessage().setProperty(MuleProperties.MULE_ENDPOINT_PROPERTY,
 53  
             event.getEndpoint().getEndpointURI().toString());
 54  0
         event = OptimizedRequestContext.criticalSetEvent(event); // MULE-2112
 55  
 
 56  
         // Apply Security filter if one is set
 57  0
         ImmutableEndpoint endpoint = event.getEndpoint();
 58  0
         if (endpoint.getSecurityFilter() != null)
 59  
         {
 60  
             try
 61  
             {
 62  0
                 endpoint.getSecurityFilter().authenticate(event);
 63  
             }
 64  0
             catch (org.mule.api.security.SecurityException e)
 65  
             {
 66  
                 // TODO MULE-863: Do we need this warning?
 67  0
                 logger.warn("Outbound Request was made but was not authenticated: " + e.getMessage(), e);
 68  0
                 connector.fireNotification(new SecurityNotification(e,
 69  
                     SecurityNotification.SECURITY_AUTHENTICATION_FAILED));
 70  0
                 connector.handleException(e);
 71  0
                 return;
 72  
             }
 73  0
             catch (MuleException e)
 74  
             {
 75  0
                 disposeAndLogException();
 76  0
                 throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
 77  0
             }
 78  
         }
 79  
 
 80  
         try
 81  
         {
 82  0
             Transaction tx = TransactionCoordination.getInstance().getTransaction();
 83  0
             if (isDoThreading() && !event.isSynchronous() && tx == null)
 84  
             {
 85  0
                 connector.getDispatcherWorkManager().scheduleWork(new Worker(event), WorkManager.INDEFINITE, null, connector);
 86  
             }
 87  
             else
 88  
             {
 89  
                 // Make sure we are connected
 90  0
                 connectionStrategy.connect(this);
 91  0
                 doDispatch(event);
 92  0
                 if (connector.isEnableMessageEvents())
 93  
                 {
 94  0
                     String component = null;
 95  0
                     if (event.getService() != null)
 96  
                     {
 97  0
                         component = event.getService().getName();
 98  
                     }
 99  0
                     connector.fireNotification(new EndpointMessageNotification(event.getMessage(), event
 100  
                         .getEndpoint(), component, EndpointMessageNotification.MESSAGE_DISPATCHED));
 101  
                 }
 102  
             }
 103  
         }
 104  0
         catch (DispatchException e)
 105  
         {
 106  0
             disposeAndLogException();
 107  0
             throw e;
 108  
         }
 109  0
         catch (Exception e)
 110  
         {
 111  0
             disposeAndLogException();
 112  0
             throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
 113  0
         }
 114  0
     }
 115  
 
 116  
     public final MuleMessage send(MuleEvent event) throws DispatchException
 117  
     {
 118  
         // No point continuing if the service has rolledback the transaction
 119  8
         if (isTransactionRollback())
 120  
         {
 121  0
             return event.getMessage();
 122  
         }
 123  
 
 124  8
         event.setSynchronous(true);
 125  8
         event.getMessage().setProperty(MuleProperties.MULE_ENDPOINT_PROPERTY,
 126  
             event.getEndpoint().getEndpointURI().getUri().toString());
 127  8
         event = OptimizedRequestContext.unsafeSetEvent(event);
 128  
 
 129  
         // Apply Security filter if one is set
 130  8
         ImmutableEndpoint endpoint = event.getEndpoint();
 131  8
         if (endpoint.getSecurityFilter() != null)
 132  
         {
 133  
             try
 134  
             {
 135  0
                 endpoint.getSecurityFilter().authenticate(event);
 136  
             }
 137  0
             catch (org.mule.api.security.SecurityException e)
 138  
             {
 139  0
                 logger.warn("Outbound Request was made but was not authenticated: " + e.getMessage(), e);
 140  0
                 connector.fireNotification(new SecurityNotification(e,
 141  
                     SecurityNotification.SECURITY_AUTHENTICATION_FAILED));
 142  0
                 connector.handleException(e);
 143  0
                 return event.getMessage();
 144  
             }
 145  0
             catch (MuleException e)
 146  
             {
 147  0
                 disposeAndLogException();
 148  0
                 throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
 149  0
             }
 150  
         }
 151  
 
 152  
         try
 153  
         {
 154  
             // Make sure we are connected
 155  8
             connectionStrategy.connect(this);
 156  
 
 157  8
             MuleMessage result = doSend(event);
 158  8
             if (connector.isEnableMessageEvents())
 159  
             {
 160  0
                 String component = null;
 161  0
                 if (event.getService() != null)
 162  
                 {
 163  0
                     component = event.getService().getName();
 164  
                 }
 165  0
                 connector.fireNotification(new EndpointMessageNotification(event.getMessage(), event.getEndpoint(),
 166  
                     component, EndpointMessageNotification.MESSAGE_SENT));
 167  
             }
 168  
 
 169  
             //TODO: This chunk can be removed since there is no need to remove any properites since they are now scoped
 170  
             // Once a dispatcher has done its work we need to remove this property
 171  
             // so that it is not propagated to the next request
 172  
 //            if (result != null
 173  
 //                    && result.getPropertyNames().contains(MuleProperties.MULE_REMOTE_SYNC_PROPERTY))
 174  
             //{
 175  
 //                result = RequestContext.safeMessageCopy(result);
 176  
             //    result.removeProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY);
 177  
             //}
 178  8
             return result;
 179  
         }
 180  0
         catch (DispatchException e)
 181  
         {
 182  0
             disposeAndLogException();
 183  0
             throw e;
 184  
         }
 185  0
         catch (Exception e)
 186  
         {
 187  0
             disposeAndLogException();
 188  0
             throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
 189  
         }
 190  
     }
 191  
 
 192  
     /**
 193  
      * RemoteSync causes the message dispatch to wait for a response to an event on a
 194  
      * response channel after it sends the event. The following rules apply to
 195  
      * RemoteSync 1. The connector has to support remoteSync. Some transports do not
 196  
      * have the notion of a response channel 2. Check if the endpoint has been
 197  
      * configured for remoteSync 3. Check if the REMOTE_SYNC message header has been
 198  
      * set 4. Finally, if the current service has a response router configured,
 199  
      * that the router will handle the response channel event and we should not try
 200  
      * and receive a response in the Message dispatcher If remotesync should not be
 201  
      * used we must remove the REMOTE_SYNC header Note the MuleClient will
 202  
      * automatically set the REMOTE_SYNC header when client.send(..) is called so
 203  
      * that results are returned from remote invocations too.
 204  
      *
 205  
      * @param event the current event
 206  
      * @return true if a response channel should be used to get a resposne from the
 207  
      *         event dispatch.
 208  
      */
 209  
     protected boolean useRemoteSync(MuleEvent event)
 210  
     {
 211  0
         boolean remoteSync = false;
 212  0
         if (event.getEndpoint().getConnector().isRemoteSyncEnabled())
 213  
         {
 214  0
             remoteSync = event.getEndpoint().isRemoteSync()
 215  
                             || event.getMessage().getBooleanProperty(
 216  
                                 MuleProperties.MULE_REMOTE_SYNC_PROPERTY, false);
 217  0
             if (remoteSync)
 218  
             {
 219  
                 // service will be null for client calls
 220  0
                 if (event.getService() != null)
 221  
                 {
 222  0
                     ResponseRouterCollection responseRouters = event.getService().getResponseRouter();
 223  0
                     if (responseRouters != null && responseRouters.hasEndpoints())
 224  
                     {
 225  0
                         remoteSync = false;
 226  
                     }
 227  
                     else
 228  
                     {
 229  0
                         remoteSync = true;
 230  
                     }
 231  
                 }
 232  
             }
 233  
         }
 234  0
         if (!remoteSync)
 235  
         {
 236  0
             event.getMessage().removeProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY);
 237  
         }
 238  0
         return remoteSync;
 239  
     }
 240  
 
 241  
     private class Worker implements Work
 242  
     {
 243  
         private MuleEvent event;
 244  
 
 245  
         public Worker(MuleEvent event)
 246  0
         {
 247  0
             this.event = event;
 248  0
         }
 249  
 
 250  
         /*
 251  
          * (non-Javadoc)
 252  
          * 
 253  
          * @see java.lang.Runnable#run()
 254  
          */
 255  
         public void run()
 256  
         {
 257  
             try
 258  
             {
 259  0
                 event = RequestContext.setEvent(event);
 260  
                 // Make sure we are connected
 261  0
                 connectionStrategy.connect(AbstractMessageDispatcher.this);
 262  0
                 AbstractMessageDispatcher.this.doDispatch(event);
 263  
 
 264  0
                 if (connector.isEnableMessageEvents())
 265  
                 {
 266  0
                     String component = null;
 267  0
                     if (event.getService() != null)
 268  
                     {
 269  0
                         component = event.getService().getName();
 270  
                     }
 271  
 
 272  0
                     connector.fireNotification(new EndpointMessageNotification(event.getMessage(), event
 273  
                         .getEndpoint(), component, EndpointMessageNotification.MESSAGE_DISPATCHED));
 274  
                 }
 275  
             }
 276  0
             catch (Exception e)
 277  
             {
 278  0
                 AbstractMessageDispatcher.this.getConnector().handleException(e);
 279  0
             }
 280  0
         }
 281  
 
 282  
         public void release()
 283  
         {
 284  
             // nothing to do
 285  0
         }
 286  
     }
 287  
 
 288  
     /**
 289  
      * Checks to see if the current transaction has been rolled back
 290  
      * 
 291  
      * @return
 292  
      */
 293  
     protected boolean isTransactionRollback()
 294  
     {
 295  
         try
 296  
         {
 297  8
             Transaction tx = TransactionCoordination.getInstance().getTransaction();
 298  8
             if (tx != null && tx.isRollbackOnly())
 299  
             {
 300  0
                 return true;
 301  
             }
 302  
         }
 303  0
         catch (TransactionException e)
 304  
         {
 305  
             // TODO MULE-863: What should we really do?
 306  0
             logger.warn(e.getMessage());
 307  8
         }
 308  8
         return false;
 309  
     }
 310  
 
 311  
     protected abstract void doDispatch(MuleEvent event) throws Exception;
 312  
 
 313  
     protected abstract MuleMessage doSend(MuleEvent event) throws Exception;
 314  
                                              
 315  
 }