/********************************************************* begin of preamble
**
** Copyright (C) 2003-2010 Software- und Organisations-Service GmbH.
** All rights reserved.
**
** This file may be used under the terms of either the
**
** GNU General Public License version 2.0 (GPL)
**
** as published by the Free Software Foundation
** http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
** LICENSE.GPL included in the packaging of this file.
**
** or the
**
** Agreement for Purchase and Licensing
**
** as offered by Software- und Organisations-Service GmbH
** in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package com.sos.scheduler.engine.kernel.scripting;
/**
* \file ScriptInstance.java
* \brief general wrapper for the javax.script interface
*
* \class ScriptInstance
* \brief general wrapper for the javax.script interface
*
* \details
* This class provides a general mechanism to call script in different languages.
*
* \code
ScriptInstance module = new ScriptInstance("javascript");
module.setSourceCode("print('Hello ' + name + '\\n');");
module.addObject("nick", "name");
module.call();
\endcode
*
* \author ss
* \version 17.12.2010 12:04:34
* <div class="sos_branding">
* <p>(c) 2010 SOS GmbH - Berlin (<a style='color:silver' href='http://www.sos-berlin.com'>http://www.sos-berlin.com</a>)</p>
* </div>
*/
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.log4j.Logger;
public class ScriptInstance implements Script {
protected final Logger logger = Logger.getLogger(ScriptInstance.class.getPackage().getName());
private final String languageId;
private final ScriptEngine scriptengine;
private final Bindings scriptbindings;
private String sourceCode;
private ScriptFunction lastFunction = null;
public ScriptInstance(String scriptlanguage) {
languageId = scriptlanguage;
logger.debug("the language id is " + scriptlanguage);
ScriptEngineManager sm;
ScriptEngine se;
Bindings sb;
try {
sm = new ScriptEngineManager();
se = sm.getEngineByName(getLanguageId());
sb = se.getBindings(ScriptContext.ENGINE_SCOPE);
}
catch (Exception e) {
throw new UnsupportedScriptLanguageException(e, "Scriptlanguage " + getLanguageId() + " is not supported.", scriptlanguage);
}
scriptengine = se;
scriptbindings = sb;
}
public void setSourceCode(String sourcecode) {
this.sourceCode = sourcecode;
}
public void setSourceFile(String filename) {
this.sourceCode = readFile(filename);
}
private String readFile(String filename) {
StringBuffer sb = null;
FileReader fr = null;
logger.info("reading script from file " + filename);
try {
fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
String line;
sb = new StringBuffer();
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
}
catch (FileNotFoundException e) {
throw new InvalidScriptException(e, "the file " + filename + "does not exist.");
}
catch (IOException e) {
throw new InvalidScriptException(e, "error reading the file " + filename);
}
return (sb != null) ? sb.toString() : "";
}
public Object getObject(String name) {
return scriptbindings.get(name);
}
@Override
public void addObject(Object object, String name) {
String object_name = name;
logger.debug("addObject " + name + " to script");
scriptbindings.put(object_name, object);
}
public Object call() {
Object result = true;
String code = getSourcecode();
lastFunction = null;
if (code == null) {
throw new InvalidScriptException("scriptcode is missing - it seems neither setSourceCode nor SetSourceFile was called first.");
}
try {
result = scriptengine.eval(code, scriptbindings);
}
catch (ScriptException e) {
throw new InvalidScriptException(e, "error in script", code);
}
return result;
}
@Override
public Object call(String rawfunctionname, Object[] params) throws NoSuchMethodException {
Object result = true;
lastFunction = new ScriptFunction(rawfunctionname);
String functionname = lastFunction.getNativeFunctionName();
String code = this.getSourcecode();
if (code == null) {
throw new InvalidScriptException("scriptcode is missing - it seems neither setSourceCode nor SetSourceFile was called first.");
}
try {
logger.debug("executing function " + functionname);
scriptengine.eval(code, scriptbindings);
Invocable invocableEngine = (Invocable) scriptengine;
result = invocableEngine.invokeFunction(functionname, params);
}
catch (ScriptException e) {
throw new InvalidScriptException(e, "error in script", code);
}
return result;
}
@Override
public Object call(String rawfunctionname) throws NoSuchMethodException {
return call(rawfunctionname, new Object[] {});
}
@Override
public boolean callBoolean(String functionname, Object[] params) throws NoSuchMethodException {
Object obj = call(functionname, params);
if (obj instanceof Boolean) return (Boolean) obj;
if (obj instanceof Integer) return ((Integer)obj == 1) ? true : false;
throw new ClassCastException("the result of function " + functionname + " could not cast to " + Boolean.class.getName());
}
@Override
public boolean callBoolean(String functionname) throws NoSuchMethodException {
return callBoolean(functionname, new Object[]{});
}
@Override
public String callString(String functionname, Object[] params) throws NoSuchMethodException {
Object obj = call(functionname, params);
if (obj instanceof String) return (String) obj;
throw new ClassCastException("the result of function " + functionname + " could not cast to " + String.class.getName());
}
@Override
public String callString(String functionname) throws NoSuchMethodException {
return callString(functionname, new Object[]{});
}
@Override
public double callDouble(String functionname, Object[] params) throws NoSuchMethodException {
Object obj = call(functionname, params);
if (obj instanceof Double) return (Double) obj;
throw new ClassCastException("the result of function " + functionname + " could not cast to " + Double.class.getName());
}
@Override
public double callDouble(String functionname) throws NoSuchMethodException {
return callDouble(functionname, new Object[]{});
}
@Override
public String getLanguageId() {
return this.languageId;
}
@Override
public String getSourcecode() {
return sourceCode;
}
@Override
public ScriptFunction getLastFunction() {
return lastFunction;
}
}