Coverage Report - org.mule.module.xml.routing.RoundRobinXmlSplitter
 
Classes in this File Line Coverage Branch Coverage Complexity
RoundRobinXmlSplitter
63%
40/63
41%
13/32
3.333
RoundRobinXmlSplitter$Counter
83%
5/6
50%
1/2
3.333
 
 1  
 /*
 2  
  * $Id: RoundRobinXmlSplitter.java 11567 2008-04-11 13:08:05Z 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.xml.routing;
 12  
 
 13  
 import org.mule.DefaultMuleMessage;
 14  
 import org.mule.api.MuleException;
 15  
 import org.mule.api.MuleMessage;
 16  
 import org.mule.api.MuleSession;
 17  
 import org.mule.api.endpoint.OutboundEndpoint;
 18  
 import org.mule.api.routing.CouldNotRouteOutboundMessageException;
 19  
 import org.mule.api.routing.RoutingException;
 20  
 
 21  
 import java.util.HashMap;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 
 26  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
 27  
 
 28  
 import org.dom4j.Document;
 29  
 
 30  
 /**
 31  
  * This router will split the Xml message into parts based on the xpath expression
 32  
  * and route each new event to the endpoints on the router, one after the other.
 33  
  */
 34  16
 public class RoundRobinXmlSplitter extends FilteringXmlMessageSplitter
 35  
 {
 36  
     // We have to do some additional checks if we're going to allow filters on the
 37  
     // round robin endpoints
 38  
     // So for performance lets turn it off by default
 39  16
     protected volatile boolean enableEndpointFiltering = false;
 40  16
     private boolean deterministic = true;
 41  2
     private static final AtomicInteger globalCounter = new AtomicInteger(0);
 42  
 
 43  
     public MuleMessage route(MuleMessage message, MuleSession session, boolean synchronous)
 44  
         throws RoutingException
 45  
     {
 46  
         try
 47  
         {
 48  20
             String correlationId = messageInfoMapping.getCorrelationId(message);
 49  20
             initialise(message);
 50  
 
 51  
             OutboundEndpoint endpoint;
 52  16
             MuleMessage result = null;
 53  
             Document part;
 54  16
             List parts = (List)nodesContext.get();
 55  16
             if (parts == null)
 56  
             {
 57  4
                 logger.error("There are no parts for current message. No events were routed: " + message);
 58  4
                 return null;
 59  
             }
 60  12
             int correlationSequence = 1;
 61  12
             Counter epCounter = new Counter();
 62  12
             Iterator iterator = parts.iterator();
 63  60
             while (iterator.hasNext())
 64  
             {
 65  48
                 part = (Document)iterator.next();
 66  
                 // Create the message
 67  48
                 Map theProperties = (Map)propertiesContext.get();
 68  48
                 message = new DefaultMuleMessage(part, new HashMap(theProperties));
 69  
 
 70  48
                 if (enableEndpointFiltering)
 71  
                 {
 72  0
                     endpoint = getEndpointForMessage(message);
 73  
                 }
 74  
                 else
 75  
                 {
 76  48
                     endpoint = (OutboundEndpoint) getEndpoints().get(epCounter.next());
 77  
                 }
 78  
 
 79  48
                 if (endpoint == null)
 80  
                 {
 81  0
                     logger.error("There was no matching endpoint for message part: " + part.asXML());
 82  
                 }
 83  
                 else
 84  
                 {
 85  
                     try
 86  
                     {
 87  48
                         if (enableCorrelation != ENABLE_CORRELATION_NEVER)
 88  
                         {
 89  48
                             boolean correlationSet = message.getCorrelationId() != null;
 90  48
                             if (!correlationSet && (enableCorrelation == ENABLE_CORRELATION_IF_NOT_SET))
 91  
                             {
 92  48
                                 message.setCorrelationId(correlationId);
 93  
                             }
 94  
 
 95  
                             // take correlation group size from the message
 96  
                             // properties, set by concrete message splitter
 97  
                             // implementations
 98  48
                             final int groupSize = message.getCorrelationGroupSize();
 99  48
                             message.setCorrelationGroupSize(groupSize);
 100  48
                             message.setCorrelationSequence(correlationSequence++);
 101  
                         }
 102  48
                         if (synchronous)
 103  
                         {
 104  24
                             result = send(session, message, endpoint);
 105  
                         }
 106  
                         else
 107  
                         {
 108  24
                             dispatch(session, message, endpoint);
 109  
                         }
 110  
                     }
 111  0
                     catch (MuleException e)
 112  
                     {
 113  0
                         throw new CouldNotRouteOutboundMessageException(message, endpoint, e);
 114  48
                     }
 115  
                 }
 116  48
             }
 117  12
             return result;
 118  
         }
 119  
         finally
 120  
         {
 121  16
             this.cleanup();
 122  
         }
 123  
     }
 124  
 
 125  
     /**
 126  
      * Retrieves a specific message part for the given endpoint. the message will
 127  
      * then be routed via the provider.
 128  
      * 
 129  
      * @param message the current message being processed
 130  
      * @return the message part to dispatch
 131  
      */
 132  
     protected OutboundEndpoint getEndpointForMessage(MuleMessage message)
 133  
     {
 134  0
         for (int i = 0; i < endpoints.size(); i++)
 135  
         {
 136  0
             OutboundEndpoint endpoint = (OutboundEndpoint)endpoints.get(i);
 137  
 
 138  
             try
 139  
             {
 140  0
                 if (endpoint.getFilter() == null || endpoint.getFilter().accept(message))
 141  
                 {
 142  0
                     if (logger.isDebugEnabled())
 143  
                     {
 144  0
                         logger.debug("Endpoint filter matched for node " + i + ". Routing message over: "
 145  
                                      + endpoint.getEndpointURI().toString());
 146  
                     }
 147  0
                     return endpoint;
 148  
                 }
 149  
                 else
 150  
                 {
 151  0
                     if (logger.isDebugEnabled())
 152  
                     {
 153  0
                         logger.debug("Endpoint filter did not match");
 154  
                     }
 155  
                 }
 156  
             }
 157  0
             catch (Exception e)
 158  
             {
 159  0
                 logger.error("Unable to create message for node at position " + i, e);
 160  0
                 return null;
 161  0
             }
 162  
         }
 163  
 
 164  0
         return null;
 165  
     }
 166  
 
 167  
     public void addEndpoint(OutboundEndpoint endpoint)
 168  
     {
 169  36
         if (endpoint.getFilter() != null && !enableEndpointFiltering)
 170  
         {
 171  0
             throw new IllegalStateException(
 172  
                 "Endpoints on the RoundRobin splitter router cannot have filters associated with them");
 173  
         }
 174  36
         super.addEndpoint(endpoint);
 175  36
     }
 176  
 
 177  
     public boolean isEnableEndpointFiltering()
 178  
     {
 179  0
         return enableEndpointFiltering;
 180  
     }
 181  
 
 182  
     public void setEnableEndpointFiltering(boolean enableEndpointFiltering)
 183  
     {
 184  0
         this.enableEndpointFiltering = enableEndpointFiltering;
 185  0
     }
 186  
 
 187  
     public boolean isDeterministic()
 188  
     {
 189  12
         return deterministic;
 190  
     }
 191  
 
 192  
     public void setDeterministic(boolean deterministic)
 193  
     {
 194  0
         this.deterministic = deterministic;
 195  0
     }
 196  
 
 197  16
     private class Counter
 198  
     {
 199  
 
 200  
         private AtomicInteger counter;
 201  
 
 202  
         public Counter()
 203  12
         {
 204  12
             if (isDeterministic())
 205  
             {
 206  12
                 counter = new AtomicInteger(0);
 207  
             }
 208  
             else
 209  
             {
 210  0
                 counter = globalCounter;
 211  
             }
 212  12
         }
 213  
 
 214  
         public int next()
 215  
         {
 216  48
             return counter.getAndIncrement() % getEndpoints().size();
 217  
         }
 218  
 
 219  
     }
 220  
 
 221  
 }