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