1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.sxc;
12
13 import org.mule.api.DefaultMuleException;
14 import org.mule.api.MuleContext;
15 import org.mule.api.MuleException;
16 import org.mule.api.MuleMessage;
17 import org.mule.api.expression.ExpressionRuntimeException;
18 import org.mule.api.registry.RegistrationException;
19 import org.mule.api.routing.filter.Filter;
20 import org.mule.api.transformer.TransformerException;
21 import org.mule.config.i18n.CoreMessages;
22 import org.mule.module.xml.stax.ReversibleXMLStreamReader;
23 import org.mule.module.xml.transformer.XmlToXMLStreamReader;
24 import org.mule.module.xml.util.NamespaceManager;
25 import org.mule.routing.filters.logic.AndFilter;
26 import org.mule.routing.filters.logic.NotFilter;
27 import org.mule.routing.filters.logic.OrFilter;
28 import org.mule.routing.outbound.FilteringOutboundRouter;
29
30 import com.envoisolutions.sxc.xpath.XPathBuilder;
31 import com.envoisolutions.sxc.xpath.XPathEvaluator;
32
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.Map;
36
37
38
39
40
41
42 public class SxcFilteringOutboundRouter extends FilteringOutboundRouter
43 {
44 private final static ThreadLocal<MuleMessage> messages = new ThreadLocal<MuleMessage>();
45 private final static XmlToXMLStreamReader transformer = new XmlToXMLStreamReader();
46
47 static
48 {
49 transformer.setReversible(true);
50 }
51
52 private Map<String, String> namespaces;
53 private XPathEvaluator evaluator;
54
55 private XPathBuilder builder;
56
57 private NamespaceManager namespaceManager;
58
59 @Override
60 public void setMuleContext(MuleContext context)
61 {
62 this.muleContext = context;
63 try
64 {
65 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
66 }
67 catch (RegistrationException e)
68 {
69 throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
70 }
71
72 if (namespaceManager != null)
73 {
74 if (namespaces == null)
75 {
76 namespaces = new HashMap(namespaceManager.getNamespaces());
77 }
78 else
79 {
80 namespaces.putAll(namespaceManager.getNamespaces());
81 }
82 }
83 }
84
85 @Override
86 public void setFilter(Filter filter)
87 {
88 super.setFilter(filter);
89 }
90
91 protected void addEventHandlers(XPathBuilder xpathBuilder, Filter filter)
92 {
93 if (filter instanceof SxcFilter)
94 {
95 SxcFilter sxcFilter = ((SxcFilter) filter);
96 sxcFilter.addEventHandler(this, xpathBuilder);
97 }
98 else if (filter instanceof AndFilter)
99 {
100 AndFilter f = (AndFilter) filter;
101
102 for (Iterator<?> itr = f.getFilters().iterator(); itr.hasNext();)
103 {
104 addEventHandlers(xpathBuilder, (Filter) itr.next());
105 }
106 }
107 else if (filter instanceof OrFilter)
108 {
109 OrFilter f = (OrFilter) filter;
110
111 for (Iterator<?> itr = f.getFilters().iterator(); itr.hasNext();)
112 {
113 addEventHandlers(xpathBuilder, (Filter) itr.next());
114 }
115 }
116 else if (filter instanceof NotFilter)
117 {
118 NotFilter f = (NotFilter) filter;
119
120 addEventHandlers(xpathBuilder, f.getFilter());
121 }
122 else
123 {
124 logger.warn("Filter type " + filter.getClass().toString()
125 + " is not recognized by the SXC router. If it contains child "
126 + "SXC filters it will not work correctly.");
127 }
128 }
129
130 protected void initialize() throws Exception
131 {
132 if (evaluator == null)
133 {
134 doInitialize();
135 }
136 }
137
138 private synchronized void doInitialize()
139 {
140 if (evaluator == null)
141 {
142 builder = new XPathBuilder();
143 builder.setNamespaceContext(namespaces);
144 addEventHandlers(builder, getFilter());
145
146 evaluator = builder.compile();
147 }
148 }
149
150 @Override
151 public boolean isMatch(MuleMessage message) throws MuleException
152 {
153 ReversibleXMLStreamReader reader = null;
154 try
155 {
156 initialize();
157 messages.set(message);
158
159 reader = getXMLStreamReader(message);
160 reader.setTracking(true);
161 evaluator.evaluate(reader);
162 }
163 catch (StopProcessingException e)
164 {
165
166 }
167 catch (Exception e)
168 {
169 throw new DefaultMuleException(e);
170 }
171 finally
172 {
173 messages.set(null);
174
175 if (reader != null)
176 {
177 reader.setTracking(false);
178 reader.reset();
179 }
180 }
181
182 try
183 {
184 return testMatch(message);
185 }
186 catch (UndefinedMatchException m)
187 {
188 return false;
189 }
190 }
191
192 public boolean testMatch(MuleMessage message) throws MuleException
193 {
194 return super.isMatch(message);
195 }
196
197
198
199
200
201
202
203 protected ReversibleXMLStreamReader getXMLStreamReader(MuleMessage message) throws TransformerException
204 {
205 ReversibleXMLStreamReader r = (ReversibleXMLStreamReader) transformer.transform(message);
206
207 if (r != message.getPayload())
208 {
209 message.setPayload(r);
210 }
211 return r;
212 }
213
214 public Map<String, String> getNamespaces()
215 {
216 return namespaces;
217 }
218
219 public void setNamespaces(Map<String, String> namespaces)
220 {
221 this.namespaces = namespaces;
222 }
223
224 public static MuleMessage getCurrentMessage()
225 {
226 return messages.get();
227 }
228 }