Implement redirection for pluggable scripting contexts
This commit is contained in:
@@ -842,6 +842,7 @@ Files are no longer hosted at LuaForge.
|
||||
<li>Fix bug 3565008 so that short substrings are backed by short arrays.</li>
|
||||
<li>Fix bug 3495802 to return correct offset of substrings from string.find().</li>
|
||||
<li>Add artifacts to Maven central repository.</li>
|
||||
<li>Limit pluggable scripting to use compatible bindings and contexts, implement redirection.</li>
|
||||
|
||||
</ul></td></tr>
|
||||
</table></td></tr></table>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
|
||||
import java.io.CharArrayReader;
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.Compilable;
|
||||
import javax.script.CompiledScript;
|
||||
@@ -11,6 +15,8 @@ import javax.script.SimpleBindings;
|
||||
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.lib.OneArgFunction;
|
||||
import org.luaj.vm2.script.LuaScriptEngine;
|
||||
import org.luaj.vm2.script.LuajBindings;
|
||||
|
||||
public class ScriptEngineSample {
|
||||
|
||||
@@ -22,6 +28,7 @@ public class ScriptEngineSample {
|
||||
|
||||
ScriptEngineManager sem = new ScriptEngineManager();
|
||||
ScriptEngine e = sem.getEngineByExtension(".lua");
|
||||
e = new LuaScriptEngine();
|
||||
ScriptEngineFactory f = e.getFactory();
|
||||
|
||||
// uncomment to enable the lua-to-java bytecode compiler
|
||||
@@ -66,8 +73,8 @@ public class ScriptEngineSample {
|
||||
System.out.println( "y="+b1.get("y") );
|
||||
System.out.println( "y="+b2.get("y") );
|
||||
|
||||
// Bindings that use a client-specified Bindings type.
|
||||
Bindings sb = new SimpleBindings();
|
||||
// In Luaj 3.0, client bindings must derive from LuajBindings.
|
||||
Bindings sb = new LuajBindings();
|
||||
sb.put("x", 2);
|
||||
System.out.println( "eval: "+cs.eval(sb) );
|
||||
|
||||
@@ -81,6 +88,36 @@ public class ScriptEngineSample {
|
||||
testEngineBindings(e);
|
||||
testClientBindings(e);
|
||||
testUserClasses(e);
|
||||
|
||||
// Test redirection of input, output, and standard error.
|
||||
Reader input = new CharArrayReader("abcdefg\nhijk".toCharArray());
|
||||
CharArrayWriter output = new CharArrayWriter();
|
||||
CharArrayWriter errors = new CharArrayWriter();
|
||||
String script =
|
||||
"print(\"string written using 'print'\")\n" +
|
||||
"io.write(\"string written using 'io.write()'\\n\")\n" +
|
||||
"io.stdout:write(\"string written using 'io.stdout:write()'\\n\")\n" +
|
||||
"io.stderr:write(\"string written using 'io.stderr:write()'\\n\")\n" +
|
||||
"io.write([[string read using 'io.stdin:read(\"*l\")':]]..io.stdin:read(\"*l\")..\"\\n\")\n";
|
||||
|
||||
System.out.println("Evaluating script with redirection set.");
|
||||
e.getContext().setReader(input);
|
||||
e.getContext().setWriter(output);
|
||||
e.getContext().setErrorWriter(errors);
|
||||
e.eval(script);
|
||||
System.out.println("output::>"+output+"<::output");
|
||||
System.out.println("errors::>"+errors+"<::errors");
|
||||
|
||||
System.out.println("Evaluating script with redirection reset.");
|
||||
output.reset();
|
||||
errors.reset();
|
||||
e.getContext().setReader(null);
|
||||
e.getContext().setWriter(null);
|
||||
e.getContext().setErrorWriter(null);
|
||||
e.eval(script);
|
||||
System.out.println("output::>"+output+"<::output");
|
||||
System.out.println("errors::>"+errors+"<::errors");
|
||||
|
||||
|
||||
} catch (ScriptException ex) {
|
||||
ex.printStackTrace();
|
||||
@@ -97,7 +134,7 @@ public class ScriptEngineSample {
|
||||
testBindings(e, e.createBindings());
|
||||
}
|
||||
public static void testClientBindings(ScriptEngine e) throws ScriptException {
|
||||
testBindings(e, new SimpleBindings());
|
||||
testBindings(e, new LuajBindings());
|
||||
}
|
||||
public static void testBindings(ScriptEngine e, Bindings b) throws ScriptException {
|
||||
CompiledScript cs = ((Compilable)e).compile(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2008 LuaJ. All rights reserved.
|
||||
* Copyright (c) 2008-2013 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
|
||||
@@ -21,38 +21,21 @@
|
||||
******************************************************************************/
|
||||
package org.luaj.vm2.script;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Map.Entry;
|
||||
import java.io.*;
|
||||
import javax.script.*;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.Compilable;
|
||||
import javax.script.CompiledScript;
|
||||
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.vm2.Globals;
|
||||
import org.luaj.vm2.LoadState;
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.LuaClosure;
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaFunction;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.Varargs;
|
||||
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||
import org.luaj.vm2.*;
|
||||
|
||||
/**
|
||||
* Implementation of the ScriptEngine interface which can compile and execute
|
||||
* scripts using luaj.
|
||||
*
|
||||
* @author jim_roseborough
|
||||
* <p>
|
||||
* This engine requires the types of the Bindings and ScriptContext to be
|
||||
* compatible with the engine. For creating new client context use
|
||||
* ScriptEngine.createContext() which will return {@link LuajContext},
|
||||
* and for client bindings use the default engine scoped bindings or
|
||||
* construct a {@link LuajBindings} directly.
|
||||
*/
|
||||
public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
|
||||
@@ -66,21 +49,13 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
|
||||
private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory();
|
||||
|
||||
private ScriptContext defaultContext;
|
||||
|
||||
private final Globals _G;
|
||||
private LuajContext context;
|
||||
|
||||
public LuaScriptEngine() {
|
||||
|
||||
// create globals
|
||||
_G = "true".equals(System.getProperty("luaj.debug"))?
|
||||
JsePlatform.debugGlobals():
|
||||
JsePlatform.standardGlobals();
|
||||
|
||||
// set up context
|
||||
ScriptContext ctx = new SimpleScriptContext();
|
||||
ctx.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
|
||||
setContext(ctx);
|
||||
context = new LuajContext();
|
||||
context.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
|
||||
setContext(context);
|
||||
|
||||
// set special values
|
||||
put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
|
||||
@@ -91,9 +66,6 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
put(FILENAME, __FILENAME__);
|
||||
put(NAME, __SHORT_NAME__);
|
||||
put("THREADING", null);
|
||||
|
||||
// Let globals act as an index metatable
|
||||
_G.set(LuaValue.INDEX, _G);
|
||||
}
|
||||
|
||||
public Object eval(String script) throws ScriptException {
|
||||
@@ -109,7 +81,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
}
|
||||
|
||||
public Object eval(Reader reader) throws ScriptException {
|
||||
return eval(reader, getContext());
|
||||
return compile(reader).eval();
|
||||
}
|
||||
|
||||
public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
|
||||
@@ -117,12 +89,7 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
}
|
||||
|
||||
public Object eval(Reader reader, Bindings bindings) throws ScriptException {
|
||||
ScriptContext c = getContext();
|
||||
Bindings current = c.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
c.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
|
||||
Object result = eval(reader);
|
||||
c.setBindings(current, ScriptContext.ENGINE_SCOPE);
|
||||
return result;
|
||||
return compile(reader).eval(bindings);
|
||||
}
|
||||
|
||||
public void put(String key, Object value) {
|
||||
@@ -144,15 +111,17 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
}
|
||||
|
||||
public Bindings createBindings() {
|
||||
return new SimpleBindings();
|
||||
return new LuajBindings();
|
||||
}
|
||||
|
||||
public ScriptContext getContext() {
|
||||
return defaultContext;
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setContext(ScriptContext context) {
|
||||
defaultContext = context;
|
||||
if (!(context instanceof LuajContext))
|
||||
throw new IllegalArgumentException("LuaScriptEngine can only be used with LuajScriptContext");
|
||||
this.context = (LuajContext) context;
|
||||
}
|
||||
|
||||
public ScriptEngineFactory getFactory() {
|
||||
@@ -165,88 +134,65 @@ public class LuaScriptEngine implements ScriptEngine, Compilable {
|
||||
|
||||
public CompiledScript compile(Reader reader) throws ScriptException {
|
||||
try {
|
||||
InputStream ris = new Utf8Encoder(reader);
|
||||
InputStream is = new Utf8Encoder(reader);
|
||||
try {
|
||||
final LuaFunction f = LoadState.load(ris, "script", "bt", _G);
|
||||
if ( f.isclosure() ) {
|
||||
// most compiled functions are closures with prototypes
|
||||
final Prototype p = f.checkclosure().p;
|
||||
return new CompiledScriptImpl() {
|
||||
protected LuaFunction newFunctionInstance(LuaTable env) {
|
||||
return new LuaClosure( p, env );
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// when luajc is used, functions are java class instances
|
||||
final Class c = f.getClass();
|
||||
return new CompiledScriptImpl() {
|
||||
protected LuaFunction newFunctionInstance(LuaTable env) throws ScriptException {
|
||||
try {
|
||||
LuaFunction f = (LuaFunction) c.newInstance();
|
||||
f.initupvalue1( env );
|
||||
return f;
|
||||
} catch (Exception e) {
|
||||
throw new ScriptException("instantiation failed: "+e.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
final Globals g = context.globals;
|
||||
final LuaFunction f = LoadState.load(is, "script", "bt", g);
|
||||
return new LuajCompiledScript(f, g);
|
||||
} catch ( LuaError lee ) {
|
||||
throw new ScriptException(lee.getMessage() );
|
||||
} finally {
|
||||
ris.close();
|
||||
is.close();
|
||||
}
|
||||
} catch ( Exception e ) {
|
||||
throw new ScriptException("eval threw "+e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected class CompiledScriptImpl extends CompiledScript {
|
||||
abstract protected LuaFunction newFunctionInstance(LuaTable env) throws ScriptException;
|
||||
|
||||
class LuajCompiledScript extends CompiledScript {
|
||||
final LuaFunction function;
|
||||
final Globals compiling_globals;
|
||||
LuajCompiledScript(LuaFunction function, Globals compiling_globals) {
|
||||
this.function = function;
|
||||
this.compiling_globals = compiling_globals;
|
||||
}
|
||||
|
||||
public ScriptEngine getEngine() {
|
||||
return LuaScriptEngine.this;
|
||||
}
|
||||
public Object eval(ScriptContext context) throws ScriptException {
|
||||
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
BindingsGlobals env = new BindingsGlobals(b);
|
||||
LuaFunction f = newFunctionInstance(env);
|
||||
|
||||
public Object eval() throws ScriptException {
|
||||
return eval(getContext());
|
||||
}
|
||||
|
||||
public Object eval(Bindings bindings) throws ScriptException {
|
||||
ScriptContext c = getContext();
|
||||
Bindings current = c.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
try {
|
||||
return f.invoke(LuaValue.NONE);
|
||||
c.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
|
||||
Object result = eval(c);
|
||||
return result;
|
||||
} finally {
|
||||
env.copyout();
|
||||
c.setBindings(current, ScriptContext.ENGINE_SCOPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BindingsGlobals extends Globals {
|
||||
final Bindings b;
|
||||
BindingsGlobals(Bindings b) {
|
||||
this.b = b;
|
||||
this.setmetatable(_G);
|
||||
this.debuglib = _G.debuglib;
|
||||
for (Entry<String,Object> e : b.entrySet())
|
||||
rawset(toLua(e.getKey()), toLua(e.getValue()));
|
||||
}
|
||||
void copyout() {
|
||||
b.clear();
|
||||
for (Varargs v = next(LuaValue.NIL); !v.arg1().isnil(); v = next(v.arg1()))
|
||||
b.put(toJava(v.arg1()).toString(), toJava(v.arg(2)));
|
||||
}
|
||||
}
|
||||
|
||||
LuaValue toLua(Object javaValue) {
|
||||
return javaValue == null? LuaValue.NIL:
|
||||
javaValue instanceof LuaValue? (LuaValue) javaValue:
|
||||
CoerceJavaToLua.coerce(javaValue);
|
||||
}
|
||||
|
||||
Object toJava(LuaValue v) {
|
||||
switch ( v.type() ) {
|
||||
case LuaValue.TNIL: return null;
|
||||
case LuaValue.TSTRING: return v.tojstring();
|
||||
case LuaValue.TUSERDATA: return v.checkuserdata(Object.class);
|
||||
case LuaValue.TNUMBER: return v.isinttype()? (Object) new Integer(v.toint()): (Object) new Double(v.todouble());
|
||||
default: return v;
|
||||
public Object eval(ScriptContext context) throws ScriptException {
|
||||
Globals g = ((LuajContext) context).globals;
|
||||
LuaFunction f = function;
|
||||
if (g != compiling_globals) {
|
||||
if (f.isclosure())
|
||||
f = new LuaClosure(f.checkclosure().p, g);
|
||||
else {
|
||||
try {
|
||||
f = f.getClass().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new ScriptException(e);
|
||||
}
|
||||
f.initupvalue1(g);
|
||||
}
|
||||
}
|
||||
return f.invoke(LuaValue.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
211
src/jse/org/luaj/vm2/script/LuajBindings.java
Normal file
211
src/jse/org/luaj/vm2/script/LuajBindings.java
Normal file
@@ -0,0 +1,211 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 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.vm2.script;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.script.Bindings;
|
||||
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.lib.ThreeArgFunction;
|
||||
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
||||
|
||||
/**
|
||||
* Implementation of Bindings that may be used with Luaj ScriptEngine implementaiton.
|
||||
*
|
||||
* <p>
|
||||
* Normally this will not be created directly, but instead will be created fro the script
|
||||
* engine using something like:
|
||||
* <pre>
|
||||
* ScriptEngineManager manager = new ScriptEngineManager();
|
||||
* ScriptEngine engine = manager.getEngineByExtension(".lua");
|
||||
* Bindings luaj_bindings = engine.createBindings();
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Each instance of LuajBindings holds its own global state.
|
||||
* Calls to get(), put(), and so on will coerce the lua values
|
||||
* into Java values on-the-fly, so that any performance or
|
||||
* memory occur at that point.
|
||||
*
|
||||
* <p>
|
||||
* Only Java String keys may be used for get(), put(), and similar
|
||||
* operations, or ClassCastException will be thrown.
|
||||
*
|
||||
* <p>
|
||||
* When iterating over the globals, only values which have string keys
|
||||
* will be returned.
|
||||
*/
|
||||
public class LuajBindings implements Bindings {
|
||||
|
||||
/** Values that are in these bindings. This table is linked to the metatable
|
||||
* of the context when it is executed via the metatable.
|
||||
*/
|
||||
public final LuaTable env;
|
||||
|
||||
/** Metatable to be used on bindings that will forards gets and sets into our table of bindings.
|
||||
*/
|
||||
final LuaTable metatable;
|
||||
|
||||
/** Construct an empty LuajBindings.
|
||||
* <p>
|
||||
* Each LuajBindings has its own environment table, which will
|
||||
* delegate to the context on global reads during execution.
|
||||
*/
|
||||
public LuajBindings() {
|
||||
env = new LuaTable();
|
||||
metatable = new LuaTable();
|
||||
metatable.set(LuaValue.INDEX, env);
|
||||
metatable.set(LuaValue.NEWINDEX, new ThreeArgFunction() {
|
||||
public LuaValue call(LuaValue table, LuaValue key, LuaValue value) {
|
||||
env.rawset(key, value);
|
||||
return LuaValue.NONE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Coerce a value from luaj types to Java types.
|
||||
* @param luajValue any value that derives from LuaValue.
|
||||
* @return If luajValue is:
|
||||
* {@link #NIL}, null;
|
||||
* {@link #LuaString}: String;
|
||||
* {@link #LuaUserdata}: Object;
|
||||
* {@link #LuaNumber}: Integer or Double;
|
||||
* otherwise: the raw {@link #LuaValue}.
|
||||
*/
|
||||
public Object toJava(LuaValue luajValue) {
|
||||
switch ( luajValue.type() ) {
|
||||
case LuaValue.TNIL: return null;
|
||||
case LuaValue.TSTRING: return luajValue.tojstring();
|
||||
case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
|
||||
case LuaValue.TNUMBER: return luajValue.isinttype()?
|
||||
(Object) new Integer(luajValue.toint()):
|
||||
(Object) new Double(luajValue.todouble());
|
||||
default: return luajValue;
|
||||
}
|
||||
}
|
||||
|
||||
/** Coerce a value from Java types to luaj types.
|
||||
* @param javaValue Any Java value, including possibly null.
|
||||
* @return LuaValue for this Java Value. If javaValue is
|
||||
* null: {@link #NIL};
|
||||
* {@link #LuaValue}: the value;
|
||||
* String: {@link #LuaString};
|
||||
* Integer: {@link #LuaInteger};
|
||||
* Double: {@link #LuaDouble};
|
||||
* array<Class>: {@link #LuaTable} containing list of values;
|
||||
* otherwise {@link #LuaUserdata} from behavior of {@link CoerceJavaToLua.coerce(Object)}
|
||||
* @see CoerceJavaToLua
|
||||
*/
|
||||
public LuaValue toLua(Object javaValue) {
|
||||
return javaValue == null? LuaValue.NIL:
|
||||
javaValue instanceof LuaValue? (LuaValue) javaValue:
|
||||
CoerceJavaToLua.coerce(javaValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
for (LuaValue key : env.keys())
|
||||
env.rawset(key, LuaValue.NIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object string_key) {
|
||||
return !env.rawget((String)string_key).isnil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<java.util.Map.Entry<String, Object>> entrySet() {
|
||||
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
for (LuaValue key : env.keys())
|
||||
if (key.type() == LuaValue.TSTRING)
|
||||
map.put(key.tojstring(), toJava(env.rawget(key)));
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return keySet().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
Set<String> set = new HashSet<String>();
|
||||
for (LuaValue key : env.keys())
|
||||
if (key.type() == LuaValue.TSTRING)
|
||||
set.add(key.tojstring());
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return keySet().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> values() {
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
for (LuaValue key : env.keys())
|
||||
if (key.type() == LuaValue.TSTRING)
|
||||
values.add(toJava(env.rawget(key)));
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return keySet().contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object string_key) {
|
||||
return toJava(env.rawget((String)string_key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object put(String string_key, Object java_value) {
|
||||
Object previous = get(string_key);
|
||||
env.rawset((String)string_key, toLua(java_value));
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends Object> values) {
|
||||
for (java.util.Map.Entry<? extends String, ? extends Object> e : values.entrySet())
|
||||
env.rawset(e.getKey(), toLua(e.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(Object string_key) {
|
||||
Object previous = get(string_key);
|
||||
env.rawset((String)string_key, LuaValue.NIL);
|
||||
return previous;
|
||||
}
|
||||
|
||||
}
|
||||
143
src/jse/org/luaj/vm2/script/LuajContext.java
Normal file
143
src/jse/org/luaj/vm2/script/LuajContext.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 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.vm2.script;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.SimpleScriptContext;
|
||||
|
||||
import org.luaj.vm2.Globals;
|
||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||
|
||||
/**
|
||||
* Context for LuaScriptEngine execution which maintains its own Globals,
|
||||
* and manages the input and output redirection.
|
||||
*/
|
||||
public class LuajContext extends SimpleScriptContext implements ScriptContext {
|
||||
|
||||
/** Globals for this context instance. */
|
||||
public final Globals globals;
|
||||
|
||||
/** The initial value of globals.STDIN */
|
||||
private final InputStream stdin;
|
||||
/** The initial value of globals.STDOUT */
|
||||
private final PrintStream stdout;
|
||||
/** The initial value of globals.STDERR */
|
||||
private final PrintStream stderr;
|
||||
|
||||
/** Construct a LuajContext with its own globals which may
|
||||
* be debug globals depending on the value of the system
|
||||
* property 'org.luaj.debug'
|
||||
* <p>
|
||||
* If the system property 'org.luaj.debug' is set, the globals
|
||||
* created will be a debug globals that includes the debug
|
||||
* library. This may provide better stack traces, but may
|
||||
* have negative impact on performance.
|
||||
*/
|
||||
public LuajContext() {
|
||||
this("true".equals(System.getProperty("org.luaj.debug")));
|
||||
}
|
||||
|
||||
/** Construct a LuajContext with its own globals, which
|
||||
* which optionally are debug globals.
|
||||
* <p>
|
||||
* If createDebugGlobals is set, the globals
|
||||
* created will be a debug globals that includes the debug
|
||||
* library. This may provide better stack traces, but may
|
||||
* have negative impact on performance.
|
||||
* @param createDebugGlobals true to create debug globals,
|
||||
* false for standard globals.
|
||||
*/
|
||||
public LuajContext(boolean createDebugGlobals) {
|
||||
globals = createDebugGlobals?
|
||||
JsePlatform.debugGlobals():
|
||||
JsePlatform.standardGlobals();
|
||||
stdin = globals.STDIN;
|
||||
stdout = globals.STDOUT;
|
||||
stderr = globals.STDERR;
|
||||
}
|
||||
|
||||
public Bindings getBindings(int scope) {
|
||||
if (scope != ScriptContext.ENGINE_SCOPE)
|
||||
throw new IllegalArgumentException("LuajScriptContext only supports ENGINE_SCOPE");
|
||||
return super.getBindings(ENGINE_SCOPE);
|
||||
}
|
||||
|
||||
public void setBindings(Bindings bindings, int scope) {
|
||||
if (!(bindings instanceof LuajBindings))
|
||||
throw new IllegalArgumentException("LuajScriptContext can only be used with LuajBindings");
|
||||
if (scope != ScriptContext.ENGINE_SCOPE)
|
||||
throw new IllegalArgumentException("LuajScriptContext only supports ENGINE_SCOPE");
|
||||
LuajBindings luaj_bindings = (LuajBindings) bindings;
|
||||
globals.setmetatable(luaj_bindings.metatable);
|
||||
super.setBindings(bindings, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorWriter(Writer writer) {
|
||||
globals.STDERR = writer != null?
|
||||
new PrintStream(new WriterOutputStream(writer)):
|
||||
stderr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReader(Reader reader) {
|
||||
globals.STDIN = reader != null?
|
||||
new ReaderInputStream(reader):
|
||||
stdin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriter(Writer writer) {
|
||||
globals.STDOUT = writer != null?
|
||||
new PrintStream(new WriterOutputStream(writer)):
|
||||
stdout;
|
||||
}
|
||||
|
||||
static final class WriterOutputStream extends OutputStream {
|
||||
final Writer w;
|
||||
WriterOutputStream(Writer w) {
|
||||
this.w = w;
|
||||
}
|
||||
public void write(int b) throws IOException {
|
||||
w.write(b);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ReaderInputStream extends InputStream {
|
||||
final Reader r;
|
||||
ReaderInputStream(Reader r) {
|
||||
this.r = r;
|
||||
}
|
||||
public int read() throws IOException {
|
||||
return r.read();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user