1
2
3
4
5
6
7
8
9
10 package org.mule.module.xml.expression;
11
12 import org.mule.api.MuleContext;
13 import org.mule.api.MuleMessage;
14 import org.mule.api.MuleRuntimeException;
15 import org.mule.api.context.MuleContextAware;
16 import org.mule.api.context.notification.MuleContextNotificationListener;
17 import org.mule.api.expression.ExpressionEvaluator;
18 import org.mule.api.lifecycle.Disposable;
19 import org.mule.api.lifecycle.Initialisable;
20 import org.mule.api.lifecycle.InitialisationException;
21 import org.mule.api.registry.RegistrationException;
22 import org.mule.context.notification.MuleContextNotification;
23 import org.mule.module.xml.i18n.XmlMessages;
24 import org.mule.module.xml.stax.MapNamespaceContext;
25 import org.mule.module.xml.util.NamespaceManager;
26 import org.mule.transformer.types.DataTypeFactory;
27
28 import java.util.Map;
29 import java.util.WeakHashMap;
30
31 import javax.xml.namespace.QName;
32 import javax.xml.xpath.XPath;
33 import javax.xml.xpath.XPathConstants;
34 import javax.xml.xpath.XPathExpression;
35 import javax.xml.xpath.XPathExpressionException;
36 import javax.xml.xpath.XPathFactory;
37
38 import org.w3c.dom.Node;
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class JaxpXPathExpressionEvaluator implements ExpressionEvaluator, Initialisable, Disposable, MuleContextAware
53 {
54
55 private Map cache = new WeakHashMap(8);
56
57 private MuleContext muleContext;
58 private NamespaceManager namespaceManager;
59 private QName returnType = XPathConstants.STRING;
60
61 public JaxpXPathExpressionEvaluator()
62 {
63 super();
64 }
65
66 @Override
67 public String getName()
68 {
69 return "xpath2";
70 }
71
72 @Override
73 public void setMuleContext(MuleContext context)
74 {
75 this.muleContext = context;
76 }
77
78 @Override
79 public void initialise() throws InitialisationException
80 {
81 try
82 {
83
84
85
86
87
88
89
90
91
92
93
94 this.muleContext.registerListener(new MuleContextNotificationListener<MuleContextNotification>()
95 {
96 @Override
97 public void onNotification(MuleContextNotification notification)
98 {
99
100 if (MuleContextNotification.CONTEXT_STARTING == notification.getAction())
101 {
102 try
103 {
104 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
105 }
106 catch (RegistrationException e)
107 {
108 throw new RuntimeException(e);
109 }
110 }
111 }
112 });
113 }
114 catch (Throwable t)
115 {
116 throw new InitialisationException(t, this);
117 }
118 }
119
120
121
122
123 @Override
124 public Object evaluate(String expression, MuleMessage message)
125 {
126 QName retType = returnType;
127 if (expression.startsWith("["))
128 {
129 int x = expression.indexOf("]");
130 if (x == -1)
131 {
132 throw new IllegalArgumentException("Expression is malformed: " + expression);
133 }
134 String type = expression.substring(1, x);
135 expression = expression.substring(x + 1);
136 if (type.equalsIgnoreCase("boolean"))
137 {
138 retType = XPathConstants.BOOLEAN;
139 }
140 else if (type.equalsIgnoreCase("string"))
141 {
142 retType = XPathConstants.STRING;
143 }
144 else if (type.equalsIgnoreCase("node"))
145 {
146 retType = XPathConstants.NODE;
147 }
148 else if (type.equalsIgnoreCase("nodeset"))
149 {
150 retType = XPathConstants.NODESET;
151 }
152 else if (type.equalsIgnoreCase("number"))
153 {
154 retType = XPathConstants.NUMBER;
155 }
156 else
157 {
158 throw new IllegalArgumentException("Result type not recognised: " + type + ". Use either boolean, string, number, node or nodeset.");
159 }
160 }
161 try
162 {
163 Node payload = message.getPayload(DataTypeFactory.create(Node.class));
164
165 XPathExpression xpath = getXPath(expression);
166
167 return xpath.evaluate(payload, retType);
168 }
169 catch (Exception e)
170 {
171 throw new MuleRuntimeException(XmlMessages.failedToProcessXPath(expression), e);
172 }
173 }
174
175 @Override
176 public final void setName(String name)
177 {
178 throw new UnsupportedOperationException("setName");
179 }
180
181 protected XPathExpression getXPath(String expression) throws XPathExpressionException
182 {
183 XPathExpression xpath = (XPathExpression) cache.get(expression + getClass().getName());
184 if (xpath == null)
185 {
186 xpath = createXPath(expression);
187 cache.put(expression + getClass().getName(), xpath);
188 }
189 return xpath;
190 }
191
192 protected XPathExpression createXPath(String expression) throws XPathExpressionException
193 {
194 XPath xp = XPathFactory.newInstance().newXPath();
195 if (getNamespaceManager() != null)
196 {
197 xp.setNamespaceContext(new MapNamespaceContext(getNamespaceManager().getNamespaces()));
198 }
199 return xp.compile(expression);
200 }
201
202
203
204
205
206
207 @Override
208 public void dispose()
209 {
210 cache.clear();
211 }
212
213 public NamespaceManager getNamespaceManager()
214 {
215 return namespaceManager;
216 }
217
218 public void setNamespaceManager(NamespaceManager namespaceManager)
219 {
220 this.namespaceManager = namespaceManager;
221 }
222
223 public MuleContext getMuleContext()
224 {
225 return muleContext;
226 }
227
228 public QName getReturnType()
229 {
230 return returnType;
231 }
232
233 public void setReturnType(QName returnType)
234 {
235 this.returnType = returnType;
236 }
237 }
238