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 if (obj.getPayload() instanceof byte[])
64 {
65 try
66 {
67 return accept(obj.getPayloadAsString());
68 }
69 catch (Exception e)
70 {
71 logger.debug("JxPath filter rejected message because it could not convert from byte[] to String" + e.getMessage(), e);
72 return false;
73 }
74 }
75 return accept(obj.getPayload());
76 }
77
78 private boolean accept(Object obj)
79 {
80 if (obj == null)
81 {
82 logger.warn("Applying JXPathFilter to null object.");
83 return false;
84 }
85 if (expression == null)
86 {
87 logger.warn("Expression for JXPathFilter is not set.");
88 return false;
89 }
90 if (expectedValue == null)
91 {
92
93 if (expression.endsWith("= null") || expression.endsWith("=null"))
94 {
95 expectedValue = "null";
96 expression = expression.substring(0, expression.lastIndexOf("="));
97 }
98 else
99 {
100 if (logger.isInfoEnabled())
101 {
102 logger.info("Expected value for JXPathFilter is not set, using 'true' by default");
103 }
104 expectedValue = Boolean.TRUE.toString();
105 }
106 }
107
108 Object xpathResult = null;
109 boolean accept = false;
110
111
112 if (obj instanceof Document)
113 {
114 if (namespaces == null)
115 {
116
117 xpathResult = ((Document)obj).valueOf(expression);
118 }
119 else
120 {
121
122 XPath xpath = DocumentHelper.createXPath(expression);
123 xpath.setNamespaceURIs(namespaces);
124 xpathResult = xpath.valueOf(obj);
125 }
126
127 }
128
129 else if (obj instanceof String)
130 {
131 try
132 {
133 return accept(DocumentHelper.parseText((String)obj));
134 }
135 catch (DocumentException e)
136 {
137 logger.warn("JXPathFilter unable to parse XML document: " + e.getMessage(), e);
138 if (logger.isDebugEnabled())
139 logger.debug("XML = " + StringMessageUtils.truncate((String)obj, 200, false));
140 return false;
141 }
142 }
143
144 else
145 {
146 if (logger.isDebugEnabled())
147 {
148 logger.debug("Passing object of type " + obj.getClass().getName() + " to JXPathContext");
149 }
150 JXPathContext context = JXPathContext.newContext(obj);
151 initialise(context);
152 xpathResult = context.getValue(expression);
153 }
154
155 if (logger.isDebugEnabled())
156 {
157 logger.debug("JXPathFilter Expression result = '" + xpathResult + "' - Expected value = '"
158 + expectedValue + "'");
159 }
160
161 if (xpathResult != null)
162 {
163 accept = xpathResult.toString().equals(expectedValue);
164 }
165 else
166 {
167
168 if (expectedValue.equals("null"))
169 {
170 accept = true;
171 }
172
173 else
174 {
175 logger.warn("JXPathFilter expression evaluates to null: " + expression);
176 }
177 }
178
179 if (logger.isDebugEnabled())
180 {
181 logger.debug("JXPathFilter accept object : " + accept);
182 }
183
184 return accept;
185 }
186
187
188
189
190
191
192
193 protected void initialise(JXPathContext context)
194 {
195 Map.Entry entry = null;
196 if (namespaces != null)
197 {
198 if (logger.isDebugEnabled())
199 {
200 logger.debug("Initializing JXPathContext with namespaces: " + namespaces);
201 }
202
203 for (Iterator iterator = namespaces.entrySet().iterator(); iterator.hasNext();)
204 {
205 entry = (Map.Entry)iterator.next();
206 context.registerNamespace(entry.getKey().toString(), entry.getValue().toString());
207 }
208 }
209
210 if (contextProperties != null)
211 {
212 if (logger.isDebugEnabled())
213 {
214 logger.debug("Initializing JXPathContext with properties: " + contextProperties);
215 }
216
217 for (Iterator iterator = contextProperties.entrySet().iterator(); iterator.hasNext();)
218 {
219 entry = (Map.Entry)iterator.next();
220 context.setValue(entry.getKey().toString(), entry.getValue());
221 }
222 }
223
224 if (factory != null)
225 {
226 context.setFactory(factory);
227 }
228
229 context.setLenient(lenient);
230 }
231
232
233
234
235 public String getExpression()
236 {
237 return expression;
238 }
239
240
241
242
243 public void setExpression(String expression)
244 {
245 this.expression = expression;
246 }
247
248
249
250
251 public String getExpectedValue()
252 {
253 return expectedValue;
254 }
255
256
257
258
259 public void setExpectedValue(String expectedValue)
260 {
261 this.expectedValue = expectedValue;
262 }
263
264
265
266
267
268 public String getValue()
269 {
270 return getExpectedValue();
271 }
272
273
274
275
276
277
278 public void setValue(String value)
279 {
280 setExpectedValue(value);
281 }
282
283 public Map getNamespaces()
284 {
285 return namespaces;
286 }
287
288 public void setNamespaces(Map namespaces)
289 {
290 this.namespaces = namespaces;
291 }
292
293 public Map getContextProperties()
294 {
295 return contextProperties;
296 }
297
298 public void setContextProperties(Map contextProperties)
299 {
300 this.contextProperties = contextProperties;
301 }
302
303 public AbstractFactory getFactory()
304 {
305 return factory;
306 }
307
308 public void setFactory(AbstractFactory factory)
309 {
310 this.factory = factory;
311 }
312
313 public boolean isLenient()
314 {
315 return lenient;
316 }
317
318 public void setLenient(boolean lenient)
319 {
320 this.lenient = lenient;
321 }
322 }