Initial pass at JSR 223 pluggable scripting engne.

This commit is contained in:
James Roseborough
2008-04-24 08:22:34 +00:00
parent 2e17f19628
commit b79f8ba714
4 changed files with 424 additions and 0 deletions

View File

@@ -0,0 +1 @@
org.luaj.script.LuaScriptEngineFactory

View File

@@ -0,0 +1,234 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.script;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.LineNumberInputStream;
import java.io.Reader;
import java.io.StringWriter;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
import org.luaj.compiler.LuaC;
import org.luaj.platform.J2sePlatform;
import org.luaj.vm.LClosure;
import org.luaj.vm.LDouble;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LString;
import org.luaj.vm.LTable;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
/**
*
* @author jim_roseborough
*/
public class LuaScriptEngine extends LFunction implements ScriptEngine {
private static final String __ENGINE_VERSION__ = "V0.28";
private static final String __NAME__ = "Luaj";
private static final String __SHORT_NAME__ = "Luaj";
private static final String __LANGUAGE__ = "lua";
private static final String __LANGUAGE_VERSION__ = "5.1";
private static final String __ARGV__ = "arg";
private static final String __FILENAME__ = "?";
static {
Platform.setInstance(new J2sePlatform());
LuaC.install();
}
private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory();
private ScriptContext defaultContext;
private final LuaState luaState;
public LuaScriptEngine() {
setContext(new SimpleScriptContext());
// set special values
put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
put(LANGUAGE, __LANGUAGE__);
put(ENGINE, __NAME__);
put(ENGINE_VERSION, __ENGINE_VERSION__);
put(ARGV, __ARGV__);
put(FILENAME, __FILENAME__);
put(NAME, __SHORT_NAME__);
put("THREADING", null);
// set lua state
luaState = Platform.getInstance().newLuaState();
// connect up to bindings
LTable metatable = new LTable();
metatable.put("__index", this);
metatable.put("__newindex", this);
luaState._G.luaSetMetatable(metatable);
}
public Object eval(String script) throws ScriptException {
return eval(script, getContext());
}
public Object eval(String script, ScriptContext context) throws ScriptException {
try {
byte[] bytes = script.getBytes("UTF-8");
ByteArrayInputStream bais = new ByteArrayInputStream( bytes );
LineNumberInputStream is = new LineNumberInputStream( bais );
try {
LPrototype p = LoadState.undump(luaState, is, "script");
LClosure c = new LClosure( p, luaState._G );
luaState.doCall( c, new LValue[0] );
return luaState.topointer(1);
} catch ( LuaErrorException lee ) {
throw new ScriptException(lee.getMessage(), "script", is.getLineNumber() );
} finally {
is.close();
}
} catch ( Throwable t ) {
throw new ScriptException("eval threw "+t.toString());
}
}
public Object eval(String script, Bindings bindings) throws ScriptException {
Bindings current = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
Object result = eval(script);
getContext().setBindings(current, ScriptContext.ENGINE_SCOPE);
return result;
}
public Object eval(Reader reader) throws ScriptException {
return eval(getScriptFromReader(reader));
}
public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
return eval(getScriptFromReader(reader), scriptContext);
}
public Object eval(Reader reader, Bindings bindings) throws ScriptException {
return eval(getScriptFromReader(reader), bindings);
}
public void put(String key, Object value) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
if ( value == null )
b.remove(key);
else {
if ( value instanceof Number ) {
double d = ((Number)value).doubleValue();
int id = (int) d;
value = (d==id? LInteger.valueOf(id): new LDouble(d));
} else if ( value instanceof String ) {
value = LString.valueOf(value.toString());
} else {
value = new LUserData(value);
}
b.put(key,value);
}
}
public Object get(String key) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
Object o = b.get(key);
if ( o == null )
return null;
LValue v = (LValue)o;
switch ( v.luaGetType() ) {
case Lua.LUA_TSTRING: return v.toJavaString();
case Lua.LUA_TUSERDATA: return v.toJavaInstance();
case Lua.LUA_TNUMBER: return v.isInteger()? (Object) v.toJavaBoxedInteger(): (Object) v.toJavaBoxedDouble();
}
return o;
}
public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
String k = key.toJavaString();
Object v = (val.isNil()? null: val);
b.put(k,v);
}
public void luaGetTable(LuaState vm, LValue table, LValue key) {
Bindings b = getBindings(ScriptContext.ENGINE_SCOPE);
String k = key.toJavaString();
Object v = b.get(k);
vm.pushlvalue((LValue)v);
}
public Bindings getBindings(int scope) {
return getContext().getBindings(scope);
}
public void setBindings(Bindings bindings, int scope) {
getContext().setBindings(bindings, scope);
}
public Bindings createBindings() {
return new SimpleBindings();
}
public ScriptContext getContext() {
return defaultContext;
}
public void setContext(ScriptContext context) {
defaultContext = context;
}
public ScriptEngineFactory getFactory() {
return myFactory;
}
/*
* private methods
*/
private static String getScriptFromReader(Reader reader) {
try {
StringWriter script = new StringWriter();
int data;
while ((data = reader.read()) != -1) {
script.write(data);
}
script.flush();
return script.toString();
} catch (IOException ex) {
}
return null;
}
}

