1
2
3
4
5
6
7
8
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
32
33
34 public class RoundRobinXmlSplitter extends FilteringXmlMessageSplitter
35 {
36
37
38
39 protected volatile boolean enableEndpointFiltering = false;
40 private boolean deterministic = true;
41 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 String correlationId = messageInfoMapping.getCorrelationId(message);
49 initialise(message);
50
51 OutboundEndpoint endpoint;
52 MuleMessage result = null;
53 Document part;
54 List parts = (List)nodesContext.get();
55 if (parts == null)
56 {
57 logger.error("There are no parts for current message. No events were routed: " + message);
58 return null;
59 }
60 int correlationSequence = 1;
61 Counter epCounter = new Counter();
62 Iterator iterator = parts.iterator();
63 while (iterator.hasNext())
64 {
65 part = (Document)iterator.next();
66
67 Map theProperties = (Map)propertiesContext.get();
68 message = new DefaultMuleMessage(part, new HashMap(theProperties));
69
70 if (enableEndpointFiltering)
71 {
72 endpoint = getEndpointForMessage(message);
73 }
74 else
75 {
76 endpoint = (OutboundEndpoint) getEndpoints().get(epCounter.next());
77 }
78
79 if (endpoint == null)
80 {
81 logger.error("There was no matching endpoint for message part: " + part.asXML());
82 }
83 else
84 {
85 try
86 {
87 if (enableCorrelation != ENABLE_CORRELATION_NEVER)
88 {
89 boolean correlationSet = message.getCorrelationId() != null;
90 if (!correlationSet && (enableCorrelation == ENABLE_CORRELATION_IF_NOT_SET))
91 {
92 message.setCorrelationId(correlationId);
93 }
94
95
96
97
98 final int groupSize = message.getCorrelationGroupSize();
99 message.setCorrelationGroupSize(groupSize);
100 message.setCorrelationSequence(correlationSequence++);
101 }
102 if (synchronous)
103 {
104 result = send(session, message, endpoint);
105 }
106 else
107 {
108 dispatch(session, message, endpoint);
109 }
110 }
111 catch (MuleException e)
112 {
113 throw new CouldNotRouteOutboundMessageException(message, endpoint, e);
114 }
115 }
116 }
117 return result;
118 }
119 finally
120 {
121 this.cleanup();
122 }
123 }
124
125
126
127
128
129
130
131
132 protected OutboundEndpoint getEndpointForMessage(MuleMessage message)
133 {
134 for (int i = 0; i < endpoints.size(); i++)
135 {
136 OutboundEndpoint endpoint = (OutboundEndpoint)endpoints.get(i);
137
138 try
139 {
140 if (endpoint.getFilter() == null || endpoint.getFilter().accept(message))
141 {
142 if (logger.isDebugEnabled())
143 {
144 logger.debug("Endpoint filter matched for node " + i + ". Routing message over: "
145 + endpoint.getEndpointURI().toString());
146 }
147 return endpoint;
148 }
149 else
150 {
151 if (logger.isDebugEnabled())
152 {
153 logger.debug("Endpoint filter did not match");
154 }
155 }
156 }
157 catch (Exception e)
158 {
159 logger.error("Unable to create message for node at position " + i, e);
160 return null;
161 }
162 }
163
164 return null;
165 }
166
167 public void addEndpoint(OutboundEndpoint endpoint)
168 {
169 if (endpoint.getFilter() != null && !enableEndpointFiltering)
170 {
171 throw new IllegalStateException(
172 "Endpoints on the RoundRobin splitter router cannot have filters associated with them");
173 }
174 super.addEndpoint(endpoint);
175 }
176
177 public boolean isEnableEndpointFiltering()
178 {
179 return enableEndpointFiltering;
180 }
181
182 public void setEnableEndpointFiltering(boolean enableEndpointFiltering)
183 {
184 this.enableEndpointFiltering = enableEndpointFiltering;
185 }
186
187 public boolean isDeterministic()
188 {
189 return deterministic;
190 }
191
192 public void setDeterministic(boolean deterministic)
193 {
194 this.deterministic = deterministic;
195 }
196
197 private class Counter
198 {
199
200 private AtomicInteger counter;
201
202 public Counter()
203 {
204 if (isDeterministic())
205 {
206 counter = new AtomicInteger(0);
207 }
208 else
209 {
210 counter = globalCounter;
211 }
212 }
213
214 public int next()
215 {
216 return counter.getAndIncrement() % getEndpoints().size();
217 }
218
219 }
220
221 }