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.expression.ExpressionRuntimeException;
19 import org.mule.api.lifecycle.Disposable;
20 import org.mule.api.lifecycle.Initialisable;
21 import org.mule.api.lifecycle.InitialisationException;
22 import org.mule.api.registry.RegistrationException;
23 import org.mule.config.i18n.CoreMessages;
24 import org.mule.context.notification.MuleContextNotification;
25 import org.mule.module.xml.i18n.XmlMessages;
26 import org.mule.module.xml.util.NamespaceManager;
27
28 import java.util.ArrayList;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.WeakHashMap;
33
34 import org.dom4j.Document;
35 import org.jaxen.JaxenException;
36 import org.jaxen.XPath;
37 import org.mule.transformer.types.DataTypeFactory;
38
39
40
41
42
43 public abstract class AbstractXPathExpressionEvaluator implements ExpressionEvaluator, Initialisable, Disposable, MuleContextAware
44 {
45 private Map<String, XPath> cache = new WeakHashMap<String, XPath>(8);
46
47 private MuleContext muleContext;
48 private NamespaceManager namespaceManager;
49
50 public void setMuleContext(MuleContext context)
51 {
52 this.muleContext = context;
53
54 }
55
56 public void initialise() throws InitialisationException
57 {
58 try
59 {
60
61
62
63
64
65
66
67
68 this.muleContext.registerListener(new MuleContextNotificationListener<MuleContextNotification>(){
69
70 public void onNotification(MuleContextNotification notification)
71 {
72
73 if (MuleContextNotification.CONTEXT_STARTING == notification.getAction())
74 {
75 try
76 {
77 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
78 }
79 catch (RegistrationException e)
80 {
81 throw new RuntimeException(e);
82 }
83 }
84 }
85 });
86 }
87 catch (Throwable t)
88 {
89 throw new InitialisationException(t, this);
90 }
91 }
92
93 public void inject() throws Exception
94 {
95 try
96 {
97 namespaceManager = muleContext.getRegistry().lookupObject(NamespaceManager.class);
98 }
99 catch (RegistrationException e)
100 {
101 throw new ExpressionRuntimeException(CoreMessages.failedToLoad("NamespaceManager"), e);
102 }
103 }
104
105
106 public Object evaluate(String expression, MuleMessage message)
107 {
108 try
109 {
110 Object payload = message.getPayload();
111
112 if(payload instanceof String)
113 {
114 payload = message.getPayload(DataTypeFactory.create(Document.class));
115 }
116
117 List<?> result;
118
119
120
121
122 XPath xpath = getXPath(expression, payload);
123 synchronized (xpath)
124 {
125 result = xpath.selectNodes(payload);
126 }
127
128 result = extractResultsFromNodes(result);
129 if(result.size()==1)
130 {
131 return result.get(0);
132 }
133 else if(result.size()==0)
134 {
135 return null;
136 }
137 else
138 {
139 return result;
140 }
141 }
142 catch (Exception e)
143 {
144 throw new MuleRuntimeException(XmlMessages.failedToProcessXPath(expression), e);
145 }
146 }
147
148 protected void addNamespaces(NamespaceManager manager, XPath xpath)
149 {
150 for (Iterator<?> iterator = manager.getNamespaces().entrySet().iterator(); iterator.hasNext();)
151 {
152 Map.Entry<?, ?> entry = (Map.Entry<?, ?>)iterator.next();
153 try
154 {
155 xpath.addNamespace(entry.getKey().toString(), entry.getValue().toString());
156 }
157 catch (JaxenException e)
158 {
159 throw new ExpressionRuntimeException(XmlMessages.failedToRegisterNamespace(entry.getKey().toString(), entry.getValue().toString()));
160 }
161 }
162 }
163
164
165 public final void setName(String name)
166 {
167 throw new UnsupportedOperationException("setName");
168 }
169
170
171
172
173
174
175 protected XPath getXPath(String expression, Object object) throws JaxenException
176 {
177 XPath xpath = cache.get(expression + getClass().getName());
178 if(xpath==null)
179 {
180 xpath = createXPath(expression, object);
181 synchronized (xpath)
182 {
183 if(namespaceManager!=null)
184 {
185 addNamespaces(namespaceManager, xpath);
186 }
187 }
188 cache.put(expression + getClass().getName(), xpath);
189 }
190 return xpath;
191 }
192
193 protected abstract XPath createXPath(String expression, Object object) throws JaxenException;
194
195 protected List<?> extractResultsFromNodes(List<?> results)
196 {
197 if (results == null)
198 {
199 return null;
200 }
201 List<Object> newResults = new ArrayList<Object>(results.size());
202 for (Object o : results)
203 {
204 newResults.add(extractResultFromNode(o));
205 }
206 return newResults;
207 }
208
209
210
211
212
213
214 public void dispose()
215 {
216 cache.clear();
217 }
218
219 public NamespaceManager getNamespaceManager()
220 {
221 return namespaceManager;
222 }
223
224 public void setNamespaceManager(NamespaceManager namespaceManager)
225 {
226 this.namespaceManager = namespaceManager;
227 }
228
229 public MuleContext getMuleContext()
230 {
231 return muleContext;
232 }
233
234 protected abstract Object extractResultFromNode(Object result);
235 }