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