View File

@@ -0,0 +1,127 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.script;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
/**
*
* @author jim_roseborough
*/
public class LuaScriptEngineFactory implements ScriptEngineFactory {
private static final String FILEEXT = ".lua";
private static final String [] MIMETYPES = {
"text/plain",
"text/lua",
"application/lua"
};
private static final String [] NAMES = {
"lua",
"luaj",
};
private ScriptEngine myScriptEngine;
private List<String> extensions;
private List<String> mimeTypes;
private List<String> names;
public LuaScriptEngineFactory() {
myScriptEngine = new LuaScriptEngine();
extensions = Collections.nCopies(1, FILEEXT);
mimeTypes = Arrays.asList(MIMETYPES);
names = Arrays.asList(NAMES);
}
public String getEngineName() {
return getScriptEngine().get(ScriptEngine.ENGINE).toString();
}
public String getEngineVersion() {
return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString();
}
public List<String> getExtensions() {
return extensions;
}
public List<String> getMimeTypes() {
return mimeTypes;
}
public List<String> getNames() {
return names;
}
public String getLanguageName() {
return getScriptEngine().get(ScriptEngine.LANGUAGE).toString();
}
public String getLanguageVersion() {
return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString();
}
public Object getParameter(String key) {
return getScriptEngine().get(key).toString();
}
public String getMethodCallSyntax(String obj, String m, String... args) {
StringBuffer sb = new StringBuffer();
sb.append(obj + ":" + m + "(");
int len = args.length;
for (int i = 0; i < len; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(args[i]);
}
sb.append(")");
return sb.toString();
}
public String getOutputStatement(String toDisplay) {
return "print(" + toDisplay + ")";
}
public String getProgram(String ... statements) {
StringBuffer sb = new StringBuffer();
int len = statements.length;
for (int i = 0; i < len; i++) {
if (i > 0) {
sb.append('\n');
}
sb.append(statements[i]);
}
return sb.toString();
}
public ScriptEngine getScriptEngine() {
return myScriptEngine;
}
}

View File

@@ -0,0 +1,62 @@
/*******************************************************************************
* Copyright (c) 2008 LuaJ. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.script;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineSample {
public static void main(String [] args) {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine e = sem.getEngineByExtension(".lua");
ScriptEngineFactory f = e.getFactory();
String engineName = f.getEngineName();
String engineVersion = f.getEngineVersion();
String langName = f.getLanguageName();
String langVersion = f.getLanguageVersion();
System.out.println(engineName + " " +
engineVersion + " " +
langName + " " +
langVersion);
String statement = f.getOutputStatement("\"hello, world\"");
System.out.println(statement);
try {
e.eval(statement);
e.put("x", 25);
e.eval("y = math.sqrt(x)");
System.out.println( "y="+e.get("y") );
e.put("x", 2);
e.eval("y = math.sqrt(x)");
System.out.println( "y="+e.get("y") );
e.eval("\n\nbogus example\n\n");
} catch (ScriptException ex) {
ex.printStackTrace();
}
}
}