import java.io.InputStream; import java.io.Reader; import org.luaj.vm2.Globals; import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.jse.JsePlatform; import org.luaj.vm2.server.Launcher; import org.luaj.vm2.server.LuajClassLoader; /** Example of using {@link LuajClassLoader} to launch scripts that are blocked from * interfering with globals from other scripts including shared static metatables. *

* This technique is useful in a server environment to expose the full set of * lua features to each script, while preventing scripts from interfering with * each other. *

* Because each Launch gets its own {@link LuajClassLoader}, it should be possible * to include the debug library, or let scripts manipulate shared metatables, * or luajava, which otherwise present challenges in a server environment. *

*/ public class SampleUsingClassLoader { /** Script that manipulates the shared string metatable. * When loaded by the {@link LuajClassLoader} via a {@link Launcher} * created by that class, each instance of {@link LuajClassLoader} will * have a completely separate version of all static variables. */ static String script = "print('args:', ...)\n" + "print('abc.foo', ('abc').foo)\n" + "getmetatable('abc').__index.foo = function() return 'bar' end\n" + "print('abc.foo', ('abc').foo)\n" + "print('abc:foo()', ('abc'):foo())\n" + "return math.pi\n"; public static void main(String[] s) throws Exception { // The default launcher used standard globals. RunUsingDefaultLauncher(); RunUsingDefaultLauncher(); // Example using custom launcher class that instantiates debug globals. RunUsingCustomLauncherClass(); RunUsingCustomLauncherClass(); } static void RunUsingDefaultLauncher() throws Exception { Launcher launcher = LuajClassLoader.NewLauncher(); // starts with pristine Globals including all luaj static variables. print(launcher.launch(script, new Object[] { "--------" })); // reuses Globals and static variables from previous step. print(launcher.launch(script, new Object[] {})); } static void RunUsingCustomLauncherClass() throws Exception { Launcher launcher = LuajClassLoader.NewLauncher(MyLauncher.class); // starts with pristine Globals including all luaj static variables. print(launcher.launch(script, new Object[] { "=========" })); // reuses Globals and static variables from previous step. print(launcher.launch(script, new Object[] { "" })); } /** Example of Launcher implementation performing specialized launching. * When loaded by the {@link LuajClassLoader} all luaj classes will be loaded * for each instance of the {@link Launcher} and not interfere with other * classes loaded by other instances. */ public static class MyLauncher implements Launcher { Globals g; public MyLauncher() { g = JsePlatform.debugGlobals(); // ... plus any other customization of the user environment } public Object[] launch(String script, Object[] arg) { LuaValue chunk = g.load(script, "main"); return new Object[] { chunk.call(LuaValue.valueOf(arg[0].toString())) }; } public Object[] launch(InputStream script, Object[] arg) { LuaValue chunk = g.load(script, "main", "bt", g); return new Object[] { chunk.call(LuaValue.valueOf(arg[0].toString())) }; } public Object[] launch(Reader script, Object[] arg) { LuaValue chunk = g.load(script, "main"); return new Object[] { chunk.call(LuaValue.valueOf(arg[0].toString())) }; } } /** Print the return values as strings. */ private static void print(Object[] return_values) { for (int i =0; i