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