Initial pass at JSR 223 pluggable scripting engne.
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
org.luaj.script.LuaScriptEngineFactory
|
||||||
234
src/script/org/luaj/script/LuaScriptEngine.java
Normal file
234
src/script/org/luaj/script/LuaScriptEngine.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
127
src/script/org/luaj/script/LuaScriptEngineFactory.java
Normal file
127
src/script/org/luaj/script/LuaScriptEngineFactory.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/script/org/luaj/script/ScriptEngineSample.java
Normal file
62
src/script/org/luaj/script/ScriptEngineSample.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user