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