1
2
3
4
5
6
7 package org.mule.module.scripting.component;
8
9 import org.mule.DefaultMuleEventContext;
10 import org.mule.DefaultMuleMessage;
11 import org.mule.api.MuleContext;
12 import org.mule.api.MuleEvent;
13 import org.mule.api.MuleMessage;
14 import org.mule.api.context.MuleContextAware;
15 import org.mule.api.lifecycle.Initialisable;
16 import org.mule.api.lifecycle.InitialisationException;
17 import org.mule.api.service.Service;
18 import org.mule.config.i18n.CoreMessages;
19 import org.mule.config.i18n.MessageFactory;
20 import org.mule.transport.NullPayload;
21 import org.mule.util.CollectionUtils;
22 import org.mule.util.IOUtils;
23 import org.mule.util.StringUtils;
24
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.Reader;
29 import java.io.StringReader;
30 import java.util.Map;
31 import java.util.Properties;
32
33 import javax.script.Bindings;
34 import javax.script.Compilable;
35 import javax.script.CompiledScript;
36 import javax.script.ScriptEngine;
37 import javax.script.ScriptEngineManager;
38 import javax.script.ScriptException;
39
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42
43
44
45
46
47 public class Scriptable implements Initialisable, MuleContextAware
48 {
49
50 private String scriptText;
51
52
53 private String scriptFile;
54
55
56 private Properties properties;
57
58
59 private String scriptEngineName;
60
61
62
63
64
65
66 private CompiledScript compiledScript;
67
68 private ScriptEngine scriptEngine;
69 private ScriptEngineManager scriptEngineManager;
70
71 private MuleContext muleContext;
72
73 protected transient Log logger = LogFactory.getLog(getClass());
74
75 public Scriptable()
76 {
77
78 }
79
80 public Scriptable(MuleContext muleContext)
81 {
82 this.muleContext = muleContext;
83 }
84
85 public void setMuleContext(MuleContext context)
86 {
87 this.muleContext = context;
88 }
89
90 public void initialise() throws InitialisationException
91 {
92 scriptEngineManager = new ScriptEngineManager();
93
94
95 if (scriptEngineName != null)
96 {
97 scriptEngine = createScriptEngineByName(scriptEngineName);
98 if (scriptEngine == null)
99 {
100 throw new InitialisationException(MessageFactory.createStaticMessage("Scripting engine '" + scriptEngineName + "' not found. Available engines are: " + listAvailableEngines()), this);
101 }
102 }
103
104 else if (scriptFile != null)
105 {
106 int i = scriptFile.lastIndexOf(".");
107 if (i > -1)
108 {
109 logger.info("Script Engine name not set. Guessing by file extension.");
110 String ext = scriptFile.substring(i + 1);
111 scriptEngine = createScriptEngineByExtension(ext);
112 if (scriptEngine == null)
113 {
114 throw new InitialisationException(MessageFactory.createStaticMessage("File extension '" + ext + "' does not map to a scripting engine. Available engines are: " + listAvailableEngines()), this);
115 }
116 else
117 {
118 setScriptEngineName(scriptEngine.getFactory().getEngineName());
119 }
120 }
121 }
122
123 Reader script = null;
124 try
125 {
126
127 if (StringUtils.isNotBlank(scriptText))
128 {
129 script = new StringReader(scriptText);
130 }
131
132 else if (scriptFile != null)
133 {
134 InputStream is;
135 try
136 {
137 is = IOUtils.getResourceAsStream(scriptFile, getClass());
138 }
139 catch (IOException e)
140 {
141 throw new InitialisationException(CoreMessages.cannotLoadFromClasspath(scriptFile), e, this);
142 }
143 if (is == null)
144 {
145 throw new InitialisationException(CoreMessages.cannotLoadFromClasspath(scriptFile), this);
146 }
147 script = new InputStreamReader(is);
148 }
149 else
150 {
151 throw new InitialisationException(CoreMessages.propertiesNotSet("scriptText, scriptFile"), this);
152 }
153
154
155 if (scriptEngine instanceof Compilable)
156 {
157 try
158 {
159 compiledScript = ((Compilable) scriptEngine).compile(script);
160 }
161 catch (ScriptException e)
162 {
163 throw new InitialisationException(e, this);
164 }
165 }
166 }
167 finally
168 {
169 if (script != null)
170 {
171 try
172 {
173 script.close();
174 }
175 catch (IOException e)
176 {
177 throw new InitialisationException(e, this);
178 }
179 }
180 }
181 }
182
183 public void populateDefaultBindings(Bindings bindings)
184 {
185 if (properties != null)
186 {
187 bindings.putAll((Map) properties);
188 }
189 bindings.put("log", logger);
190
191
192 bindings.put("result", NullPayload.getInstance());
193 bindings.put("muleContext", muleContext);
194 bindings.put("registry", muleContext.getRegistry());
195 }
196
197 public void populateBindings(Bindings bindings, Object payload)
198 {
199 populateDefaultBindings(bindings);
200 bindings.put("payload", payload);
201
202
203 bindings.put("src", payload);
204 }
205
206 public void populateBindings(Bindings bindings, MuleMessage message)
207 {
208 populateDefaultBindings(bindings);
209 if (message == null)
210 {
211 message = new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
212 }
213 bindings.put("message", message);
214
215
216 bindings.put("payload", message.getPayload());
217
218 bindings.put("src", message.getPayload());
219 }
220
221 public void populateBindings(Bindings bindings, MuleEvent event)
222 {
223 populateBindings(bindings, event.getMessage());
224 bindings.put("originalPayload", event.getMessage().getPayload());
225 bindings.put("payload", event.getMessage().getPayload());
226 bindings.put("eventContext", new DefaultMuleEventContext(event));
227 bindings.put("id", event.getId());
228 bindings.put("flowConstruct", event.getFlowConstruct());
229 if (event.getFlowConstruct() instanceof Service)
230 {
231 bindings.put("service", event.getFlowConstruct());
232 }
233 }
234
235 public Object runScript(Bindings bindings) throws ScriptException
236 {
237 Object result;
238 try
239 {
240 if (compiledScript != null)
241 {
242 result = compiledScript.eval(bindings);
243 }
244 else
245 {
246 result = scriptEngine.eval(scriptText, bindings);
247 }
248
249
250
251 if (result == null)
252 {
253 result = bindings.get("result");
254 }
255 }
256 catch (ScriptException e)
257 {
258
259 throw e;
260 }
261 catch (Exception ex)
262 {
263 throw new ScriptException(ex);
264 }
265 return result;
266 }
267
268 protected ScriptEngine createScriptEngineByName(String name)
269 {
270 return scriptEngineManager.getEngineByName(name);
271 }
272
273 protected ScriptEngine createScriptEngineByExtension(String ext)
274 {
275 return scriptEngineManager.getEngineByExtension(ext);
276 }
277
278 protected String listAvailableEngines()
279 {
280 return CollectionUtils.toString(scriptEngineManager.getEngineFactories(), false);
281 }
282
283
284
285
286
287 public String getScriptText()
288 {
289 return scriptText;
290 }
291
292 public void setScriptText(String scriptText)
293 {
294 this.scriptText = scriptText;
295 }
296
297 public String getScriptFile()
298 {
299 return scriptFile;
300 }
301
302 public void setScriptFile(String scriptFile)
303 {
304 this.scriptFile = scriptFile;
305 }
306
307 public void setScriptEngineName(String scriptEngineName)
308 {
309 this.scriptEngineName = scriptEngineName;
310 }
311
312 public String getScriptEngineName()
313 {
314 return scriptEngineName;
315 }
316
317 public Properties getProperties()
318 {
319 return properties;
320 }
321
322 public void setProperties(Properties properties)
323 {
324 this.properties = properties;
325 }
326
327 public ScriptEngine getScriptEngine()
328 {
329 return scriptEngine;
330 }
331
332 protected void setScriptEngine(ScriptEngine scriptEngine)
333 {
334 this.scriptEngine = scriptEngine;
335 }
336
337 protected CompiledScript getCompiledScript()
338 {
339 return compiledScript;
340 }
341
342 protected void setCompiledScript(CompiledScript compiledScript)
343 {
344 this.compiledScript = compiledScript;
345 }
346 }