Coverage Report - org.mule.module.scripting.component.Scriptable
 
Classes in this File Line Coverage Branch Coverage Complexity
Scriptable
0%
0/105
0%
0/30
2.208
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 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  
  * A JSR 223 Script service. Allows any JSR 223 compliant script engines such as
 45  
  * JavaScript, Groovy or Rhino to be embedded as Mule components.
 46  
  */
 47  
 public class Scriptable implements Initialisable, MuleContextAware
 48  
 {
 49  
     /** The actual body of the script */
 50  
     private String scriptText;
 51  
 
 52  
     /** A file from which the script will be loaded */
 53  
     private String scriptFile;
 54  
 
 55  
     /** Parameters to be made available to the script as variables */
 56  
     private Properties properties;
 57  
 
 58  
     /** The name of the JSR 223 scripting engine (e.g., "groovy") */
 59  
     private String scriptEngineName;
 60  
 
 61  
     /////////////////////////////////////////////////////////////////////////////
 62  
     // Internal variables, not exposed as properties
 63  
     /////////////////////////////////////////////////////////////////////////////
 64  
 
 65  
     /** A compiled version of the script, if the scripting engine supports it */
 66  
     private CompiledScript compiledScript;
 67  
 
 68  
     private ScriptEngine scriptEngine;
 69  
     private ScriptEngineManager scriptEngineManager;
 70  
 
 71  
     private MuleContext muleContext;
 72  
 
 73  0
     protected transient Log logger = LogFactory.getLog(getClass());
 74  
 
 75  
     public Scriptable()
 76  0
     {
 77  
         //For Spring
 78  0
     }
 79  
 
 80  
     public Scriptable(MuleContext muleContext)
 81  0
     {
 82  0
         this.muleContext = muleContext;
 83  0
     }
 84  
 
 85  
     public void setMuleContext(MuleContext context)
 86  
     {
 87  0
         this.muleContext = context;
 88  0
     }
 89  
 
 90  
     public void initialise() throws InitialisationException
 91  
     {
 92  0
         scriptEngineManager = new ScriptEngineManager();
 93  
 
 94  
         // Create scripting engine
 95  0
         if (scriptEngineName != null)
 96  
         {
 97  0
             scriptEngine = createScriptEngineByName(scriptEngineName);
 98  0
             if (scriptEngine == null)
 99  
             {
 100  0
                 throw new InitialisationException(MessageFactory.createStaticMessage("Scripting engine '" + scriptEngineName + "' not found.  Available engines are: " + listAvailableEngines()), this);
 101  
             }
 102  
         }
 103  
         // Determine scripting engine to use by file extension
 104  0
         else if (scriptFile != null)
 105  
         {
 106  0
             int i = scriptFile.lastIndexOf(".");
 107  0
             if (i > -1)
 108  
             {
 109  0
                 logger.info("Script Engine name not set. Guessing by file extension.");
 110  0
                 String ext = scriptFile.substring(i + 1);
 111  0
                 scriptEngine = createScriptEngineByExtension(ext);
 112  0
                 if (scriptEngine == null)
 113  
                 {
 114  0
                     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  0
                     setScriptEngineName(scriptEngine.getFactory().getEngineName());
 119  
                 }
 120  
             }
 121  
         }
 122  
 
 123  0
         Reader script = null;
 124  
         try
 125  
         {
 126  
             // Load script from variable
 127  0
             if (StringUtils.isNotBlank(scriptText))
 128  
             {
 129  0
                 script = new StringReader(scriptText);
 130  
             }
 131  
             // Load script from file
 132  0
             else if (scriptFile != null)
 133  
             {
 134  
                 InputStream is;
 135  
                 try
 136  
                 {
 137  0
                     is = IOUtils.getResourceAsStream(scriptFile, getClass());
 138  
                 }
 139  0
                 catch (IOException e)
 140  
                 {
 141  0
                     throw new InitialisationException(CoreMessages.cannotLoadFromClasspath(scriptFile), e, this);
 142  0
                 }
 143  0
                 if (is == null)
 144  
                 {
 145  0
                     throw new InitialisationException(CoreMessages.cannotLoadFromClasspath(scriptFile), this);
 146  
                 }
 147  0
                 script = new InputStreamReader(is);
 148  0
             }
 149  
             else
 150  
             {
 151  0
                 throw new InitialisationException(CoreMessages.propertiesNotSet("scriptText, scriptFile"), this);
 152  
             }
 153  
 
 154  
             // Pre-compile script if scripting engine supports compilation.
 155  0
             if (scriptEngine instanceof Compilable)
 156  
             {
 157  
                 try
 158  
                 {
 159  0
                     compiledScript = ((Compilable) scriptEngine).compile(script);
 160  
                 }
 161  0
                 catch (ScriptException e)
 162  
                 {
 163  0
                     throw new InitialisationException(e, this);
 164  0
                 }
 165  
             }
 166  
         }
 167  
         finally
 168  
         {
 169  0
             if (script != null)
 170  
             {
 171  
                 try
 172  
                 {
 173  0
                     script.close();
 174  
                 }
 175  0
                 catch (IOException e)
 176  
                 {
 177  0
                     throw new InitialisationException(e, this);
 178  0
                 }
 179  
             }
 180  
         }
 181  0
     }
 182  
 
 183  
     public void populateDefaultBindings(Bindings bindings)
 184  
     {
 185  0
         if (properties != null)
 186  
         {
 187  0
             bindings.putAll((Map) properties);
 188  
         }
 189  0
         bindings.put("log", logger);
 190  
         //A place holder for a returned result if the script doesn't return a result.
 191  
         //The script can overwrite this binding
 192  0
         bindings.put("result", NullPayload.getInstance());
 193  0
         bindings.put("muleContext", muleContext);
 194  0
         bindings.put("registry", muleContext.getRegistry());
 195  0
     }
 196  
 
 197  
     public void populateBindings(Bindings bindings, Object payload)
 198  
     {
 199  0
         populateDefaultBindings(bindings);
 200  0
         bindings.put("payload", payload);
 201  
         //For backward compatability. Usually used by the script transformer since
 202  
         //src maps with the argument passed into the transformer
 203  0
         bindings.put("src", payload);
 204  0
     }
 205  
 
 206  
     public void populateBindings(Bindings bindings, MuleMessage message)
 207  
     {
 208  0
         populateDefaultBindings(bindings);
 209  0
         if (message == null)
 210  
         {
 211  0
             message = new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
 212  
         }
 213  0
         bindings.put("message", message);
 214  
         //This will get overwritten if populateBindings(Bindings bindings, MuleEvent event) is called
 215  
         //and not this method directly.
 216  0
         bindings.put("payload", message.getPayload());
 217  
         //For backward compatability
 218  0
         bindings.put("src", message.getPayload());
 219  0
     }
 220  
 
 221  
     public void populateBindings(Bindings bindings, MuleEvent event)
 222  
     {
 223  0
         populateBindings(bindings, event.getMessage());
 224  0
         bindings.put("originalPayload", event.getMessage().getPayload());
 225  0
         bindings.put("payload", event.getMessage().getPayload());
 226  0
         bindings.put("eventContext", new DefaultMuleEventContext(event));
 227  0
         bindings.put("id", event.getId());
 228  0
         bindings.put("flowConstruct", event.getFlowConstruct());
 229  0
         if (event.getFlowConstruct() instanceof Service)
 230  
         {
 231  0
             bindings.put("service", event.getFlowConstruct());
 232  
         }
 233  0
     }
 234  
 
 235  
     public Object runScript(Bindings bindings) throws ScriptException
 236  
     {
 237  
         Object result;
 238  
         try
 239  
         {
 240  0
             if (compiledScript != null)
 241  
             {
 242  0
                 result = compiledScript.eval(bindings);
 243  
             }
 244  
             else
 245  
             {
 246  0
                 result = scriptEngine.eval(scriptText, bindings);
 247  
             }
 248  
 
 249  
             // The result of the script can be returned directly or it can
 250  
             // be set as the variable "result".
 251  0
             if (result == null)
 252  
             {
 253  0
                 result = bindings.get("result");
 254  
             }
 255  
         }
 256  0
         catch (ScriptException e)
 257  
         {
 258  
             // re-throw
 259  0
             throw e;
 260  
         }
 261  0
         catch (Exception ex)
 262  
         {
 263  0
             throw new ScriptException(ex);
 264  0
         }
 265  0
         return result;
 266  
     }
 267  
 
 268  
     protected ScriptEngine createScriptEngineByName(String name)
 269  
     {
 270  0
         return scriptEngineManager.getEngineByName(name);
 271  
     }
 272  
 
 273  
     protected ScriptEngine createScriptEngineByExtension(String ext)
 274  
     {
 275  0
         return scriptEngineManager.getEngineByExtension(ext);
 276  
     }
 277  
 
 278  
     protected String listAvailableEngines()
 279  
     {
 280  0
         return CollectionUtils.toString(scriptEngineManager.getEngineFactories(), false);
 281  
     }
 282  
 
 283  
     ////////////////////////////////////////////////////////////////////////////////
 284  
     // Getters and setters
 285  
     ////////////////////////////////////////////////////////////////////////////////
 286  
 
 287  
     public String getScriptText()
 288  
     {
 289  0
         return scriptText;
 290  
     }
 291  
 
 292  
     public void setScriptText(String scriptText)
 293  
     {
 294  0
         this.scriptText = scriptText;
 295  0
     }
 296  
 
 297  
     public String getScriptFile()
 298  
     {
 299  0
         return scriptFile;
 300  
     }
 301  
 
 302  
     public void setScriptFile(String scriptFile)
 303  
     {
 304  0
         this.scriptFile = scriptFile;
 305  0
     }
 306  
 
 307  
     public void setScriptEngineName(String scriptEngineName)
 308  
     {
 309  0
         this.scriptEngineName = scriptEngineName;
 310  0
     }
 311  
 
 312  
     public String getScriptEngineName()
 313  
     {
 314  0
         return scriptEngineName;
 315  
     }
 316  
 
 317  
     public Properties getProperties()
 318  
     {
 319  0
         return properties;
 320  
     }
 321  
 
 322  
     public void setProperties(Properties properties)
 323  
     {
 324  0
         this.properties = properties;
 325  0
     }
 326  
 
 327  
     public ScriptEngine getScriptEngine()
 328  
     {
 329  0
         return scriptEngine;
 330  
     }
 331  
 
 332  
     protected void setScriptEngine(ScriptEngine scriptEngine)
 333  
     {
 334  0
         this.scriptEngine = scriptEngine;
 335  0
     }
 336  
 
 337  
     protected CompiledScript getCompiledScript()
 338  
     {
 339  0
         return compiledScript;
 340  
     }
 341  
 
 342  
     protected void setCompiledScript(CompiledScript compiledScript)
 343  
     {
 344  0
         this.compiledScript = compiledScript;
 345  0
     }
 346  
 }