All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sandius.rembulan.lib.luajava.LuaJavaLib Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Miroslav Janíček
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.sandius.rembulan.lib.luajava;

import net.sandius.rembulan.LuaRuntimeException;
import net.sandius.rembulan.Table;
import net.sandius.rembulan.TableFactory;
import net.sandius.rembulan.impl.UnimplementedFunction;
import net.sandius.rembulan.lib.Lib;
import net.sandius.rembulan.lib.impl.AbstractLibFunction;
import net.sandius.rembulan.lib.impl.ArgumentIterator;
import net.sandius.rembulan.runtime.ExecutionContext;
import net.sandius.rembulan.runtime.ResolvedControlThrowable;

import java.lang.reflect.InvocationTargetException;

public class LuaJavaLib extends Lib {

	@Override
	public String name() {
		return "luajava";
	}

	@Override
	public Table toTable(TableFactory tableFactory) {
		Table t = tableFactory.newTable();

		t.rawset("newInstance", NewInstance.INSTANCE);
		t.rawset("bindClass", BindClass.INSTANCE);
		t.rawset("new", New.INSTANCE);
		t.rawset("createProxy", new UnimplementedFunction("luajava.createProxy"));
		t.rawset("loadLib", new UnimplementedFunction("luajava.loadLib"));

		return t;
	}

