/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.collector.jmx.tracers.script; import org.apache.log4j.Logger; import javax.script.*; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.HashMap; import java.util.Map; /** * <p>Title: ScriptManagerWrapper</p> * <p>Description: Java Scripting Wrapper class to use scripting in Helios.</p> * <p>Company: Helios Development Group</p> * @author Sandeep Malhotra (smalhotra@heliosdev.org) */ public class ScriptBeanWrapper { /* javax.script.ScriptEngineManager */ protected ScriptEngineManager scriptManager = null; /* javax.script.ScriptEngine for the language requested by the user */ protected ScriptEngine engine = null; /* Map to store bindings that will be applied to ScriptEngineManger before acquring * an engine for a specific language */ protected Map<String,Object> scriptBindings = new HashMap<String,Object>(); /* ScriptBean object that holds information about scripts' language, source etc. */ protected ScriptBean scriptBean = null; /* Actual Interface object for the script. This Interface is used to call methods on the script.*/ protected Object scriptBeanInterface = null; /* Reference to log */ protected Logger log = null; /** * Default constructor that initializes log and ScriptEngineManager */ public ScriptBeanWrapper(){ log = Logger.getLogger(ScriptBeanWrapper.class); scriptManager = new ScriptEngineManager(); } /** * Constructor to instantiate wrapper using ScriptBean object * * @param scriptBean */ public ScriptBeanWrapper(ScriptBean scriptBean){ log = Logger.getLogger(ScriptBeanWrapper.class); scriptManager = new ScriptEngineManager(); this.scriptBean = scriptBean; } /** * @return the scriptBean */ public ScriptBean getScriptBean() { return scriptBean; } /** * @param scriptBean the scriptBean to set */ public void setScriptBean(ScriptBean scriptBean) { this.scriptBean = scriptBean; } /** * @return the scriptManager */ public ScriptEngineManager getScriptManager() { return scriptManager; } /** * @return the engine */ public ScriptEngine getEngine() { return engine; } /** * @return the bindings */ public Map<String,Object> getScriptBindings() { return scriptBindings; } /** * @param scriptBindings the bindings to set */ public void setScriptBindings(Map<String,Object> scriptBindings) { this.scriptBindings = scriptBindings; } /** * If you want to call script through an interface, you should call this method everytime to acquire that Interface. * Internally, a cached reference to this Interface will returned until the initial script is modified (file or inline) * * @return the scriptBeanInterface */ public Object getScriptBeanInterface() throws ScriptBeanException { if(scriptBeanInterface!=null && !scriptBean.isModified() ){ return scriptBeanInterface; } else { long start = System.currentTimeMillis(); initializeBean(); if(scriptBean.getScriptBeanInterfaceClazz()!=null){ try{ scriptBeanInterface = ((Invocable)engine).getInterface(scriptBean.getScriptBeanInterfaceClazz()); log.debug("ScriptBean for language [ " +scriptBean.getLanguage()+ " ] initialized in: " + (System.currentTimeMillis() - start) +" milliseconds." ); }catch(IllegalArgumentException iaex){ throw new ScriptBeanException("An error occured while getting Interface. Check if scriptBeanInterfaceClazz is a valid Interface.", iaex); } }else{ throw new ScriptBeanException("Required attribute scriptBeanInterfaceClazz for ScriptBean is missing."); } scriptBean.setModified(false); } return scriptBeanInterface; } /** * If you want to call script through an interface, you should call this method everytime to acquire that Interface. * Internally, a cached reference to this Interface will returned until the initial script is modified (file or inline) * * @return the scriptBeanInterface */ public Object invokeFunction(String functionName, Object...parameters) throws ScriptBeanException { long start = System.currentTimeMillis(); Object returnedObject = null; initializeBean(); try{ returnedObject = ((Invocable)engine).invokeFunction(functionName, parameters); log.debug("InvokeFuntion for language [ " +scriptBean.getLanguage()+ " ] completed in: " + (System.currentTimeMillis() - start) +" milliseconds." ); }catch(NoSuchMethodException nsmex){ throw new ScriptBeanException("An error occured while invoking a function on the script. Check whether number of parameters passed matches function signature in the script.", nsmex); }catch(ScriptException sex){ throw new ScriptBeanException("An error occured while invoking a function on the script.", sex); }catch(NullPointerException npex){ throw new ScriptBeanException("An error occured while invoking a function on the script. Check whether function name is null.", npex); } return returnedObject; } /** * Method that refreshes required references in case the script source if modified. * * @throws ScriptBeanException */ private void initializeBean() throws ScriptBeanException{ SimpleBindings binding = new SimpleBindings(scriptBindings); scriptManager.setBindings(binding); if(scriptBean.getLanguage()!=null){ engine = scriptManager.getEngineByName(scriptBean.getLanguage()); if(! (engine instanceof Invocable)){ throw new ScriptBeanException("The Scripting Engine for language [" +scriptBean.getLanguage()+ " ] does not support Invocable Interface." ); } if(scriptBean.getScriptFile()!=null){ try{ engine.eval (new BufferedReader (new FileReader (scriptBean.getScriptFile()))); }catch(ScriptException sex){ throw new ScriptBeanException("An exception occured while evaluating script from file [ " +scriptBean.getScriptFile()+ " ]", sex); }catch (FileNotFoundException fnfex){ throw new ScriptBeanException("Cannot file script file [ " +scriptBean.getScriptFile()+ " ]", fnfex); } } else if (scriptBean.getInlineScript()!=null){ try{ engine.eval(scriptBean.getInlineScript()); }catch(ScriptException sex){ throw new ScriptBeanException("An exception occured while evaluating inline script [ " +scriptBean.getInlineScript()+ " ]", sex); } } } else { throw new ScriptBeanException("Required attribute language is missing for ScriptBean."); } } // public void printBindings(){ // Iterator iterator = scriptBindings.entrySet().iterator(); // while(iterator.hasNext()){ // Map.Entry<String,Object> singleObj = (Map.Entry<String,Object>)iterator.next(); // log.info(singleObj.getKey() + " ** " + singleObj.getValue()); // } // } }