1
2
3
4
5
6
7
8
9
10
11 package org.mule.routing;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.OptimizedRequestContext;
15 import org.mule.api.AnnotatedObject;
16 import org.mule.api.MessagingException;
17 import org.mule.api.MuleEvent;
18 import org.mule.api.MuleException;
19 import org.mule.api.MuleMessage;
20 import org.mule.api.MuleSession;
21 import org.mule.api.lifecycle.Disposable;
22 import org.mule.api.lifecycle.Initialisable;
23 import org.mule.api.lifecycle.InitialisationException;
24 import org.mule.api.processor.MessageProcessor;
25 import org.mule.api.routing.MatchableMessageProcessor;
26 import org.mule.api.routing.MatchingRouter;
27 import org.mule.api.routing.TransformingMatchable;
28 import org.mule.config.i18n.CoreMessages;
29
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.CopyOnWriteArrayList;
36
37 import javax.xml.namespace.QName;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42
43
44
45
46
47 public class AbstractMatchingRouter implements MatchingRouter, AnnotatedObject
48 {
49
50
51
52 protected final transient Log logger = LogFactory.getLog(getClass());
53
54 @SuppressWarnings("unchecked")
55 protected List<MatchableMessageProcessor> matchableRoutes = new CopyOnWriteArrayList();
56 protected boolean matchAll = false;
57 protected MessageProcessor defaultRoute;
58 private final Map<QName, Object> annotations = new ConcurrentHashMap<QName, Object>();
59
60 public MuleEvent process(MuleEvent event) throws MuleException
61 {
62 MuleMessage message = event.getMessage();
63 MuleSession session = event.getSession();
64 MuleEvent result;
65 boolean matchfound = false;
66
67 for (Iterator iterator = matchableRoutes.iterator(); iterator.hasNext();)
68 {
69 MatchableMessageProcessor outboundRouter = (MatchableMessageProcessor) iterator.next();
70
71 final MuleEvent eventToRoute;
72
73 boolean copyEvent = false;
74
75
76
77 if (iterator.hasNext())
78 {
79 if (isMatchAll())
80 {
81 copyEvent = true;
82 }
83 else if (outboundRouter instanceof TransformingMatchable)
84 {
85 copyEvent = ((TransformingMatchable) outboundRouter).isTransformBeforeMatch();
86 }
87 }
88
89 if (copyEvent)
90 {
91 if (((DefaultMuleMessage) message).isConsumable())
92 {
93 throw new MessagingException(CoreMessages.cannotCopyStreamPayload(message.getPayload().getClass().getName()), event);
94 }
95 eventToRoute = OptimizedRequestContext.criticalSetEvent(event);
96 }
97 else
98 {
99 eventToRoute = event;
100 }
101
102 if (outboundRouter.isMatch(eventToRoute.getMessage()))
103 {
104 matchfound = true;
105 result = outboundRouter.process(event);
106 if (!isMatchAll())
107 {
108 return result;
109 }
110 }
111 }
112
113 if (!matchfound && defaultRoute != null)
114 {
115 if (logger.isDebugEnabled())
116 {
117 logger.debug("Message did not match any routers on: " + session.getFlowConstruct().getName()
118 + " invoking catch all strategy");
119 }
120 return processDefaultRoute(event);
121 }
122 else if (!matchfound)
123 {
124 logger.warn("Message did not match any routers on: "
125 + session.getFlowConstruct().getName()
126 + " and there is no catch all strategy configured on this router. Disposing message "
127 + message);
128 }
129 return event;
130 }
131
132 protected MuleEvent processDefaultRoute(MuleEvent event) throws MuleException
133 {
134 return defaultRoute.process(event);
135 }
136
137 public boolean isMatchAll()
138 {
139 return matchAll;
140 }
141
142 public void setMatchAll(boolean matchAll)
143 {
144 this.matchAll = matchAll;
145 }
146
147 public void addRoute(MatchableMessageProcessor matchable)
148 {
149 matchableRoutes.add(matchable);
150 }
151
152 public void removeRoute(MatchableMessageProcessor matchable)
153 {
154 matchableRoutes.remove(matchable);
155 }
156
157 public void setDefaultRoute(MessageProcessor defaultRoute)
158 {
159 this.defaultRoute = defaultRoute;
160 }
161
162 public List<MatchableMessageProcessor> getRoutes()
163 {
164 return matchableRoutes;
165 }
166
167 public MessageProcessor getDefaultRoute()
168 {
169 return defaultRoute;
170 }
171
172 public void initialise() throws InitialisationException
173 {
174 for (MatchableMessageProcessor route : matchableRoutes)
175 {
176 if (route instanceof Initialisable)
177 {
178 ((Initialisable) route).initialise();
179 }
180 }
181 }
182
183 public void dispose()
184 {
185 for (MatchableMessageProcessor route : matchableRoutes)
186 {
187 if (route instanceof Disposable)
188 {
189 ((Disposable) route).dispose();
190 }
191 }
192 }
193
194 public final Object getAnnotation(QName name)
195 {
196 return annotations.get(name);
197 }
198
199 public final Map<QName, Object> getAnnotations()
200 {
201 return Collections.unmodifiableMap(annotations);
202 }
203
204 public synchronized final void setAnnotations(Map<QName, Object> newAnnotations)
205 {
206 annotations.clear();
207 annotations.putAll(newAnnotations);
208 }
209 }