View Javadoc

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