JSR223Provider - airminer/jnlua GitHub Wiki

JNLua includes a provider for JSR 223: Scripting for the Java Platform. JSR 223 allows the use of scripting languages on Java in a generic way. JNLua also supports the optional JSR 223 interfaces Compilable and Invocable.

Registration Attributes

JNLua is registered with the JSR 223 script engine manager using the following attributes:

Attribute Value
Engine Name JNLua
Engine Version LuaState.VERSION
Language Name Lua
Language Version LuaState.LUA_VERSION
Names lua, Lua, jnlua, JNLua
MIME Types application/x-lua, text/x-lua
Extensions lua

Bindings

JSR 223 uses the term bindings to describe the concept of making objects in the Java host environment accessible in the script engine (and vice versa.) In that context, JSR 223 further distinguishes a global scope and an engine scope. The global scope is on a per script engine manager basis and global bindings are typically shared across all script engines created by a script engine manager; the engine scope is on a per script engine basis and engine bindings are typically unique per script engine.

The JNLua JSR 223 provider supports specialized bindings for the engine scope. These bindings are tied directly to the Lua script engine and constitute a map view on the global variables of the underlying Lua state. This means that changes in the global variables of the Lua state immediately show in the engine scope bindings and vice versa. To comply with the JSR 223 API, the map view contains only those entries from the global environment which have non-empty string keys. (Non-empty string keys are the norm for the Lua global environment. However, Lua does not prevent you from using other types of keys.)

The JNLUa JSR 223 provider accepts any binding that complies to the specification. For bindings other than its specialized engine scope bindings, it simply copies the bound objects into the global environment of the Lua state before evaluating scripts.

Example

The full description of JSR 223 is beyond the scope of the JNLua documentation. See the JSR 223 specification and related documentation for more information.

The following code shows a simple demo application using JNLua by means of JSR 223. Note that the import list makes no direct reference to JNLua.

import javax.script.Compilable; 
import javax.script.CompiledScript; 
import javax.script.Invocable; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import javax.script.ScriptException; 

public class Simple { 
	public static void main(String[] args) { 
		// Acquire a script engine manager 
		ScriptEngineManager manager = new ScriptEngineManager(); 

		// Get a script engine by name 
		ScriptEngine engine = manager.getEngineByName("Lua"); 

		// Populate the engine with some objects 
		String name = "Lua"; 
		StringBuilder sb = new StringBuilder(); 
		engine.put("name", name); 
		engine.put("sb", sb); 

		// Evaluate a script 
		try { 
			Object nameFromEngine = engine.eval("return name"); 
			System.out.println("The name of the language is " + nameFromEngine); 
		} catch (ScriptException e) { 
			e.printStackTrace(); 
		} 

		// Evaluate a script generated via the factory 
		try { 
			String methodCall = engine.getFactory().getMethodCallSyntax("sb", "append", "name"); 
			engine.eval(methodCall); // evaluates 'sb:append(name)' 
		} catch (ScriptException e) { 
			e.printStackTrace(); 
		} 
		System.out.println("The string builder says " + sb.toString()); 

		// Pre-compile a script and evaluate it repeatedly 
		Compilable compilable = (Compilable) engine; 
		try { 
			CompiledScript compiledScript = compilable.compile("return name"); 
			for (int i = 0; i < 3; i++) { 
				Object nameFromEngine = compiledScript.eval(); 
				System.out.println("The name of the language is still " + nameFromEngine); 
			} 
		} catch (ScriptException e) { 
			e.printStackTrace(); 
		} 

		// Invoke a function 
		Invocable invocable = (Invocable) engine; 
		try { 
			invocable.invokeFunction("print", "Lua is Lua"); 
		} catch (ScriptException e) { 
			e.printStackTrace(); 
		} catch (NoSuchMethodException e) { 
			e.printStackTrace(); 
		} 

		// Let Lua implement an interface... 
		try { 
			engine.eval("runnable = { run = function () print(\"This is Lua\") end }"); 
			Object luaRunnable = engine.get("runnable"); 
			Runnable runnable = invocable.getInterface(luaRunnable, Runnable.class); 

			// ... and run it from another thread 
			Thread thread = new Thread(runnable); 
			thread.start(); 
			thread.join(); 
		} catch (ScriptException e) { 
			e.printStackTrace(); 
		} catch (InterruptedException e) { 
			e.printStackTrace(); 
		} 
	} 
}