Major refactoring of package names, class names

This commit is contained in:
James Roseborough
2007-11-07 23:56:06 +00:00
parent 2281d056ec
commit ff66779330
99 changed files with 1151 additions and 2739 deletions

View File

@@ -0,0 +1,66 @@
package org.luaj.lib.j2se;
import java.util.HashMap;
import java.util.Map;
import org.luaj.lib.j2se.LuajavaLib.LInstance;
import org.luaj.vm.LBoolean;
import org.luaj.vm.LDouble;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LString;
import org.luaj.vm.LValue;
public class CoerceJavaToLua {
public static interface Coercion {
public LValue coerce( Object javaValue );
};
private static Map COERCIONS = new HashMap();
static {
Coercion boolCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Boolean b = (Boolean) javaValue;
return b.booleanValue()? LBoolean.TRUE: LBoolean.FALSE;
}
} ;
Coercion intCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return LInteger.valueOf( n.intValue() );
}
} ;
Coercion doubleCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return new LDouble( n.doubleValue() );
}
} ;
Coercion stringCoercion = new Coercion() {
public LValue coerce( Object javaValue ) {
return new LString( javaValue.toString() );
}
} ;
COERCIONS.put( Boolean.class, boolCoercion );
COERCIONS.put( Byte.class, intCoercion );
COERCIONS.put( Short.class, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Float.class, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
}
public static LValue coerce(Object o) {
if ( o == null )
return LNil.NIL;
Class clazz = o.getClass();
Coercion c = (Coercion) COERCIONS.get( clazz );
if ( c != null )
return c.coerce( o );
return new LInstance( o, o.getClass() );
}
}

View File

@@ -0,0 +1,162 @@
package org.luaj.lib.j2se;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm.LBoolean;
import org.luaj.vm.LDouble;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNil;
import org.luaj.vm.LNumber;
import org.luaj.vm.LString;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
public class CoerceLuaToJava {
public static interface Coercion {
public Object coerce( LValue value );
public int score( LValue value );
};
private static Map COERCIONS = new HashMap();
private static Coercion OBJECT_COERCION;
static {
Coercion boolCoercion = new Coercion() {
public Object coerce(LValue value) {
return value.toJavaBoolean()? Boolean.TRUE: Boolean.FALSE;
}
public int score(LValue value) {
if ( value instanceof LBoolean || value == LNil.NIL )
return 0;
if ( value instanceof LNumber )
return 1;
return 4;
}
};
Coercion intCoercion = new Coercion() {
public Object coerce(LValue value) {
return Integer.valueOf( value.toJavaInt() );
}
public int score(LValue value) {
if ( value instanceof LInteger )
return 0;
if ( value instanceof LNumber )
return 1;
if ( value instanceof LBoolean || value == LNil.NIL )
return 2;
return 4;
}
};
Coercion doubleCoercion = new Coercion() {
public Object coerce(LValue value) {
return Double.valueOf( value.toJavaDouble() );
}
public int score(LValue value) {
if ( value instanceof LDouble )
return 0;
if ( value instanceof LNumber )
return 1;
if ( value instanceof LBoolean || value == LNil.NIL )
return 2;
return 4;
}
};
Coercion stringCoercion = new Coercion() {
public Object coerce(LValue value) {
return value.toJavaString();
}
public int score(LValue value) {
if ( value instanceof LUserData )
return 0;
return 1;
}
};
Coercion objectCoercion = new Coercion() {
public Object coerce(LValue value) {
if ( value instanceof LUserData )
return ((LUserData)value).m_instance;
if ( value instanceof LString )
return value.toJavaString();
if ( value instanceof LInteger )
return Integer.valueOf(value.toJavaInt());
if ( value instanceof LDouble )
return Double.valueOf(value.toJavaDouble());
if ( value instanceof LBoolean )
return Boolean.valueOf(value.toJavaBoolean());
if ( value == LNil.NIL )
return null;
return value;
}
public int score(LValue value) {
if ( value instanceof LString )
return 0;
return 0x10;
}
};
COERCIONS.put( Boolean.TYPE, boolCoercion );
COERCIONS.put( Boolean.class, boolCoercion );
COERCIONS.put( Byte.TYPE, intCoercion );
COERCIONS.put( Byte.class, intCoercion );
COERCIONS.put( Short.TYPE, intCoercion );
COERCIONS.put( Short.class, intCoercion );
COERCIONS.put( Integer.TYPE, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Long.TYPE, intCoercion );
COERCIONS.put( Long.class, intCoercion );
COERCIONS.put( Double.TYPE, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
COERCIONS.put( Object.class, objectCoercion );
}
static Object coerceArg(LValue v, Class type) {
Coercion co = (Coercion) COERCIONS.get( type );
if ( co != null )
return co.coerce( v );
if ( v instanceof LUserData )
return ((LUserData) v).m_instance;
return v;
}
static Object[] coerceArgs(LValue[] suppliedArgs, Class[] parameterTypes) {
int nargs = suppliedArgs.length;
int n = parameterTypes.length;
Object[] args = new Object[n];
for ( int i=0; i<n && i<nargs; i++ )
args[i] = coerceArg( suppliedArgs[i], parameterTypes[i] );
return args;
}
/*
* Score parameter types for match with supplied parameter list
*
* 1) exact number of args
* 2) java has more args
* 3) java has less args
* 4) types coerce well
*/
static int scoreParamTypes(LValue[] suppliedArgs, Class[] paramTypes) {
int nargs = suppliedArgs.length;
int njava = paramTypes.length;
int score = (njava == nargs? 0: njava > nargs? 0x4000: 0x8000);
for ( int i=0; i<nargs && i<njava; i++ ) {
LValue a = suppliedArgs[i];
Class c = paramTypes[i];
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
score += co.score( a );
} else if ( a instanceof LUserData ) {
Object o = ((LUserData) a).m_instance;
if ( ! c.isAssignableFrom(o.getClass()) )
score += 0x10000;
} else {
score += 0x100;
}
}
return score;
}
}