	/**
	 * {@code newInstance(className, ...)}
	 *
	 * 

This function creates a new Java object, and returns a Lua object that is a reference * to the actual Java object. You can access this object with the regular syntax used * to access object oriented functions in Lua objects.

* *

The first parameter is the name of the class to be instantiated. The other parameters * are passed to the Java Class constructor.

* *

Example:

* *
	 * obj = luajava.newInstance("java.lang.Object")
	 * -- obj is now a reference to the new object
	 * -- created and any of its methods can be accessed.
	 *
	 * -- this creates a string tokenizer to the "a,b,c,d"
	 * -- string using "," as the token separator.
	 * strTk = luajava.newInstance("java.util.StringTokenizer",
	 *     "a,b,c,d", ",")
	 * while strTk:hasMoreTokens() do
	 *     print(strTk:nextToken())
	 * end
	 * 
* *

The code above should print the following on the screen:

* *
	 * a
	 * b
	 * c
	 * d
	 * 
*/ static class NewInstance extends AbstractLibFunction { static final NewInstance INSTANCE = new NewInstance(); @Override protected String name() { return "newInstance"; } @Override protected void invoke(ExecutionContext context, ArgumentIterator args) throws ResolvedControlThrowable { String className = args.nextString().toString(); Object[] ctorArgs = args.getTail(); final ObjectWrapper instance; try { instance = ObjectWrapper.newInstance(className, ctorArgs); } catch (ClassNotFoundException | MethodSelectionException | IllegalAccessException | InstantiationException | InvocationTargetException ex) { throw new LuaRuntimeException(ex); } context.getReturnBuffer().setTo(instance); } } /** * {@code bindClass(className)} * *

This function retrieves a Java class corresponding to {@code className}. * The returned object can be used to access static fields and methods of the corresponding * class.

* *

Example:

* *
	 * sys = luajava.bindClass("java.lang.System")
	 * print ( sys:currentTimeMillis() )
	 *
	 * -- this prints the time returned by the function.
	 * 
*/ static class BindClass extends AbstractLibFunction { static final BindClass INSTANCE = new BindClass(); @Override protected String name() { return "bindClass"; } @Override protected void invoke(ExecutionContext context, ArgumentIterator args) throws ResolvedControlThrowable { String className = args.nextString().toString(); final ClassWrapper wrapper; try { wrapper = ClassWrapper.of(className); } catch (ClassNotFoundException ex) { throw new LuaRuntimeException(ex); } context.getReturnBuffer().setTo(wrapper); } } /** * {@code new(javaClass)} * *

This function receives a java.lang.Class and returns a new instance of this class.

* *

{@code new} works just like {@code newInstance}, but the first argument is an instance of the * class.

* *

Example:

* *
	 * str = luajava.bindClass("java.lang.String")
	 * strInstance = luajava.new(str)
	 * 
*/ static class New extends AbstractLibFunction { static final New INSTANCE = new New(); @Override protected String name() { return "new"; } @Override protected void invoke(ExecutionContext context, ArgumentIterator args) throws ResolvedControlThrowable { ClassWrapper classWrapper = args.nextUserdata(ClassWrapper.staticTypeName(), ClassWrapper.class); final ObjectWrapper instance; try { instance = ObjectWrapper.newInstance(classWrapper.get(), new Object[] { }); } catch (MethodSelectionException | IllegalAccessException | InstantiationException | InvocationTargetException ex) { throw new LuaRuntimeException(ex); } context.getReturnBuffer().setTo(instance); } } /** * {@code createProxy(interfaceNames, luaObject)} * *

We can also, instead of creating a Java object to be manipulated by Lua, create a Lua * object that will be manipulated by Java. We can do that in LuaJava by creating a proxy to * that object. This is done by the {@code createProxy} function.

* *

The function {@code createProxy} returns a java Object reference that can be used as * an implementation of the given interface.

* *

{@code createProxy} receives a string that contains the names of the interfaces to * be implemented, separated by a comma ({@code ,}), and a Lua object that is the interface * implementation.

* *

Example:

* *
	 * button = luajava.newInstance("java.awt.Button", "execute")
	 * button_cb = {}
	 * function button_cb.actionPerformed(ev)
	 *   -- ...
	 * end
	 *
	 * buttonProxy = luajava.createProxy("java.awt.ActionListener",
	 *    button_cb)
	 *
	 * button:addActionListener(buttonProxy)
	 * 
* *

We can use Lua scripts to write implementations only for Java interfaces.

*/ static class CreateProxy extends AbstractLibFunction { static final CreateProxy INSTANCE = new CreateProxy(); @Override protected String name() { return "createProxy"; } @Override protected void invoke(ExecutionContext context, ArgumentIterator args) throws ResolvedControlThrowable { throw new UnsupportedOperationException("not implemented: " + name()); // TODO } } /** * {@code loadLib(className, methodName)} * *

loadLib is a function that has a use similar to Lua's {@code loadlib} function. * The purpose of this function is to allow users to write libraries in Java and then load * them into Lua.

* *

What {@code loadLib} does is call a static function in a given class and execute * a given method, which should receive {@code LuaState} as parameter. If this function * returns a integer, LuaJava takes it as the number of parameters returned by the the * function, otherwise nothing is returned.

* *

The following Lua example can access the global {@code eg} created by the Java class * {@code test.LoadLibExample}: * *

	 * luajava.loadLib("test.LoadLibExample", "open")
	 * eg.example(3)
	 * 
* *

And this Java example implements the method {@code example}:

* *
	 * public static int open(LuaState L) throws LuaException {
	 *     L.newTable();
	 *     L.pushValue(-1);
	 *     L.setGlobal("eg");
	 *
	 *     L.pushString("example");
	 *
	 *     L.pushJavaFunction(new JavaFunction(L) {
	 *         //
	 *         // Example for loadLib.
	 *         // Prints the time and the first parameter, if any.
	 *         //
	 *         public int execute() throws LuaException {
	 *             System.out.println(new Date().toString());
	 *
	 *             if (L.getTop() > 1) {
	 *                 System.out.println(getParam(2));
	 *             }
	 *
	 *             return 0;
	 *         }
	 *     });
	 *
	 *     L.setTable(-3);
	 *
	 *     return 1;
	 * }
	 * 
*/ static class LoadLib extends AbstractLibFunction { static final LoadLib INSTANCE = new LoadLib(); @Override protected String name() { return "loadLib"; } @Override protected void invoke(ExecutionContext context, ArgumentIterator args) throws ResolvedControlThrowable { throw new UnsupportedOperationException("not implemented: " + name()); // TODO } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy