Add luajava exceptino handling, array and unit test logic from 1.0 branch

This commit is contained in:
James Roseborough
2010-04-03 05:31:53 +00:00
parent 46a9527701
commit a548ef27fb
5 changed files with 368 additions and 23 deletions

View File

@@ -49,6 +49,8 @@ public class LuaError extends RuntimeException {
return msg;
}
private Throwable cause;
/**
* Construct a LuaErrorException in response to a Throwable that was caught
* indicating a problem with the VM rather than the lua code.
@@ -57,6 +59,7 @@ public class LuaError extends RuntimeException {
*/
public LuaError(Throwable cause) {
this( errorHook( "vm error: "+cause ) );
this.cause = cause;
}
/**
@@ -94,5 +97,12 @@ public class LuaError extends RuntimeException {
}
}
/**
* Get the cause, if any.
*/
public Throwable getCause() {
return cause;
}
}

View File

@@ -21,9 +21,11 @@
******************************************************************************/
package org.luaj.vm2.lib.jse;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
@@ -213,14 +215,50 @@ public class CoerceLuaToJava {
COERCIONS.put( Object.class, objectCoercion );
}
static Object coerceArg(LuaValue v, Class type) {
Coercion co = (Coercion) COERCIONS.get( type );
if ( co != null )
return co.coerce( v );
Object o = v.optuserdata(type, null);
if ( o != null )
return o;
return v;
/** Score a single parameter, including array handling */
private static int scoreParam(LuaValue a, Class c) {
if ( a.isuserdata(c) )
return 0;
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
return co.score( a );
}
if ( c.isArray() ) {
Class typ = c.getComponentType();
switch ( a.type() ) {
case LuaValue.TTABLE:
return scoreParam( a.checktable().get(1), typ );
default:
return 0x10 + (scoreParam(a, typ) << 8);
}
}
return 0x1000;
}
/** Do a conversion */
static Object coerceArg(LuaValue a, Class c) {
if ( a.isuserdata(c) )
return a.touserdata(c);
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
return co.coerce( a );
}
if ( c.isArray() ) {
boolean istable = a.istable();
int n = istable? a.length(): 1;
Class typ = c.getComponentType();
Object arr = Array.newInstance(typ, n);
for ( int i=0; i<n; i++ ) {
LuaValue ele = (istable? a.checktable().get(i+1): a);
if ( ele != null )
Array.set(arr, i, coerceArg(ele, typ));
}
return arr;
}
if ( a.isnil() )
return null;
throw new LuaError("no coercion found for "+a.getClass()+" to "+c);
}
static Object[] coerceArgs(LuaValue[] suppliedArgs, Class[] parameterTypes) {
@@ -247,16 +285,9 @@ public class CoerceLuaToJava {
for ( int i=0; i<nargs && i<njava; i++ ) {
LuaValue a = suppliedArgs[i];
Class c = paramTypes[i];
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
score += co.score( a );
} else if ( a.optuserdata(c, null) == null ) {
score += 0x10000;
} else {
score += 0x100;
}
int s = scoreParam( a, c );
score += s;
}
return score;
}
}

View File

@@ -26,9 +26,11 @@ package org.luaj.vm2.lib.jse;
*
* TODO: coerce types on way in and out, pick method base on arg count ant types.
*/
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
@@ -42,7 +44,6 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaUserdata;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
@@ -65,6 +66,10 @@ public class LuajavaLib extends OneArgFunction {
private static final Map classMetatables = new HashMap();
private static final int METHOD_MODIFIERS_VARARGS = 0x80;
private static LuaValue LENGTH = valueOf("length");
public static void install(LuaValue globals) {
globals.set("luajava", new LuajavaLib());
}
@@ -120,10 +125,22 @@ public class LuajavaLib extends OneArgFunction {
LuaValue func = lobj.get(name);
if ( func.isnil() )
return null;
boolean isvarargs = ((method.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
int n = args!=null? args.length: 0;
LuaValue[] v = new LuaValue[n];
for ( int i=0; i<n; i++ )
v[i] = CoerceJavaToLua.coerce(args[i]);
LuaValue[] v;
if ( isvarargs ) {
Object o = args[--n];
int m = Array.getLength( o );
v = new LuaValue[n+m];
for ( int i=0; i<n; i++ )
v[i] = CoerceJavaToLua.coerce(args[i]);
for ( int i=0; i<m; i++ )
v[i+n] = CoerceJavaToLua.coerce(Array.get(o,i));
} else {
v = new LuaValue[n];
for ( int i=0; i<n; i++ )
v[i] = CoerceJavaToLua.coerce(args[i]);
}
LuaValue result = func.invoke(v).arg1();
return CoerceLuaToJava.coerceArg(result, method.getReturnType());
}
@@ -153,6 +170,8 @@ public class LuajavaLib extends OneArgFunction {
}
} catch (LuaError e) {
throw e;
} catch (InvocationTargetException ite) {
throw new LuaError(ite.getTargetException());
} catch (Exception e) {
throw new LuaError(e);
}
@@ -188,12 +207,23 @@ public class LuajavaLib extends OneArgFunction {
mt = new LuaTable();
mt.set( LuaValue.INDEX, new TwoArgFunction() {
public LuaValue call(LuaValue table, LuaValue key) {
Object instance = table.touserdata();
if ( key.isinttype() ) {
if ( clazz.isArray() ) {
int index = key.toint() - 1;
if ( index >= 0 && index < Array.getLength(instance) )
return CoerceJavaToLua.coerce( Array.get(instance, index) );
return NIL;
}
}
final String s = key.toString();
try {
Field f = clazz.getField(s);
Object o = f.get(table.checkuserdata(Object.class));
Object o = f.get(instance);
return CoerceJavaToLua.coerce( o );
} catch (NoSuchFieldException nsfe) {
if ( clazz.isArray() && key.equals(LENGTH) )
return LuaValue.valueOf( Array.getLength(instance) );
return new LMethod(clazz,s);
} catch (Exception e) {
throw new LuaError(e);
@@ -202,6 +232,18 @@ public class LuajavaLib extends OneArgFunction {
});
mt.set( LuaValue.NEWINDEX, new ThreeArgFunction() {
public LuaValue call(LuaValue table, LuaValue key, LuaValue val) {
Object instance = table.touserdata();
if ( key.isinttype() ) {
if ( clazz.isArray() ) {
Object v = CoerceLuaToJava.coerceArg(val, clazz.getComponentType());
int index = key.toint() - 1;
if ( index >= 0 && index < Array.getLength(instance) )
Array.set(instance, index, v);
else
throw new LuaError("array bounds exceeded "+index);
return NIL;
}
}
String s = key.toString();
try {
Field f = clazz.getField(s);
@@ -241,6 +283,8 @@ public class LuajavaLib extends OneArgFunction {
// coerce the result
return CoerceJavaToLua.coerce(result);
} catch (InvocationTargetException ite) {
throw new LuaError(ite.getTargetException());
} catch (Exception e) {
throw new LuaError(e);
}