View File

@@ -0,0 +1,315 @@
package org.luaj.lib.j2se;
/** LuaJava-like bindings to Java scripting.
*
* TODO: coerce types on way in and out, pick method base on arg count ant types.
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.luaj.vm.LFunction;
import org.luaj.vm.LTable;
import org.luaj.vm.LUserData;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
public final class LuajavaLib extends LFunction {
public static void install(LTable globals) {
LTable luajava = new LTable();
for ( int i=0; i<NAMES.length; i++ )
luajava.put( NAMES[i], new LuajavaLib(i) );
globals.put( "luajava", luajava );
}
private static final int NEWINSTANCE = 0;
private static final int BINDCLASS = 1;
private static final int NEW = 2;
private static final int CREATEPROXY = 3;
private static final int LOADLIB = 4;
private static final String[] NAMES = {
"newInstance",
"bindClass",
"new",
"createProxy",
"loadLib" };
private int id;
private LuajavaLib( int id ) {
this.id = id;
}
public String toString() {
return "luajava."+NAMES[id];
}
// perform a lua call
public boolean luaStackCall(LuaState vm) {
String className;
switch ( id ) {
case BINDCLASS:
className = vm.tostring(2);
try {
Class clazz = Class.forName(className);
vm.settop(0);
vm.pushlvalue( new LInstance( clazz, clazz ) );
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
case NEWINSTANCE:
className = vm.tostring(2);
try {
// get constructor
Class clazz = Class.forName(className);
ParamsList params = new ParamsList( vm );
Constructor con = resolveConstructor( clazz, params );
// coerce args
Object[] args = CoerceLuaToJava.coerceArgs( params.values, con.getParameterTypes() );
Object o = con.newInstance( args );
// set the result
vm.settop(0);
vm.pushlvalue( new LInstance( o, clazz ) );
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
default:
luaUnsupportedOperation();
}
return false;
}
public static class ParamsList {
public final LValue[] values;
public final Class[] classes;
public int hash;
ParamsList( LuaState vm ) {
int n = vm.gettop()-2;
values = new LValue[n];
classes = new Class[n];
for ( int i=0; i<n; i++ ) {
values[i] = vm.topointer(i+3);
classes[i] = values[i].getClass();
hash += classes[i].hashCode();
}
}
public int hashCode() {
return hash;
}
public boolean equals( Object o ) {
return ( o instanceof ParamsList )?
Arrays.equals( classes, ((ParamsList) o).classes ):
false;
}
}
public static class LInstance extends LUserData {
private Class clazz;
public LInstance(Object o, Class clazz) {
super(o);
this.clazz = clazz;
}
public void luaGetTable(LuaState vm, LValue table, LValue key) {
final String s = key.toJavaString();
try {
Field f = clazz.getField(s);
Object o = f.get(m_instance);
LValue v = CoerceJavaToLua.coerce( o );
vm.pushlvalue( v );
} catch (NoSuchFieldException nsfe) {
vm.pushlvalue( new LMethod(m_instance,clazz,s) );
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void luaSetTable(LuaState vm, LValue table, LValue key, LValue val) {
Class c = m_instance.getClass();
String s = key.toJavaString();
try {
Field f = c.getField(s);
Object v = CoerceLuaToJava.coerceArg(val, f.getType());
f.set(m_instance,v);
vm.settop(0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean luaStackCall(LuaState vm) {
// TODO Auto-generated method stub
return super.luaStackCall(vm);
}
}
private static final class LMethod extends LFunction {
private final Object instance;
private final Class clazz;
private final String s;
private LMethod(Object instance, Class clazz, String s) {
this.instance = instance;
this.clazz = clazz;
this.s = s;
}
public String toString() {
return clazz.getName()+"."+s+"()";
}
public boolean luaStackCall(LuaState vm) {
try {
// find the method
ParamsList params = new ParamsList( vm );
Method meth = resolveMethod( clazz, s, params );
// coerce the arguments
Object[] args = CoerceLuaToJava.coerceArgs( params.values, meth.getParameterTypes() );
Object result = meth.invoke( instance, args );
// coerce the result
vm.settop(0);
vm.pushlvalue( CoerceJavaToLua.coerce(result) );
return false;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private static Map consCache =
new HashMap();
private static Map consIndex =
new HashMap();
private static Constructor resolveConstructor(Class clazz, ParamsList params ) {
// get the cache
Map cache = (Map) consCache.get( clazz );
if ( cache == null )
consCache.put( clazz, cache = new HashMap() );
// look up in the cache
Constructor c = (Constructor) cache.get( params );
if ( c != null )
return c;
// get index
Map index = (Map) consIndex.get( clazz );
if ( index == null ) {
consIndex.put( clazz, index = new HashMap() );
Constructor[] cons = clazz.getConstructors();
for ( int i=0; i<cons.length; i++ ) {
Constructor con = cons[i];
Integer n = Integer.valueOf( con.getParameterTypes().length );
List list = (List) index.get(n);
if ( list == null )
index.put( n, list = new ArrayList() );
list.add( con );
}
}
// figure out best list of arguments == supplied args
Integer n = Integer.valueOf( params.classes.length );
List list = (List) index.get(n);
if ( list == null )
throw new IllegalArgumentException("no constructor with "+n+" args");
// find constructor with best score
int bests = Integer.MAX_VALUE;
int besti = 0;
for ( int i=0, size=list.size(); i<size; i++ ) {
Constructor con = (Constructor) list.get(i);
int s = CoerceLuaToJava.scoreParamTypes(params.values, con.getParameterTypes());
if ( s < bests ) {
bests = s;
besti = i;
}
}
// put into cache
c = (Constructor) list.get(besti);
cache.put( params, c );
return c;
}
private static Map methCache =
new HashMap();
private static Map methIndex =
new HashMap();
private static Method resolveMethod(Class clazz, String methodName, ParamsList params ) {
// get the cache
Map nameCache = (Map) methCache.get( clazz );
if ( nameCache == null )
methCache.put( clazz, nameCache = new HashMap() );
Map cache = (Map) nameCache.get( methodName );
if ( cache == null )
nameCache.put( methodName, cache = new HashMap() );
// look up in the cache
Method m = (Method) cache.get( params );
if ( m != null )
return m;
// get index
Map index = (Map) methIndex.get( clazz );
if ( index == null ) {
methIndex.put( clazz, index = new HashMap() );
Method[] meths = clazz.getMethods();
for ( int i=0; i<meths.length; i++ ) {
Method meth = meths[i];
String s = meth.getName();
Integer n = Integer.valueOf(meth.getParameterTypes().length);
Map map = (Map) index.get(s);
if ( map == null )
index.put( s, map = new HashMap() );
List list = (List) map.get(n);
if ( list == null )
map.put( n, list = new ArrayList() );
list.add( meth );
}
}
// figure out best list of arguments == supplied args
Map map = (Map) index.get(methodName);
if ( map == null )
throw new IllegalArgumentException("no method named '"+methodName+"'");
Integer n = Integer.valueOf( params.classes.length );
List list = (List) map.get(n);
if ( list == null )
throw new IllegalArgumentException("no method named '"+methodName+"' with "+n+" args");
// find constructor with best score
int bests = Integer.MAX_VALUE;
int besti = 0;
for ( int i=0, size=list.size(); i<size; i++ ) {
Method meth = (Method) list.get(i);
int s = CoerceLuaToJava.scoreParamTypes(params.values, meth.getParameterTypes());
if ( s < bests ) {
bests = s;
besti = i;
}
}
// put into cache
m = (Method) list.get(besti);
cache.put( params, m );
return m;
}
}