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