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