1
2
3
4
5
6
7
8
9
10
11 package org.mule.routing.filters.xml;
12
13 import org.mule.umo.UMOFilter;
14 import org.mule.umo.UMOMessage;
15 import org.mule.util.StringMessageUtils;
16
17 import java.util.Iterator;
18 import java.util.Map;
19
20 import org.apache.commons.jxpath.AbstractFactory;
21 import org.apache.commons.jxpath.JXPathContext;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.dom4j.Document;
25 import org.dom4j.DocumentException;
26 import org.dom4j.DocumentHelper;
27 import org.dom4j.XPath;
28
29
30
31
32
33 public class JXPathFilter implements UMOFilter
34 {
35
36 protected transient Log logger = LogFactory.getLog(getClass());
37
38 private String expression;
39 private String expectedValue;
40 private Map namespaces = null;
41 private Map contextProperties = null;
42 private AbstractFactory factory;
43 private boolean lenient = true;
44
45 public JXPathFilter()
46 {
47 super();
48 }
49
50 public JXPathFilter(String expression)
51 {
52 this.expression = expression;
53 }
54
55 public JXPathFilter(String expression, String expectedValue)
56 {
57 this.expression = expression;
58 this.expectedValue = expectedValue;
59 }
60
61 public boolean accept(UMOMessage obj)
62 {
63 return accept(obj.getPayload());
64 }
65
66 private boolean accept(Object obj)
67 {
68 if (obj == null)
69 {
70 logger.warn("Applying JXPathFilter to null object.");
71 return false;
72 }
73 if (expression == null)
74 {
75 logger.warn("Expression for JXPathFilter is not set.");
76 return false;
77 }
78 if (expectedValue == null)
79 {
80
81 if (expression.endsWith("= null") || expression.endsWith("=null"))
82 {
83 expectedValue = "null";
84 expression = expression.substring(0, expression.lastIndexOf("="));
85 }
86 else
87 {
88 if (logger.isInfoEnabled())
89 {
90 logger.info("Expected value for JXPathFilter is not set, using 'true' by default");
91 }
92 expectedValue = Boolean.TRUE.toString();
93 }
94 }
95
96 Object xpathResult = null;
97 boolean accept = false;
98
99
100 if (obj instanceof Document)
101 {
102 if (namespaces == null)
103 {
104
105 xpathResult = ((Document)obj).valueOf(expression);
106 }
107 else
108 {
109
110 XPath xpath = DocumentHelper.createXPath(expression);
111 xpath.setNamespaceURIs(namespaces);
112 xpathResult = xpath.valueOf(obj);
113 }
114
115 }
116
117 else if (obj instanceof String)
118 {
119 try
120 {
121 return accept(DocumentHelper.parseText((String)obj));
122 }
123 catch (DocumentException e)
124 {
125 logger.warn("JXPathFilter unable to parse XML document: " + e.getMessage(), e);
126 if (logger.isDebugEnabled())
127 logger.debug("XML = " + StringMessageUtils.truncate((String)obj, 200, false));
128 return false;
129 }
130 }
131
132 else
133 {
134 if (logger.isDebugEnabled())
135 {
136 logger.debug("Passing object of type " + obj.getClass().getName() + " to JXPathContext");
137 }
138 JXPathContext context = JXPathContext.newContext(obj);
139 initialise(context);
140 xpathResult = context.getValue(expression);
141 }
142
143 if (logger.isDebugEnabled())
144 {
145 logger.debug("JXPathFilter Expression result = '" + xpathResult + "' - Expected value = '"
146 + expectedValue + "'");
147 }
148
149 if (xpathResult != null)
150 {
151 accept = xpathResult.toString().equals(expectedValue);
152 }
153 else
154 {
155
156 if (expectedValue.equals("null"))
157 {
158 accept = true;
159 }
160
161 else
162 {
163 logger.warn("JXPathFilter expression evaluates to null: " + expression);
164 }
165 }
166
167 if (logger.isDebugEnabled())
168 {
169 logger.debug("JXPathFilter accept object : " + accept);
170 }
171
172 return accept;
173 }
174
175
176
177
178
179
180
181 protected void initialise(JXPathContext context)
182 {
183 Map.Entry entry = null;
184 if (namespaces != null)
185 {
186 if (logger.isDebugEnabled())
187 {
188 logger.debug("Initializing JXPathContext with namespaces: " + namespaces);
189 }
190
191 for (Iterator iterator = namespaces.entrySet().iterator(); iterator.hasNext();)
192 {
193 entry = (Map.Entry)iterator.next();
194 context.registerNamespace(entry.getKey().toString(), entry.getValue().toString());
195 }
196 }
197
198 if (contextProperties != null)
199 {
200 if (logger.isDebugEnabled())
201 {
202 logger.debug("Initializing JXPathContext with properties: " + contextProperties);
203 }
204
205 for (Iterator iterator = contextProperties.entrySet().iterator(); iterator.hasNext();)
206 {
207 entry = (Map.Entry)iterator.next();
208 context.setValue(entry.getKey().toString(), entry.getValue());
209 }
210 }
211
212 if (factory != null)
213 {
214 context.setFactory(factory);
215 }
216
217 context.setLenient(lenient);
218 }
219
220
221
222
223 public String getExpression()
224 {
225 return expression;
226 }
227
228
229
230
231 public void setExpression(String expression)
232 {
233 this.expression = expression;
234 }
235
236
237
238
239 public String getExpectedValue()
240 {
241 return expectedValue;
242 }
243
244
245
246
247 public void setExpectedValue(String expectedValue)
248 {
249 this.expectedValue = expectedValue;
250 }
251
252
253
254
255
256 public String getValue()
257 {
258 return getExpectedValue();
259 }
260
261
262
263
264
265
266 public void setValue(String value)
267 {
268 setExpectedValue(value);
269 }
270
271 public Map getNamespaces()
272 {
273 return namespaces;
274 }
275
276 public void setNamespaces(Map namespaces)
277 {
278 this.namespaces = namespaces;
279 }
280
281 public Map getContextProperties()
282 {
283 return contextProperties;
284 }
285
286 public void setContextProperties(Map contextProperties)
287 {
288 this.contextProperties = contextProperties;
289 }
290
291 public AbstractFactory getFactory()
292 {
293 return factory;
294 }
295
296 public void setFactory(AbstractFactory factory)
297 {
298 this.factory = factory;
299 }
300
301 public boolean isLenient()
302 {
303 return lenient;
304 }
305
306 public void setLenient(boolean lenient)
307 {
308 this.lenient = lenient;
309 }
310 }