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