View Javadoc

1   /*
2    * $Id: RoundRobinXmlSplitter.java 7976 2007-08-21 14:26:13Z 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.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             nodesContext.set(null);
128             propertiesContext.set(null);
129         }
130     }
131 
132     /**
133      * Retrieves a specific message part for the given endpoint. the message will
134      * then be routed via the provider.
135      * 
136      * @param message the current message being processed
137      * @return the message part to dispatch
138      */
139     protected UMOEndpoint getEndpointForMessage(UMOMessage message)
140     {
141         for (int i = 0; i < endpoints.size(); i++)
142         {
143             UMOEndpoint endpoint = (UMOEndpoint)endpoints.get(i);
144 
145             try
146             {
147                 if (endpoint.getFilter() == null || endpoint.getFilter().accept(message))
148                 {
149                     if (logger.isDebugEnabled())
150                     {
151                         logger.debug("Endpoint filter matched for node " + i + ". Routing message over: "
152                                      + endpoint.getEndpointURI().toString());
153                     }
154                     return endpoint;
155                 }
156                 else
157                 {
158                     if (logger.isDebugEnabled())
159                     {
160                         logger.debug("Endpoint filter did not match");
161                     }
162                 }
163             }
164             catch (Exception e)
165             {
166                 logger.error("Unable to create message for node at position " + i, e);
167                 return null;
168             }
169         }
170 
171         return null;
172     }
173 
174     public void addEndpoint(UMOEndpoint endpoint)
175     {
176         if (endpoint.getFilter() != null && !enableEndpointFiltering)
177         {
178             throw new IllegalStateException(
179                 "Endpoints on the RoundRobin splitter router cannot have filters associated with them");
180         }
181         super.addEndpoint(endpoint);
182     }
183 
184     public boolean isEnableEndpointFiltering()
185     {
186         return enableEndpointFiltering;
187     }
188 
189     public void setEnableEndpointFiltering(boolean enableEndpointFiltering)
190     {
191         this.enableEndpointFiltering = enableEndpointFiltering;
192     }
193 }