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 XPath xpath = getXPath(expression, payload);
118 if(namespaceManager!=null)
119 {
120 addNamespaces(namespaceManager, xpath);
121 }
122
123 List<?> result = xpath.selectNodes(payload);
124 result = extractResultsFromNodes(result);
125 if(result.size()==1)
126 {
127 return result.get(0);
128 }
129 else if(result.size()==0)
130 {
131 return null;
132 }
133 else
134 {
135 return result;
136 }
137 }
138 catch (Exception e)
139 {
140 throw new MuleRuntimeException(XmlMessages.failedToProcessXPath(expression), e);
141 }
142 }
143
144 protected void addNamespaces(NamespaceManager manager, XPath xpath)
145 {
146 for (Iterator<?> iterator = manager.getNamespaces().entrySet().iterator(); iterator.hasNext();)
147 {
148 Map.Entry<?, ?> entry = (Map.Entry<?, ?>)iterator.next();
149 try
150 {
151 xpath.addNamespace(entry.getKey().toString(), entry.getValue().toString());
152 }
153 catch (JaxenException e)
154 {
155 throw new ExpressionRuntimeException(XmlMessages.failedToRegisterNamespace(entry.getKey().toString(), entry.getValue().toString()));
156 }
157 }
158 }
159
160
161 public final void setName(String name)
162 {
163 throw new UnsupportedOperationException("setName");
164 }
165
166 protected XPath getXPath(String expression, Object object) throws JaxenException
167 {
168 XPath xpath = cache.get(expression + getClass().getName());
169 if(xpath==null)
170 {
171 xpath = createXPath(expression, object);
172 cache.put(expression + getClass().getName(), xpath);
173 }
174 return xpath;
175 }
176
177 protected abstract XPath createXPath(String expression, Object object) throws JaxenException;
178
179 protected List<?> extractResultsFromNodes(List<?> results)
180 {
181 if (results == null)
182 {
183 return null;
184 }
185 List<Object> newResults = new ArrayList<Object>(results.size());
186 for (Object o : results)
187 {
188 newResults.add(extractResultFromNode(o));
189 }
190 return newResults;
191 }
192
193
194
195
196
197
198 public void dispose()
199 {
200 cache.clear();
201 }
202
203 public NamespaceManager getNamespaceManager()
204 {
205 return namespaceManager;
206 }
207
208 public void setNamespaceManager(NamespaceManager namespaceManager)
209 {
210 this.namespaceManager = namespaceManager;
211 }
212
213 public MuleContext getMuleContext()
214 {
215 return muleContext;
216 }
217
218 protected abstract Object extractResultFromNode(Object result);
219 }