Added missed Classes

This commit is contained in:
UnlegitDqrk
2026-03-01 12:57:18 +01:00
parent 405fd633fd
commit ba3d1d8ef9
43 changed files with 9482 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaUserdata;
import org.luaj.vm2.LuaValue;
/**
* Helper class to coerce values from Java to lua within the luajava library.
* <p>
* This class is primarily used by the {@link LuajavaLib},
* but can also be used directly when working with Java/lua bindings.
* <p>
* To coerce scalar types, the various, generally the {@code valueOf(type)} methods
* on {@link LuaValue} may be used:
* <ul>
* <li>{@link LuaValue#valueOf(boolean)}</li>
* <li>{@link LuaValue#valueOf(byte[])}</li>
* <li>{@link LuaValue#valueOf(double)}</li>
* <li>{@link LuaValue#valueOf(int)}</li>
* <li>{@link LuaValue#valueOf(String)}</li>
* </ul>
* <p>
* To coerce arrays of objects and lists, the {@code listOf(..)} and {@code tableOf(...)} methods
* on {@link LuaValue} may be used:
* <ul>
* <li>{@link LuaValue#listOf(LuaValue[])}</li>
* <li>{@link LuaValue#listOf(LuaValue[], org.luaj.vm2.Varargs)}</li>
* <li>{@link LuaValue#tableOf(LuaValue[])}</li>
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[], org.luaj.vm2.Varargs)}</li>
* </ul>
* The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and dimesioning
* of the argument and tries to guess the best fit for corrsponding lua scalar,
* table, or table of tables.
*
* @see CoerceJavaToLua#coerce(Object)
* @see LuajavaLib
*/
public class CoerceJavaToLua {
static interface Coercion {
public LuaValue coerce( Object javaValue );
};
private static final class BoolCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
Boolean b = (Boolean) javaValue;
return b.booleanValue()? LuaValue.TRUE: LuaValue.FALSE;
}
}
private static final class IntCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return LuaInteger.valueOf( n.intValue() );
}
}
private static final class CharCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
Character c = (Character) javaValue;
return LuaInteger.valueOf( c.charValue() );
}
}
private static final class DoubleCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
Number n = (Number) javaValue;
return LuaDouble.valueOf( n.doubleValue() );
}
}
private static final class StringCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
return LuaString.valueOf( javaValue.toString() );
}
}
private static final class BytesCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
return LuaValue.valueOf((byte[]) javaValue);
}
}
private static final class ClassCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
return JavaClass.forClass((Class) javaValue);
}
}
private static final class InstanceCoercion implements Coercion {
public LuaValue coerce(Object javaValue) {
return new JavaInstance(javaValue);
}
}
private static final class ArrayCoercion implements Coercion {
public LuaValue coerce(Object javaValue) {
// should be userdata?
return new JavaArray(javaValue);
}
}
private static final class LuaCoercion implements Coercion {
public LuaValue coerce( Object javaValue ) {
return (LuaValue) javaValue;
}
}
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
static {
Coercion boolCoercion = new BoolCoercion() ;
Coercion intCoercion = new IntCoercion() ;
Coercion charCoercion = new CharCoercion() ;
Coercion doubleCoercion = new DoubleCoercion() ;
Coercion stringCoercion = new StringCoercion() ;
Coercion bytesCoercion = new BytesCoercion() ;
Coercion classCoercion = new ClassCoercion() ;
COERCIONS.put( Boolean.class, boolCoercion );
COERCIONS.put( Byte.class, intCoercion );
COERCIONS.put( Character.class, charCoercion );
COERCIONS.put( Short.class, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Long.class, doubleCoercion );
COERCIONS.put( Float.class, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
COERCIONS.put( byte[].class, bytesCoercion );
COERCIONS.put( Class.class, classCoercion );
}
/**
* Coerse a Java object to a corresponding lua value.
* <p>
* Integral types {@code boolean}, {@code byte}, {@code char}, and {@code int}
* will become {@link LuaInteger};
* {@code long}, {@code float}, and {@code double} will become {@link LuaDouble};
* {@code String} and {@code byte[]} will become {@link LuaString};
* types inheriting from {@link LuaValue} will be returned without coercion;
* other types will become {@link LuaUserdata}.
* @param o Java object needing conversion
* @return {@link LuaValue} corresponding to the supplied Java value.
* @see LuaValue
* @see LuaInteger
* @see LuaDouble
* @see LuaString
* @see LuaUserdata
*/
public static LuaValue coerce(Object o) {
if ( o == null )
return LuaValue.NIL;
Class clazz = o.getClass();
Coercion c = (Coercion) COERCIONS.get( clazz );
if ( c == null ) {
c = clazz.isArray()? arrayCoercion:
o instanceof LuaValue ? luaCoercion:
instanceCoercion;
COERCIONS.put( clazz, c );
}
return c.coerce(o);
}
static final Coercion instanceCoercion = new InstanceCoercion();
static final Coercion arrayCoercion = new ArrayCoercion();
static final Coercion luaCoercion = new LuaCoercion() ;
}

View File

@@ -0,0 +1,372 @@
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.Array;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
/**
* Helper class to coerce values from lua to Java within the luajava library.
* <p>
* This class is primarily used by the {@link LuajavaLib},
* but can also be used directly when working with Java/lua bindings.
* <p>
* To coerce to specific Java values, generally the {@code toType()} methods
* on {@link LuaValue} may be used:
* <ul>
* <li>{@link LuaValue#toboolean()}</li>
* <li>{@link LuaValue#tobyte()}</li>
* <li>{@link LuaValue#tochar()}</li>
* <li>{@link LuaValue#toshort()}</li>
* <li>{@link LuaValue#toint()}</li>
* <li>{@link LuaValue#tofloat()}</li>
* <li>{@link LuaValue#todouble()}</li>
* <li>{@link LuaValue#tojstring()}</li>
* <li>{@link LuaValue#touserdata()}</li>
* <li>{@link LuaValue#touserdata(Class)}</li>
* </ul>
* <p>
* For data in lua tables, the various methods on {@link LuaTable} can be used directly
* to convert data to something more useful.
*
* @see LuajavaLib
* @see CoerceJavaToLua
*/
public class CoerceLuaToJava {
static int SCORE_NULL_VALUE = 0x10;
static int SCORE_WRONG_TYPE = 0x100;
static int SCORE_UNCOERCIBLE = 0x10000;
static interface Coercion {
public int score( LuaValue value );
public Object coerce( LuaValue value );
};
/**
* Coerce a LuaValue value to a specified java class
* @param value LuaValue to coerce
* @param clazz Class to coerce into
* @return Object of type clazz (or a subclass) with the corresponding value.
*/
public static Object coerce(LuaValue value, Class clazz) {
return getCoercion(clazz).coerce(value);
}
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
static final class BoolCoercion implements Coercion {
public String toString() {
return "BoolCoercion()";
}
public int score( LuaValue value ) {
switch ( value.type() ) {
case LuaValue.TBOOLEAN:
return 0;
}
return 1;
}
public Object coerce(LuaValue value) {
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
}
}
static final class NumericCoercion implements Coercion {
static final int TARGET_TYPE_BYTE = 0;
static final int TARGET_TYPE_CHAR = 1;
static final int TARGET_TYPE_SHORT = 2;
static final int TARGET_TYPE_INT = 3;
static final int TARGET_TYPE_LONG = 4;
static final int TARGET_TYPE_FLOAT = 5;
static final int TARGET_TYPE_DOUBLE = 6;
static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" };
final int targetType;
public String toString() {
return "NumericCoercion("+TYPE_NAMES[targetType]+")";
}
NumericCoercion(int targetType) {
this.targetType = targetType;
}
public int score( LuaValue value ) {
int fromStringPenalty = 0;
if ( value.type() == LuaValue.TSTRING ) {
value = value.tonumber();
if ( value.isnil() ) {
return SCORE_UNCOERCIBLE;
}
fromStringPenalty = 4;
}
if ( value.isint() ) {
switch ( targetType ) {
case TARGET_TYPE_BYTE: {
int i = value.toint();
return fromStringPenalty + ((i==(byte)i)? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_CHAR: {
int i = value.toint();
return fromStringPenalty + ((i==(byte)i)? 1: (i==(char)i)? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_SHORT: {
int i = value.toint();
return fromStringPenalty +
((i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_INT: {
int i = value.toint();
return fromStringPenalty +
((i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0);
}
case TARGET_TYPE_FLOAT: return fromStringPenalty + 1;
case TARGET_TYPE_LONG: return fromStringPenalty + 1;
case TARGET_TYPE_DOUBLE: return fromStringPenalty + 2;
default: return SCORE_WRONG_TYPE;
}
} else if ( value.isnumber() ) {
switch ( targetType ) {
case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE;
case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE;
case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE;
case TARGET_TYPE_INT: return SCORE_WRONG_TYPE;
case TARGET_TYPE_LONG: {
double d = value.todouble();
return fromStringPenalty + ((d==(long)d)? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_FLOAT: {
double d = value.todouble();
return fromStringPenalty + ((d==(float)d)? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_DOUBLE: {
double d = value.todouble();
return fromStringPenalty + (((d==(long)d) || (d==(float)d))? 1: 0);
}
default: return SCORE_WRONG_TYPE;
}
} else {
return SCORE_UNCOERCIBLE;
}
}
public Object coerce(LuaValue value) {
switch ( targetType ) {
case TARGET_TYPE_BYTE: return Byte.valueOf( (byte) value.toint() );
case TARGET_TYPE_CHAR: return Character.valueOf( (char) value.toint() );
case TARGET_TYPE_SHORT: return Short.valueOf( (short) value.toint() );
case TARGET_TYPE_INT: return Integer.valueOf( (int) value.toint() );
case TARGET_TYPE_LONG: return Long.valueOf( (long) value.todouble() );
case TARGET_TYPE_FLOAT: return Float.valueOf( (float) value.todouble() );
case TARGET_TYPE_DOUBLE: return Double.valueOf( (double) value.todouble() );
default: return null;
}
}
}
static final class StringCoercion implements Coercion {
public static final int TARGET_TYPE_STRING = 0;
public static final int TARGET_TYPE_BYTES = 1;
final int targetType;
public StringCoercion(int targetType) {
this.targetType = targetType;
}
public String toString() {
return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")";
}
public int score(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TSTRING:
return value.checkstring().isValidUtf8()?
(targetType==TARGET_TYPE_STRING? 0: 1):
(targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE);
case LuaValue.TNIL:
return SCORE_NULL_VALUE;
default:
return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE;
}
}
public Object coerce(LuaValue value) {
if ( value.isnil() )
return null;
if ( targetType == TARGET_TYPE_STRING )
return value.tojstring();
LuaString s = value.checkstring();
byte[] b = new byte[s.m_length];
s.copyInto(0, b, 0, b.length);
return b;
}
}
static final class ArrayCoercion implements Coercion {
final Class componentType;
final Coercion componentCoercion;
public ArrayCoercion(Class componentType) {
this.componentType = componentType;
this.componentCoercion = getCoercion(componentType);
}
public String toString() {
return "ArrayCoercion("+componentType.getName()+")";
}
public int score(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TTABLE:
return value.length()==0? 0: componentCoercion.score( value.get(1) );
case LuaValue.TUSERDATA:
return inheritanceLevels( componentType, value.touserdata().getClass().getComponentType() );
case LuaValue.TNIL:
return SCORE_NULL_VALUE;
default:
return SCORE_UNCOERCIBLE;
}
}
public Object coerce(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TTABLE: {
int n = value.length();
Object a = Array.newInstance(componentType, n);
for ( int i=0; i<n; i++ )
Array.set(a, i, componentCoercion.coerce(value.get(i+1)));
return a;
}
case LuaValue.TUSERDATA:
return value.touserdata();
case LuaValue.TNIL:
return null;
default:
return null;
}
}
}
/**
* Determine levels of inheritance between a base class and a subclass
* @param baseclass base class to look for
* @param subclass class from which to start looking
* @return number of inheritance levels between subclass and baseclass,
* or SCORE_UNCOERCIBLE if not a subclass
*/
static final int inheritanceLevels( Class baseclass, Class subclass ) {
if ( subclass == null )
return SCORE_UNCOERCIBLE;
if ( baseclass == subclass )
return 0;
int min = Math.min( SCORE_UNCOERCIBLE, inheritanceLevels( baseclass, subclass.getSuperclass() ) + 1 );
Class[] ifaces = subclass.getInterfaces();
for ( int i=0; i<ifaces.length; i++ )
min = Math.min(min, inheritanceLevels(baseclass, ifaces[i]) + 1 );
return min;
}
static final class ObjectCoercion implements Coercion {
final Class targetType;
ObjectCoercion(Class targetType) {
this.targetType = targetType;
}
public String toString() {
return "ObjectCoercion("+targetType.getName()+")";
}
public int score(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TNUMBER:
return inheritanceLevels( targetType, value.isint()? Integer.class: Double.class );
case LuaValue.TBOOLEAN:
return inheritanceLevels( targetType, Boolean.class );
case LuaValue.TSTRING:
return inheritanceLevels( targetType, String.class );
case LuaValue.TUSERDATA:
return inheritanceLevels( targetType, value.touserdata().getClass() );
case LuaValue.TNIL:
return SCORE_NULL_VALUE;
default:
return inheritanceLevels( targetType, value.getClass() );
}
}
public Object coerce(LuaValue value) {
switch ( value.type() ) {
case LuaValue.TNUMBER:
return value.isint()? (Object) Integer.valueOf(value.toint()): (Object) Double.valueOf(value.todouble());
case LuaValue.TBOOLEAN:
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
case LuaValue.TSTRING:
return value.tojstring();
case LuaValue.TUSERDATA:
return value.optuserdata(targetType, null);
case LuaValue.TNIL:
return null;
default:
return value;
}
}
}
static {
Coercion boolCoercion = new BoolCoercion();
Coercion byteCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_BYTE);
Coercion charCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_CHAR);
Coercion shortCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_SHORT);
Coercion intCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_INT);
Coercion longCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_LONG);
Coercion floatCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_FLOAT);
Coercion doubleCoercion = new NumericCoercion(NumericCoercion.TARGET_TYPE_DOUBLE);
Coercion stringCoercion = new StringCoercion(StringCoercion.TARGET_TYPE_STRING);
Coercion bytesCoercion = new StringCoercion(StringCoercion.TARGET_TYPE_BYTES);
COERCIONS.put( Boolean.TYPE, boolCoercion );
COERCIONS.put( Boolean.class, boolCoercion );
COERCIONS.put( Byte.TYPE, byteCoercion );
COERCIONS.put( Byte.class, byteCoercion );
COERCIONS.put( Character.TYPE, charCoercion );
COERCIONS.put( Character.class, charCoercion );
COERCIONS.put( Short.TYPE, shortCoercion );
COERCIONS.put( Short.class, shortCoercion );
COERCIONS.put( Integer.TYPE, intCoercion );
COERCIONS.put( Integer.class, intCoercion );
COERCIONS.put( Long.TYPE, longCoercion );
COERCIONS.put( Long.class, longCoercion );
COERCIONS.put( Float.TYPE, floatCoercion );
COERCIONS.put( Float.class, floatCoercion );
COERCIONS.put( Double.TYPE, doubleCoercion );
COERCIONS.put( Double.class, doubleCoercion );
COERCIONS.put( String.class, stringCoercion );
COERCIONS.put( byte[].class, bytesCoercion );
}
static Coercion getCoercion(Class c) {
Coercion co = (Coercion) COERCIONS.get( c );
if ( co != null ) {
return co;
}
if ( c.isArray() ) {
Class typ = c.getComponentType();
co = new ArrayCoercion(c.getComponentType());
} else {
co = new ObjectCoercion(c);
}
COERCIONS.put( c, co );
return co;
}
}

View File

@@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.Array;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaUserdata;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.libs.OneArgFunction;
/**
* LuaValue that represents a Java instance of array type.
* <p>
* Can get elements by their integer key index, as well as the length.
* <p>
* This class is not used directly.
* It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
* when an array is supplied.
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaArray extends LuaUserdata {
private static final class LenFunction extends OneArgFunction {
public LuaValue call(LuaValue u) {
return LuaValue.valueOf(Array.getLength(((LuaUserdata)u).m_instance));
}
}
static final LuaValue LENGTH = valueOf("length");
static final LuaTable array_metatable;
static {
array_metatable = new LuaTable();
array_metatable.rawset(LuaValue.LEN, new LenFunction());
}
JavaArray(Object instance) {
super(instance);
setmetatable(array_metatable);
}
public LuaValue get(LuaValue key) {
if ( key.equals(LENGTH) )
return valueOf(Array.getLength(m_instance));
if ( key.isint() ) {
int i = key.toint() - 1;
return i>=0 && i<Array.getLength(m_instance)?
CoerceJavaToLua.coerce(Array.get(m_instance,key.toint()-1)):
NIL;
}
return super.get(key);
}
public void set(LuaValue key, LuaValue value) {
if ( key.isint() ) {
int i = key.toint() - 1;
if ( i>=0 && i<Array.getLength(m_instance) )
Array.set(m_instance,i,CoerceLuaToJava.coerce(value, m_instance.getClass().getComponentType()));
else if ( m_metatable==null || ! settable(this,key,value) )
error("array index out of bounds");
}
else
super.set(key, value);
}
}

View File

@@ -0,0 +1,153 @@
/*******************************************************************************
* Copyright (c) 2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.luaj.vm2.LuaValue;
/**
* LuaValue that represents a Java class.
* <p>
* Will respond to get() and set() by returning field values, or java methods.
* <p>
* This class is not used directly.
* It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
* when a Class is supplied.
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
static final Map classes = Collections.synchronizedMap(new HashMap());
static final LuaValue NEW = valueOf("new");
Map fields;
Map methods;
Map innerclasses;
static JavaClass forClass(Class c) {
JavaClass j = (JavaClass) classes.get(c);
if ( j == null )
classes.put( c, j = new JavaClass(c) );
return j;
}
JavaClass(Class c) {
super(c);
this.jclass = this;
}
public LuaValue coerce(Object javaValue) {
return this;
}
Field getField(LuaValue key) {
if ( fields == null ) {
Map m = new HashMap();
Field[] f = ((Class)m_instance).getFields();
for ( int i=0; i<f.length; i++ ) {
Field fi = f[i];
if ( Modifier.isPublic(fi.getModifiers()) ) {
m.put(LuaValue.valueOf(fi.getName()), fi);
try {
if (!fi.isAccessible())
fi.setAccessible(true);
} catch (SecurityException s) {
}
}
}
fields = m;
}
return (Field) fields.get(key);
}
LuaValue getMethod(LuaValue key) {
if ( methods == null ) {
Map namedlists = new HashMap();
Method[] m = ((Class)m_instance).getMethods();
for ( int i=0; i<m.length; i++ ) {
Method mi = m[i];
if ( Modifier.isPublic( mi.getModifiers()) ) {
String name = mi.getName();
List list = (List) namedlists.get(name);
if ( list == null )
namedlists.put(name, list = new ArrayList());
list.add( JavaMethod.forMethod(mi) );
}
}
Map map = new HashMap();
Constructor[] c = ((Class)m_instance).getConstructors();
List list = new ArrayList();
for ( int i=0; i<c.length; i++ )
if ( Modifier.isPublic(c[i].getModifiers()) )
list.add( JavaConstructor.forConstructor(c[i]) );
switch ( list.size() ) {
case 0: break;
case 1: map.put(NEW, list.get(0)); break;
default: map.put(NEW, JavaConstructor.forConstructors( (JavaConstructor[])list.toArray(new JavaConstructor[list.size()]) ) ); break;
}
for ( Iterator it=namedlists.entrySet().iterator(); it.hasNext(); ) {
Entry e = (Entry) it.next();
String name = (String) e.getKey();
List methods = (List) e.getValue();
map.put( LuaValue.valueOf(name),
methods.size()==1?
methods.get(0):
JavaMethod.forMethods( (JavaMethod[])methods.toArray(new JavaMethod[methods.size()])) );
}
methods = map;
}
return (LuaValue) methods.get(key);
}
Class getInnerClass(LuaValue key) {
if ( innerclasses == null ) {
Map m = new HashMap();
Class[] c = ((Class)m_instance).getClasses();
for ( int i=0; i<c.length; i++ ) {
Class ci = c[i];
String name = ci.getName();
String stub = name.substring(Math.max(name.lastIndexOf('$'), name.lastIndexOf('.'))+1);
m.put(LuaValue.valueOf(stub), ci);
}
innerclasses = m;
}
return (Class) innerclasses.get(key);
}
public LuaValue getConstructor() {
return getMethod(NEW);
}
}

View File

@@ -0,0 +1,116 @@
/*******************************************************************************
* Copyright (c) 2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.libs.VarArgFunction;
/**
* LuaValue that represents a particular public Java constructor.
* <p>
* May be called with arguments to return a JavaInstance
* created by calling the constructor.
* <p>
* This class is not used directly.
* It is returned by calls to {@link JavaClass#new(LuaValue key)}
* when the value of key is "new".
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaConstructor extends JavaMember {
static final Map constructors = Collections.synchronizedMap(new HashMap());
static JavaConstructor forConstructor(Constructor c) {
JavaConstructor j = (JavaConstructor) constructors.get(c);
if ( j == null )
constructors.put( c, j = new JavaConstructor(c) );
return j;
}
public static LuaValue forConstructors(JavaConstructor[] array) {
return new Overload(array);
}
final Constructor constructor;
private JavaConstructor(Constructor c) {
super( c.getParameterTypes(), c.getModifiers() );
this.constructor = c;
}
public Varargs invoke(Varargs args) {
Object[] a = convertArgs(args);
try {
return CoerceJavaToLua.coerce( constructor.newInstance(a) );
} catch (InvocationTargetException e) {
throw new LuaError(e.getTargetException());
} catch (Exception e) {
return LuaValue.error("coercion error "+e);
}
}
/**
* LuaValue that represents an overloaded Java constructor.
* <p>
* On invocation, will pick the best method from the list, and invoke it.
* <p>
* This class is not used directly.
* It is returned by calls to calls to {@link JavaClass#get(LuaValue key)}
* when key is "new" and there is more than one public constructor.
*/
static class Overload extends VarArgFunction {
final JavaConstructor[] constructors;
public Overload(JavaConstructor[] c) {
this.constructors = c;
}
public Varargs invoke(Varargs args) {
JavaConstructor best = null;
int score = CoerceLuaToJava.SCORE_UNCOERCIBLE;
for ( int i=0; i<constructors.length; i++ ) {
int s = constructors[i].score(args);
if ( s < score ) {
score = s;
best = constructors[i];
if ( score == 0 )
break;
}
}
// any match?
if ( best == null )
LuaValue.error("no coercible public method");
// invoke it
return best.invoke(args);
}
}
}

View File

@@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright (c) 2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.Field;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaUserdata;
import org.luaj.vm2.LuaValue;
/**
* LuaValue that represents a Java instance.
* <p>
* Will respond to get() and set() by returning field values or methods.
* <p>
* This class is not used directly.
* It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
* when a subclass of Object is supplied.
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaInstance extends LuaUserdata {
JavaClass jclass;
JavaInstance(Object instance) {
super(instance);
}
public LuaValue get(LuaValue key) {
if ( jclass == null )
jclass = JavaClass.forClass(m_instance.getClass());
Field f = jclass.getField(key);
if ( f != null )
try {
return CoerceJavaToLua.coerce(f.get(m_instance));
} catch (Exception e) {
throw new LuaError(e);
}
LuaValue m = jclass.getMethod(key);
if ( m != null )
return m;
Class c = jclass.getInnerClass(key);
if ( c != null )
return JavaClass.forClass(c);
return super.get(key);
}
public void set(LuaValue key, LuaValue value) {
if ( jclass == null )
jclass = JavaClass.forClass(m_instance.getClass());
Field f = jclass.getField(key);
if ( f != null )
try {
f.set(m_instance, CoerceLuaToJava.coerce(value, f.getType()));
return;
} catch (Exception e) {
throw new LuaError(e);
}
super.set(key, value);
}
}

View File

@@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright (c) 2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.libs.VarArgFunction;
import org.luaj.vm2.libs.jse.CoerceLuaToJava.Coercion;
/**
* Java method or constructor.
* <p>
* Primarily handles argument coercion for parameter lists including scoring of compatibility and
* java varargs handling.
* <p>
* This class is not used directly.
* It is an abstract base class for {@link JavaConstructor} and {@link JavaMethod}.
* @see JavaConstructor
* @see JavaMethod
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
abstract
class JavaMember extends VarArgFunction {
static final int METHOD_MODIFIERS_VARARGS = 0x80;
final Coercion[] fixedargs;
final Coercion varargs;
protected JavaMember(Class[] params, int modifiers) {
boolean isvarargs = ((modifiers & METHOD_MODIFIERS_VARARGS) != 0);
fixedargs = new Coercion[isvarargs? params.length-1: params.length];
for ( int i=0; i<fixedargs.length; i++ )
fixedargs[i] = CoerceLuaToJava.getCoercion( params[i] );
varargs = isvarargs? CoerceLuaToJava.getCoercion( params[params.length-1] ): null;
}
int score(Varargs args) {
int n = args.narg();
int s = n>fixedargs.length? CoerceLuaToJava.SCORE_WRONG_TYPE * (n-fixedargs.length): 0;
for ( int j=0; j<fixedargs.length; j++ )
s += fixedargs[j].score( args.arg(j+1) );
if ( varargs != null )
for ( int k=fixedargs.length; k<n; k++ )
s += varargs.score( args.arg(k+1) );
return s;
}
protected Object[] convertArgs(Varargs args) {
Object[] a;
if ( varargs == null ) {
a = new Object[fixedargs.length];
for ( int i=0; i<a.length; i++ )
a[i] = fixedargs[i].coerce( args.arg(i+1) );
} else {
int n = Math.max(fixedargs.length,args.narg());
a = new Object[n];
for ( int i=0; i<fixedargs.length; i++ )
a[i] = fixedargs[i].coerce( args.arg(i+1) );
for ( int i=fixedargs.length; i<n; i++ )
a[i] = varargs.coerce( args.arg(i+1) );
}
return a;
}
}

View File

@@ -0,0 +1,163 @@
/*******************************************************************************
* Copyright (c) 2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
* LuaValue that represents a Java method.
* <p>
* Can be invoked via call(LuaValue...) and related methods.
* <p>
* This class is not used directly.
* It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)}
* when a method is named.
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaMethod extends JavaMember {
static final Map methods = Collections.synchronizedMap(new HashMap());
static JavaMethod forMethod(Method m) {
JavaMethod j = (JavaMethod) methods.get(m);
if ( j == null )
methods.put( m, j = new JavaMethod(m) );
return j;
}
static LuaFunction forMethods(JavaMethod[] m) {
return new Overload(m);
}
final Method method;
private JavaMethod(Method m) {
super( m.getParameterTypes(), m.getModifiers() );
this.method = m;
try {
if (!m.isAccessible())
m.setAccessible(true);
} catch (SecurityException s) {
}
}
public LuaValue call() {
return error("method cannot be called without instance");
}
public LuaValue call(LuaValue arg) {
return invokeMethod(arg.checkuserdata(), LuaValue.NONE);
}
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return invokeMethod(arg1.checkuserdata(), arg2);
}
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return invokeMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3));
}
public Varargs invoke(Varargs args) {
return invokeMethod(args.checkuserdata(1), args.subargs(2));
}
LuaValue invokeMethod(Object instance, Varargs args) {
Object[] a = convertArgs(args);
try {
return CoerceJavaToLua.coerce( method.invoke(instance, a) );
} catch (InvocationTargetException e) {
throw new LuaError(e.getTargetException());
} catch (Exception e) {
return LuaValue.error("coercion error "+e);
}
}
/**
* LuaValue that represents an overloaded Java method.
* <p>
* On invocation, will pick the best method from the list, and invoke it.
* <p>
* This class is not used directly.
* It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)}
* when an overloaded method is named.
*/
static class Overload extends LuaFunction {
final JavaMethod[] methods;
Overload(JavaMethod[] methods) {
this.methods = methods;
}
public LuaValue call() {
return error("method cannot be called without instance");
}
public LuaValue call(LuaValue arg) {
return invokeBestMethod(arg.checkuserdata(), LuaValue.NONE);
}
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return invokeBestMethod(arg1.checkuserdata(), arg2);
}
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return invokeBestMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3));
}
public Varargs invoke(Varargs args) {
return invokeBestMethod(args.checkuserdata(1), args.subargs(2));
}
private LuaValue invokeBestMethod(Object instance, Varargs args) {
JavaMethod best = null;
int score = CoerceLuaToJava.SCORE_UNCOERCIBLE;
for ( int i=0; i<methods.length; i++ ) {
int s = methods[i].score(args);
if ( s < score ) {
score = s;
best = methods[i];
if ( score == 0 )
break;
}
}
// any match?
if ( best == null )
LuaValue.error("no coercible public method");
// invoke it
return best.invokeMethod(instance, args);
}
}
}

View File

@@ -0,0 +1,116 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.libs.BaseLib;
import org.luaj.vm2.libs.LibFunction;
import org.luaj.vm2.libs.ResourceFinder;
/**
* Subclass of {@link BaseLib} and {@link LibFunction} which implements the lua basic library functions
* and provides a directory based {@link ResourceFinder} as the {@link Globals#finder}.
* <p>
* Since JME has no file system by default, {@link BaseLib} implements
* {@link ResourceFinder} using {@link Class#getResource(String)}.
* The {@link JseBaseLib} implements {@link Globals#finder} by scanning the current directory
* first, then falling back to {@link Class#getResource(String)} if that fails.
* Otherwise, the behavior is the same as that of {@link BaseLib}.
* <p>
* Typically, this library is included as part of a call to
* {@link JsePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* globals.get("print").call(LuaValue.valueOf("hello, world"));
* } </pre>
* <p>
* For special cases where the smallest possible footprint is desired,
* a minimal set of libraries could be loaded
* directly via {@link Globals#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.get("print").call(LuaValue.valueOf("hello, world"));
* } </pre>
* <p>However, other libraries such as <em>PackageLib</em> are not loaded in this case.
* <p>
* This is a direct port of the corresponding library in C.
* @see Globals
* @see BaseLib
* @see ResourceFinder
* @see Globals#finder
* @see LibFunction
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.1">Lua 5.2 Base Lib Reference</a>
*/
public class JseBaseLib extends BaseLib {
/** Perform one-time initialization on the library by creating a table
* containing the library functions, adding that table to the supplied environment,
* adding the table to package.loaded, and returning table as the return value.
* <P>Specifically, extend the library loading to set the default value for {@link Globals#STDIN}
* @param modname the module name supplied if this is loaded via 'require'.
* @param env the environment to load into, which must be a Globals instance.
*/
public LuaValue call(LuaValue modname, LuaValue env) {
super.call(modname, env);
env.checkglobals().STDIN = System.in;
return env;
}
/**
* Try to open a file in the current working directory,
* or fall back to base opener if not found.
*
* This implementation attempts to open the file using new File(filename).
* It falls back to the base implementation that looks it up as a resource
* in the class path if not found as a plain file.
*
* @see BaseLib
* @see ResourceFinder
*
* @param filename
* @return InputStream, or null if not found.
*/
public InputStream findResource(String filename) {
File f = new File(filename);
if ( ! f.exists() )
return super.findResource(filename);
try {
return new BufferedInputStream(new FileInputStream(f));
} catch ( IOException ioe ) {
return null;
}
}
}

View File

@@ -0,0 +1,343 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.libs.IoLib;
import org.luaj.vm2.libs.LibFunction;
/**
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}
* library for the JSE platform.
* <p>
* It uses RandomAccessFile to implement seek on files.
* <p>
* Typically, this library is included as part of a call to
* {@link JsePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
* } </pre>
* <p>
* For special cases where the smallest possible footprint is desired,
* a minimal set of libraries could be loaded
* directly via {@link Globals#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.load(new PackageLib());
* globals.load(new JseIoLib());
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
* } </pre>
* <p>However, other libraries such as <em>MathLib</em> are not loaded in this case.
* <p>
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
* @see LibFunction
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see IoLib
* @see org.luaj.vm2.libs.jme.JmeIoLib
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.8">Lua 5.2 I/O Lib Reference</a>
*/
public class JseIoLib extends IoLib {
protected File wrapStdin() throws IOException {
return new StdinFile();
}
protected File wrapStdout() throws IOException {
return new StdoutFile(FTYPE_STDOUT);
}
protected File wrapStderr() throws IOException {
return new StdoutFile(FTYPE_STDERR);
}
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw");
if ( appendMode ) {
f.seek(f.length());
} else {
if ( ! readMode )
f.setLength(0);
}
return new FileImpl( f );
}
protected File openProgram(String prog, String mode) throws IOException {
final Process p = Runtime.getRuntime().exec(prog);
return "w".equals(mode)?
new FileImpl( p.getOutputStream() ):
new FileImpl( p.getInputStream() );
}
protected File tmpFile() throws IOException {
java.io.File f = java.io.File.createTempFile(".luaj","bin");
f.deleteOnExit();
return new FileImpl( new RandomAccessFile(f,"rw") );
}
private static void notimplemented() {
throw new LuaError("not implemented");
}
private final class FileImpl extends File {
private final RandomAccessFile file;
private final InputStream is;
private final OutputStream os;
private boolean closed = false;
private boolean nobuffer = false;
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) {
this.file = file;
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
this.os = os;
}
private FileImpl( RandomAccessFile f ) {
this( f, null, null );
}
private FileImpl( InputStream i ) {
this( null, i, null );
}
private FileImpl( OutputStream o ) {
this( null, null, o );
}
public String tojstring() {
return "file (" + (this.closed ? "closed" : String.valueOf(this.hashCode())) + ")";
}
public boolean isstdfile() {
return file == null;
}
public void close() throws IOException {
closed = true;
if ( file != null ) {
file.close();
}
}
public void flush() throws IOException {
if ( os != null )
os.flush();
}
public void write(LuaString s) throws IOException {
if ( os != null )
os.write( s.m_bytes, s.m_offset, s.m_length );
else if ( file != null )
file.write( s.m_bytes, s.m_offset, s.m_length );
else
notimplemented();
if ( nobuffer )
flush();
}
public boolean isclosed() {
return closed;
}
public int seek(String option, int pos) throws IOException {
if ( file != null ) {
if ( "set".equals(option) ) {
file.seek(pos);
} else if ( "end".equals(option) ) {
file.seek(file.length()+pos);
} else {
file.seek(file.getFilePointer()+pos);
}
return (int) file.getFilePointer();
}
notimplemented();
return 0;
}
public void setvbuf(String mode, int size) {
nobuffer = "no".equals(mode);
}
// get length remaining to read
public int remaining() throws IOException {
return file!=null? (int) (file.length()-file.getFilePointer()): -1;
}
// peek ahead one character
public int peek() throws IOException {
if ( is != null ) {
is.mark(1);
int c = is.read();
is.reset();
return c;
} else if ( file != null ) {
long fp = file.getFilePointer();
int c = file.read();
file.seek(fp);
return c;
}
notimplemented();
return 0;
}
// return char if read, -1 if eof, throw IOException on other exception
public int read() throws IOException {
if ( is != null )
return is.read();
else if ( file != null ) {
return file.read();
}
notimplemented();
return 0;
}
// return number of bytes read if positive, -1 if eof, throws IOException
public int read(byte[] bytes, int offset, int length) throws IOException {
if (file!=null) {
return file.read(bytes, offset, length);
} else if (is!=null) {
return is.read(bytes, offset, length);
} else {
notimplemented();
}
return length;
}
}
private final class StdoutFile extends File {
private final int file_type;
private StdoutFile(int file_type) {
this.file_type = file_type;
}
public String tojstring() {
return "file ("+this.hashCode()+")";
}
private final PrintStream getPrintStream() {
return file_type == FTYPE_STDERR?
globals.STDERR:
globals.STDOUT;
}
public void write(LuaString string) throws IOException {
getPrintStream().write(string.m_bytes, string.m_offset, string.m_length);
}
public void flush() throws IOException {
getPrintStream().flush();
}
public boolean isstdfile() {
return true;
}
public void close() throws IOException {
// do not close std files.
}
public boolean isclosed() {
return false;
}
public int seek(String option, int bytecount) throws IOException {
return 0;
}
public void setvbuf(String mode, int size) {
}
public int remaining() throws IOException {
return 0;
}
public int peek() throws IOException, EOFException {
return 0;
}
public int read() throws IOException, EOFException {
return 0;
}
public int read(byte[] bytes, int offset, int length)
throws IOException {
return 0;
}
}
private final class StdinFile extends File {
private StdinFile() {
}
public String tojstring() {
return "file ("+this.hashCode()+")";
}
public void write(LuaString string) throws IOException {
}
public void flush() throws IOException {
}
public boolean isstdfile() {
return true;
}
public void close() throws IOException {
// do not close std files.
}
public boolean isclosed() {
return false;
}
public int seek(String option, int bytecount) throws IOException {
return 0;
}
public void setvbuf(String mode, int size) {
}
public int remaining() throws IOException {
return -1;
}
public int peek() throws IOException, EOFException {
globals.STDIN.mark(1);
int c = globals.STDIN.read();
globals.STDIN.reset();
return c;
}
public int read() throws IOException, EOFException {
return globals.STDIN.read();
}
public int read(byte[] bytes, int offset, int length)
throws IOException {
return globals.STDIN.read(bytes, offset, length);
}
}
}

View File

@@ -0,0 +1,120 @@
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.libs.LibFunction;
import org.luaj.vm2.libs.TwoArgFunction;
/**
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
* library.
* <p>
* It contains all lua math functions, including those not available on the JME platform.
* See {@link org.luaj.vm2.libs.MathLib} for the exception list.
* <p>
* Typically, this library is included as part of a call to
* {@link JsePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
* } </pre>
* <p>
* For special cases where the smallest possible footprint is desired,
* a minimal set of libraries could be loaded
* directly via {@link Globals#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.load(new PackageLib());
* globals.load(new JseMathLib());
* System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
* } </pre>
* <p>However, other libraries such as <em>CoroutineLib</em> are not loaded in this case.
* <p>
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
* @see LibFunction
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see JseMathLib
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.6">Lua 5.2 Math Lib Reference</a>
*/
public class JseMathLib extends org.luaj.vm2.libs.MathLib {
public JseMathLib() {}
/** Perform one-time initialization on the library by creating a table
* containing the library functions, adding that table to the supplied environment,
* adding the table to package.loaded, and returning table as the return value.
* <P>Specifically, adds all library functions that can be implemented directly
* in JSE but not JME: acos, asin, atan, atan2, cosh, exp, log, pow, sinh, and tanh.
* @param modname the module name supplied if this is loaded via 'require'.
* @param env the environment to load into, which must be a Globals instance.
*/
public LuaValue call(LuaValue modname, LuaValue env) {
super.call(modname, env);
LuaValue math = env.get("math");
math.set("acos", new acos());
math.set("asin", new asin());
LuaValue atan = new atan2();
math.set("atan", atan);
math.set("atan2", atan);
math.set("cosh", new cosh());
math.set("exp", new exp());
math.set("log", new log());
math.set("pow", new pow());
math.set("sinh", new sinh());
math.set("tanh", new tanh());
return math;
}
static final class acos extends UnaryOp { protected double call(double d) { return Math.acos(d); } }
static final class asin extends UnaryOp { protected double call(double d) { return Math.asin(d); } }
static final class atan2 extends TwoArgFunction {
public LuaValue call(LuaValue x, LuaValue y) {
return valueOf(Math.atan2(x.checkdouble(), y.optdouble(1)));
}
}
static final class cosh extends UnaryOp { protected double call(double d) { return Math.cosh(d); } }
static final class exp extends UnaryOp { protected double call(double d) { return Math.exp(d); } }
static final class log extends TwoArgFunction {
public LuaValue call(LuaValue x, LuaValue base) {
double nat = Math.log(x.checkdouble());
double b = base.optdouble(Math.E);
if (b != Math.E) nat /= Math.log(b);
return valueOf(nat);
}
}
static final class pow extends BinaryOp { protected double call(double x, double y) { return Math.pow(x, y); } }
static final class sinh extends UnaryOp { protected double call(double d) { return Math.sinh(d); } }
static final class tanh extends UnaryOp { protected double call(double d) { return Math.tanh(d); } }
/** Faster, better version of pow() used by arithmetic operator ^ */
public double dpow_lib(double a, double b) {
return Math.pow(a, b);
}
}

View File

@@ -0,0 +1,135 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.io.File;
import java.io.IOException;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.libs.LibFunction;
import org.luaj.vm2.libs.OsLib;
/**
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
* <p>
* This contains more complete implementations of the following functions
* using features that are specific to JSE:
* <ul>
* <li>{@code execute()}</li>
* <li>{@code remove()}</li>
* <li>{@code rename()}</li>
* <li>{@code tmpname()}</li>
* </ul>
* <p>
* Because the nature of the {@code os} library is to encapsulate
* os-specific features, the behavior of these functions varies considerably
* from their counterparts in the C platform.
* <p>
* Typically, this library is included as part of a call to
* {@link JsePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("os").get("time").call() );
* } </pre>
* <p>
* For special cases where the smallest possible footprint is desired,
* a minimal set of libraries could be loaded
* directly via {@link Globals#load(LuaValue)} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.load(new PackageLib());
* globals.load(new JseOsLib());
* System.out.println( globals.get("os").get("time").call() );
* } </pre>
* <p>However, other libraries such as <em>MathLib</em> are not loaded in this case.
* <p>
* @see LibFunction
* @see OsLib
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.9">Lua 5.2 OS Lib Reference</a>
*/
public class JseOsLib extends OsLib {
/** return code indicating the execute() threw an I/O exception */
public static final int EXEC_IOEXCEPTION = 1;
/** return code indicating the execute() was interrupted */
public static final int EXEC_INTERRUPTED = -2;
/** return code indicating the execute() threw an unknown exception */
public static final int EXEC_ERROR = -3;
/** public constructor */
public JseOsLib() {
}
protected String getenv(String varname) {
String s = System.getenv(varname);
return s != null? s : System.getProperty(varname);
}
protected Varargs execute(String command) {
int exitValue;
try {
exitValue = new JseProcess(command, null, globals.STDOUT, globals.STDERR).waitFor();
} catch (IOException ioe) {
exitValue = EXEC_IOEXCEPTION;
} catch (InterruptedException e) {
exitValue = EXEC_INTERRUPTED;
} catch (Throwable t) {
exitValue = EXEC_ERROR;
}
if (exitValue == 0)
return varargsOf(TRUE, valueOf("exit"), ZERO);
return varargsOf(NIL, valueOf("signal"), valueOf(exitValue));
}
protected void remove(String filename) throws IOException {
File f = new File(filename);
if ( ! f.exists() )
throw new IOException("No such file or directory");
if ( ! f.delete() )
throw new IOException("Failed to delete");
}
protected void rename(String oldname, String newname) throws IOException {
File f = new File(oldname);
if ( ! f.exists() )
throw new IOException("No such file or directory");
if ( ! f.renameTo(new File(newname)) )
throw new IOException("Failed to rename");
}
protected String tmpname() {
try {
File f = File.createTempFile(TMP_PREFIX ,TMP_SUFFIX);
return f.getAbsolutePath();
} catch ( IOException ioe ) {
return super.tmpname();
}
}
}

View File

@@ -0,0 +1,143 @@
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.libs.Bit32Lib;
import org.luaj.vm2.libs.CoroutineLib;
import org.luaj.vm2.libs.DebugLib;
import org.luaj.vm2.libs.PackageLib;
import org.luaj.vm2.libs.ResourceFinder;
import org.luaj.vm2.libs.StringLib;
import org.luaj.vm2.libs.TableLib;
/** The {@link JsePlatform} class is a convenience class to standardize
* how globals tables are initialized for the JSE platform.
* <p>
* It is used to allocate either a set of standard globals using
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
* <p>
* A simple example of initializing globals and using them from Java is:
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* globals.get("print").call(LuaValue.valueOf("hello, world"));
* } </pre>
* <p>
* Once globals are created, a simple way to load and run a script is:
* <pre> {@code
* globals.load( new FileInputStream("main.lua"), "main.lua" ).call();
* } </pre>
* <p>
* although {@code require} could also be used:
* <pre> {@code
* globals.get("require").call(LuaValue.valueOf("main"));
* } </pre>
* For this to succeed, the file "main.lua" must be in the current directory or a resource.
* See {@link JseBaseLib} for details on finding scripts using {@link ResourceFinder}.
* <p>
* The standard globals will contain all standard libraries plus {@code luajava}:
* <ul>
* <li>{@link Globals}</li>
* <li>{@link JseBaseLib}</li>
* <li>{@link PackageLib}</li>
* <li>{@link Bit32Lib}</li>
* <li>{@link TableLib}</li>
* <li>{@link StringLib}</li>
* <li>{@link CoroutineLib}</li>
* <li>{@link JseMathLib}</li>
* <li>{@link JseIoLib}</li>
* <li>{@link JseOsLib}</li>
* <li>{@link LuajavaLib}</li>
* </ul>
* In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
* <p>
* The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}.
* <p>
* The class ensures that initialization is done in the correct order.
*
* @see Globals
* @see org.luaj.vm2.libs.jme.JmePlatform
*/
public class JsePlatform {
/**
* Create a standard set of globals for JSE including all the libraries.
*
* @return Table of globals initialized with the standard JSE libraries
* @see #debugGlobals()
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
*/
public static Globals standardGlobals() {
Globals globals = new Globals();
globals.load(new JseBaseLib());
globals.load(new PackageLib());
globals.load(new Bit32Lib());
globals.load(new TableLib());
globals.load(new JseStringLib());
globals.load(new CoroutineLib());
globals.load(new JseMathLib());
globals.load(new JseIoLib());
globals.load(new JseOsLib());
globals.load(new LuajavaLib());
LoadState.install(globals);
LuaC.install(globals);
return globals;
}
/** Create standard globals including the {@link DebugLib} library.
*
* @return Table of globals initialized with the standard JSE and debug libraries
* @see #standardGlobals()
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see DebugLib
*/
public static Globals debugGlobals() {
Globals globals = standardGlobals();
globals.load(new DebugLib());
return globals;
}
/** Simple wrapper for invoking a lua function with command line arguments.
* The supplied function is first given a new Globals object as its environment
* then the program is run with arguments.
* @return {@link Varargs} containing any values returned by mainChunk.
*/
public static Varargs luaMain(LuaValue mainChunk, String[] args) {
Globals g = standardGlobals();
int n = args.length;
LuaValue[] vargs = new LuaValue[args.length];
for (int i = 0; i < n; ++i)
vargs[i] = LuaValue.valueOf(args[i]);
LuaValue arg = LuaValue.listOf(vargs);
arg.set("n", n);
g.set("arg", arg);
mainChunk.initupvalue1(g);
return mainChunk.invoke(LuaValue.varargsOf(vargs));
}
}

View File

@@ -0,0 +1,132 @@
/*******************************************************************************
* Copyright (c) 2012 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/** Analog of Process that pipes input and output to client-specified streams.
*/
public class JseProcess {
final Process process;
final Thread input,output,error;
/** Construct a process around a command, with specified streams to redirect input and output to.
*
* @param cmd The command to execute, including arguments, if any
* @param stdin Optional InputStream to read from as process input, or null if input is not needed.
* @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
* @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
* @throws IOException If the system process could not be created.
* @see Process
*/
public JseProcess(String[] cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException {
this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
}
/** Construct a process around a command, with specified streams to redirect input and output to.
*
* @param cmd The command to execute, including arguments, if any
* @param stdin Optional InputStream to read from as process input, or null if input is not needed.
* @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
* @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
* @throws IOException If the system process could not be created.
* @see Process
*/
public JseProcess(String cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException {
this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
}
private JseProcess(Process process, InputStream stdin, OutputStream stdout, OutputStream stderr) {
this.process = process;
input = stdin == null? null: copyBytes(stdin, process.getOutputStream(), null, process.getOutputStream());
output = stdout == null? null: copyBytes(process.getInputStream(), stdout, process.getInputStream(), null);
error = stderr == null? null: copyBytes(process.getErrorStream(), stderr, process.getErrorStream(), null);
}
/** Get the exit value of the process. */
public int exitValue() {
return process.exitValue();
}
/** Wait for the process to complete, and all pending output to finish.
* @return The exit status.
* @throws InterruptedException
*/
public int waitFor() throws InterruptedException {
int r = process.waitFor();
if (input != null)
input.join();
if (output != null)
output.join();
if (error != null)
error.join();
process.destroy();
return r;
}
/** Create a thread to copy bytes from input to output. */
private Thread copyBytes(final InputStream input,
final OutputStream output, final InputStream ownedInput,
final OutputStream ownedOutput) {
Thread t = (new CopyThread(output, ownedOutput, ownedInput, input));
t.start();
return t;
}
private static final class CopyThread extends Thread {
private final OutputStream output;
private final OutputStream ownedOutput;
private final InputStream ownedInput;
private final InputStream input;
private CopyThread(OutputStream output, OutputStream ownedOutput,
InputStream ownedInput, InputStream input) {
this.output = output;
this.ownedOutput = ownedOutput;
this.ownedInput = ownedInput;
this.input = input;
}
public void run() {
try {
byte[] buf = new byte[1024];
int r;
try {
while ((r = input.read(buf)) >= 0) {
output.write(buf, 0, r);
}
} finally {
if (ownedInput != null)
ownedInput.close();
if (ownedOutput != null)
ownedOutput.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
public class JseStringLib extends org.luaj.vm2.libs.StringLib {
/** public constructor */
public JseStringLib() {
}
protected String format(String src, double x) {
String out;
try {
out = String.format(src, new Object[] {Double.valueOf(x)});
} catch (Throwable e) {
out = super.format(src, x);
}
return out;
}
}

View File

@@ -0,0 +1,214 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.libs.jse;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.libs.LibFunction;
import org.luaj.vm2.libs.VarArgFunction;
/**
* Subclass of {@link LibFunction} which implements the features of the luajava package.
* <p>
* Luajava is an approach to mixing lua and java using simple functions that bind
* java classes and methods to lua dynamically. The API is documented on the
* <a href="http://www.keplerproject.org/luajava/">luajava</a> documentation pages.
*
* <p>
* Typically, this library is included as part of a call to
* {@link JsePlatform#standardGlobals()}
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* System.out.println( globals.get("luajava").get("bindClass").call( LuaValue.valueOf("java.lang.System") ).invokeMethod("currentTimeMillis") );
* } </pre>
* <p>
* To instantiate and use it directly,
* link it into your globals table via {@link Globals#load} using code such as:
* <pre> {@code
* Globals globals = new Globals();
* globals.load(new JseBaseLib());
* globals.load(new PackageLib());
* globals.load(new LuajavaLib());
* globals.load(
* "sys = luajava.bindClass('java.lang.System')\n"+
* "print ( sys:currentTimeMillis() )\n", "main.lua" ).call();
* } </pre>
* <p>
*
* The {@code luajava} library is available
* on all JSE platforms via the call to {@link JsePlatform#standardGlobals()}
* and the luajava api's are simply invoked from lua.
* Because it makes extensive use of Java's reflection API, it is not available
* on JME, but can be used in Android applications.
* <p>
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
*
* @see LibFunction
* @see JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see LuaC
* @see CoerceJavaToLua
* @see CoerceLuaToJava
* @see <a href="http://www.keplerproject.org/luajava/manual.html#luareference">http://www.keplerproject.org/luajava/manual.html#luareference</a>
*/
public class LuajavaLib extends VarArgFunction {
static final int INIT = 0;
static final int BINDCLASS = 1;
static final int NEWINSTANCE = 2;
static final int NEW = 3;
static final int CREATEPROXY = 4;
static final int LOADLIB = 5;
static final String[] NAMES = {
"bindClass",
"newInstance",
"new",
"createProxy",
"loadLib",
};
static final int METHOD_MODIFIERS_VARARGS = 0x80;
public LuajavaLib() {
}
public Varargs invoke(Varargs args) {
try {
switch ( opcode ) {
case INIT: {
// LuaValue modname = args.arg1();
LuaValue env = args.arg(2);
LuaTable t = new LuaTable();
bind( t, this.getClass(), NAMES, BINDCLASS );
env.set("luajava", t);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("luajava", t);
return t;
}
case BINDCLASS: {
final Class clazz = classForName(args.checkjstring(1));
return JavaClass.forClass(clazz);
}
case NEWINSTANCE:
case NEW: {
// get constructor
final LuaValue c = args.checkvalue(1);
final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
final Varargs consargs = args.subargs(2);
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
}
case CREATEPROXY: {
final int niface = args.narg()-1;
if ( niface <= 0 )
throw new LuaError("no interfaces");
final LuaValue lobj = args.checktable(niface+1);
// get the interfaces
final Class[] ifaces = new Class[niface];
for ( int i=0; i<niface; i++ )
ifaces[i] = classForName(args.checkjstring(i+1));
// create the invocation handler
InvocationHandler handler = new ProxyInvocationHandler(lobj);
// create the proxy object
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);
// return the proxy
return LuaValue.userdataOf( proxy );
}
case LOADLIB: {
// get constructor
String classname = args.checkjstring(1);
String methodname = args.checkjstring(2);
Class clazz = classForName(classname);
Method method = clazz.getMethod(methodname, new Class[] {});
Object result = method.invoke(clazz, new Object[] {});
if ( result instanceof LuaValue ) {
return (LuaValue) result;
} else {
return NIL;
}
}
default:
throw new LuaError("not yet supported: "+this);
}
} catch (LuaError e) {
throw e;
} catch (InvocationTargetException ite) {
throw new LuaError(ite.getTargetException());
} catch (Exception e) {
throw new LuaError(e);
}
}
// load classes using app loader to allow luaj to be used as an extension
protected Class classForName(String name) throws ClassNotFoundException {
return Class.forName(name, true, ClassLoader.getSystemClassLoader());
}
private static final class ProxyInvocationHandler implements InvocationHandler {
private final LuaValue lobj;
private ProxyInvocationHandler(LuaValue lobj) {
this.lobj = lobj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
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;
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.coerce(result, method.getReturnType());
}
}
}

View File

@@ -0,0 +1,21 @@
package org.luaj.vm2.libs.jse;
import junit.framework.TestCase;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
public class JsePlatformTest extends TestCase {
public void testLuaMainPassesArguments() {
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("return #arg, arg.n, arg[2], arg[1]");
Varargs results = JsePlatform.luaMain(chunk, new String[] { "aaa", "bbb" });
assertEquals(results.narg(), 4);
assertEquals(results.arg(1), LuaValue.valueOf(2));
assertEquals(results.arg(2), LuaValue.valueOf(2));
assertEquals(results.arg(3), LuaValue.valueOf("bbb"));
assertEquals(results.arg(4), LuaValue.valueOf("aaa"));
}
}

View File

@@ -0,0 +1,446 @@
package org.luaj.vm2.libs.jse;
import junit.framework.TestCase;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.libs.jse2.JavaArray;
public class LuaJavaCoercionTest extends TestCase {
private static LuaValue globals;
private static LuaValue ZERO = LuaValue.ZERO;
private static LuaValue ONE = LuaValue.ONE;
private static LuaValue TWO = LuaValue.valueOf(2);
private static LuaValue THREE = LuaValue.valueOf(3);
private static LuaString LENGTH = LuaString.valueOf("length");
protected void setUp() throws Exception {
super.setUp();
globals = JsePlatform.standardGlobals();
}
public void testJavaIntToLuaInt() {
Integer i = Integer.valueOf(777);
LuaValue v = CoerceJavaToLua.coerce(i);
assertEquals( LuaInteger.class, v.getClass() );
assertEquals( 777, v.toint() );
}
public void testLuaIntToJavaInt() {
LuaInteger i = LuaInteger.valueOf(777);
Object o = CoerceLuaToJava.coerce(i, int.class);
assertEquals( Integer.class, o.getClass() );
assertEquals( 777, ((Number)o).intValue() );
o = CoerceLuaToJava.coerce(i, Integer.class);
assertEquals( Integer.class, o.getClass() );
assertEquals( new Integer(777), o );
}
public void testJavaStringToLuaString() {
String s = new String("777");
LuaValue v = CoerceJavaToLua.coerce(s);
assertEquals( LuaString.class, v.getClass() );
assertEquals( "777", v.toString() );
}
public void testLuaStringToJavaString() {
LuaString s = LuaValue.valueOf("777");
Object o = CoerceLuaToJava.coerce(s, String.class);
assertEquals( String.class, o.getClass() );
assertEquals( "777", o );
}
public void testJavaClassToLuaUserdata() {
LuaValue va = CoerceJavaToLua.coerce(ClassA.class);
LuaValue va1 = CoerceJavaToLua.coerce(ClassA.class);
LuaValue vb = CoerceJavaToLua.coerce(ClassB.class);
assertSame(va, va1);
assertNotSame(va, vb);
LuaValue vi = CoerceJavaToLua.coerce(new ClassA());
assertNotSame(va, vi);
assertTrue(vi.isuserdata());
assertTrue(vi.isuserdata(ClassA.class));
assertFalse(vi.isuserdata(ClassB.class));
LuaValue vj = CoerceJavaToLua.coerce(new ClassB());
assertNotSame(vb, vj);
assertTrue(vj.isuserdata());
assertFalse(vj.isuserdata(ClassA.class));
assertTrue(vj.isuserdata(ClassB.class));
}
static class ClassA {
}
static class ClassB {
}
public void testJavaIntArrayToLuaTable() {
int[] i = { 222, 333 };
LuaValue v = CoerceJavaToLua.coerce(i);
assertEquals( JavaArray.class, v.getClass() );
assertEquals( LuaInteger.valueOf(222), v.get(ONE) );
assertEquals( LuaInteger.valueOf(333), v.get(TWO) );
assertEquals( TWO, v.get(LENGTH));
assertEquals( LuaValue.NIL, v.get(THREE) );
assertEquals( LuaValue.NIL, v.get(ZERO) );
v.set(ONE, LuaInteger.valueOf(444));
v.set(TWO, LuaInteger.valueOf(555));
assertEquals( 444, i[0] );
assertEquals( 555, i[1] );
assertEquals( LuaInteger.valueOf(444), v.get(ONE) );
assertEquals( LuaInteger.valueOf(555), v.get(TWO) );
try {
v.set(ZERO, LuaInteger.valueOf(777));
fail( "array bound exception not thrown" );
} catch ( LuaError lee ) {
// expected
}
try {
v.set(THREE, LuaInteger.valueOf(777));
fail( "array bound exception not thrown" );
} catch ( LuaError lee ) {
// expected
}
}
public void testLuaTableToJavaIntArray() {
LuaTable t = new LuaTable();
t.set(1, LuaInteger.valueOf(222) );
t.set(2, LuaInteger.valueOf(333) );
int[] i = null;
Object o = CoerceLuaToJava.coerce(t, int[].class);
assertEquals( int[].class, o.getClass() );
i = (int[]) o;
assertEquals( 2, i.length );
assertEquals( 222, i[0] );
assertEquals( 333, i[1] );
}
public void testIntArrayScoringTables() {
int a = 5;
LuaValue la = LuaInteger.valueOf(a);
LuaTable tb = new LuaTable();
tb.set( 1, la );
LuaTable tc = new LuaTable();
tc.set( 1, tb );
int saa = CoerceLuaToJava.getCoercion(int.class).score(la);
int sab = CoerceLuaToJava.getCoercion(int[].class).score(la);
int sac = CoerceLuaToJava.getCoercion(int[][].class).score(la);
assertTrue( saa < sab );
assertTrue( saa < sac );
int sba = CoerceLuaToJava.getCoercion(int.class).score(tb);
int sbb = CoerceLuaToJava.getCoercion(int[].class).score(tb);
int sbc = CoerceLuaToJava.getCoercion(int[][].class).score(tb);
assertTrue( sbb < sba );
assertTrue( sbb < sbc );
int sca = CoerceLuaToJava.getCoercion(int.class).score(tc);
int scb = CoerceLuaToJava.getCoercion(int[].class).score(tc);
int scc = CoerceLuaToJava.getCoercion(int[][].class).score(tc);
assertTrue( scc < sca );
assertTrue( scc < scb );
}
public void testIntArrayScoringUserdata() {
int a = 5;
int[] b = { 44, 66 };
int[][] c = { { 11, 22 }, { 33, 44 } };
LuaValue va = CoerceJavaToLua.coerce(a);
LuaValue vb = CoerceJavaToLua.coerce(b);
LuaValue vc = CoerceJavaToLua.coerce(c);
int vaa = CoerceLuaToJava.getCoercion(int.class).score(va);
int vab = CoerceLuaToJava.getCoercion(int[].class).score(va);
int vac = CoerceLuaToJava.getCoercion(int[][].class).score(va);
assertTrue( vaa < vab );
assertTrue( vaa < vac );
int vba = CoerceLuaToJava.getCoercion(int.class).score(vb);
int vbb = CoerceLuaToJava.getCoercion(int[].class).score(vb);
int vbc = CoerceLuaToJava.getCoercion(int[][].class).score(vb);
assertTrue( vbb < vba );
assertTrue( vbb < vbc );
int vca = CoerceLuaToJava.getCoercion(int.class).score(vc);
int vcb = CoerceLuaToJava.getCoercion(int[].class).score(vc);
int vcc = CoerceLuaToJava.getCoercion(int[][].class).score(vc);
assertTrue( vcc < vca );
assertTrue( vcc < vcb );
}
public static class SampleClass {
public String sample() { return "void-args"; }
public String sample(int a) { return "int-args "+a; }
public String sample(int[] a) { return "int-array-args "+a[0]+","+a[1]; }
public String sample(int[][] a) { return "int-array-array-args "+a[0][0]+","+a[0][1]+","+a[1][0]+","+a[1][1]; }
}
public void testMatchVoidArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue result = v.method("sample");
assertEquals( "void-args", result.toString() );
}
public void testMatchIntArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue arg = CoerceJavaToLua.coerce(new Integer(123));
LuaValue result = v.method("sample",arg);
assertEquals( "int-args 123", result.toString() );
}
public void testMatchIntArrayArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue arg = CoerceJavaToLua.coerce(new int[]{345,678});
LuaValue result = v.method("sample",arg);
assertEquals( "int-array-args 345,678", result.toString() );
}
public void testMatchIntArrayArrayArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue arg = CoerceJavaToLua.coerce(new int[][]{{22,33},{44,55}});
LuaValue result = v.method("sample",arg);
assertEquals( "int-array-array-args 22,33,44,55", result.toString() );
}
public static final class SomeException extends RuntimeException {
public SomeException(String message) {
super(message);
}
}
public static final class SomeClass {
public static void someMethod() {
throw new SomeException( "this is some message" );
}
}
public void testExceptionMessage() {
String script = "local c = luajava.bindClass( \""+SomeClass.class.getName()+"\" )\n" +
"return pcall( c.someMethod, c )";
Varargs vresult = globals.get("load").call(LuaValue.valueOf(script)).invoke(LuaValue.NONE);
LuaValue status = vresult.arg1();
LuaValue message = vresult.arg(2);
assertEquals( LuaValue.FALSE, status );
int index = message.toString().indexOf( "this is some message" );
assertTrue( "bad message: "+message, index>=0 );
}
public void testLuaErrorCause() {
String script = "luajava.bindClass( \""+SomeClass.class.getName()+"\"):someMethod()";
LuaValue chunk = globals.get("load").call(LuaValue.valueOf(script));
try {
chunk.invoke(LuaValue.NONE);
fail( "call should not have succeeded" );
} catch ( LuaError lee ) {
Throwable c = lee.getCause();
assertEquals( SomeException.class, c.getClass() );
}
}
public interface VarArgsInterface {
public String varargsMethod( String a, String ... v );
public String arrayargsMethod( String a, String[] v );
}
public void testVarArgsProxy() {
String script = "return luajava.createProxy( \""+VarArgsInterface.class.getName()+"\", \n"+
"{\n" +
" varargsMethod = function(a,...)\n" +
" return table.concat({a,...},'-')\n" +
" end,\n" +
" arrayargsMethod = function(a,array)\n" +
" return tostring(a)..(array and \n" +
" ('-'..tostring(array.length)\n" +
" ..'-'..tostring(array[1])\n" +
" ..'-'..tostring(array[2])\n" +
" ) or '-nil')\n" +
" end,\n" +
"} )\n";
Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
if ( ! chunk.arg1().toboolean() )
fail( chunk.arg(2).toString() );
LuaValue result = chunk.arg1().call();
Object u = result.touserdata();
VarArgsInterface v = (VarArgsInterface) u;
assertEquals( "foo", v.varargsMethod("foo") );
assertEquals( "foo-bar", v.varargsMethod("foo", "bar") );
assertEquals( "foo-bar-etc", v.varargsMethod("foo", "bar", "etc") );
assertEquals( "foo-0-nil-nil", v.arrayargsMethod("foo", new String[0]) );
assertEquals( "foo-1-bar-nil", v.arrayargsMethod("foo", new String[] {"bar"}) );
assertEquals( "foo-2-bar-etc", v.arrayargsMethod("foo", new String[] {"bar","etc"}) );
assertEquals( "foo-3-bar-etc", v.arrayargsMethod("foo", new String[] {"bar","etc","etc"}) );
assertEquals( "foo-nil", v.arrayargsMethod("foo", null) );
}
public void testBigNum() {
String script =
"bigNumA = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n" +
"bigNumB = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n" +
"bigNumC = bigNumA:multiply(bigNumB);\n" +
//"print(bigNumA:toString())\n" +
//"print(bigNumB:toString())\n" +
//"print(bigNumC:toString())\n" +
"return bigNumA:toString(), bigNumB:toString(), bigNumC:toString()";
Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
if ( ! chunk.arg1().toboolean() )
fail( chunk.arg(2).toString() );
Varargs results = chunk.arg1().invoke();
int nresults = results.narg();
String sa = results.tojstring(1);
String sb = results.tojstring(2);
String sc = results.tojstring(3);
assertEquals( 3, nresults );
assertEquals( "12345678901234567890", sa );
assertEquals( "12345678901234567890", sb );
assertEquals( "152415787532388367501905199875019052100", sc );
}
public interface IA {}
public interface IB extends IA {}
public interface IC extends IB {}
public static class A implements IA {
}
public static class B extends A implements IB {
public String set( Object x ) { return "set(Object) "; }
public String set( String x ) { return "set(String) "+x; }
public String set( A x ) { return "set(A) "; }
public String set( B x ) { return "set(B) "; }
public String set( C x ) { return "set(C) "; }
public String set( byte x ) { return "set(byte) "+x; }
public String set( char x ) { return "set(char) "+(int)x; }
public String set( short x ) { return "set(short) "+x; }
public String set( int x ) { return "set(int) "+x; }
public String set( long x ) { return "set(long) "+x; }
public String set( float x ) { return "set(float) "+x; }
public String set( double x ) { return "set(double) "+x; }
public String setr( double x ) { return "setr(double) "+x; }
public String setr( float x ) { return "setr(float) "+x; }
public String setr( long x ) { return "setr(long) "+x; }
public String setr( int x ) { return "setr(int) "+x; }
public String setr( short x ) { return "setr(short) "+x; }
public String setr( char x ) { return "setr(char) "+(int)x; }
public String setr( byte x ) { return "setr(byte) "+x; }
public String setr( C x ) { return "setr(C) "; }
public String setr( B x ) { return "setr(B) "; }
public String setr( A x ) { return "setr(A) "; }
public String setr( String x ) { return "setr(String) "+x; }
public String setr( Object x ) { return "setr(Object) "; }
public Object getObject() { return new Object(); }
public String getString() { return "abc"; }
public byte[] getbytearray() { return new byte[] { 1, 2, 3 }; }
public A getA() { return new A(); }
public B getB() { return new B(); }
public C getC() { return new C(); }
public byte getbyte() { return 1; }
public char getchar() { return 65000; }
public short getshort() { return -32000; }
public int getint() { return 100000; }
public long getlong() { return 50000000000L; }
public float getfloat() { return 6.5f; }
public double getdouble() { return Math.PI; }
}
public static class C extends B implements IC {
}
public static class D extends C implements IA {
}
public void testOverloadedJavaMethodObject() { doOverloadedMethodTest( "Object", "" ); }
public void testOverloadedJavaMethodString() { doOverloadedMethodTest( "String", "abc" ); }
public void testOverloadedJavaMethodA() { doOverloadedMethodTest( "A", "" ); }
public void testOverloadedJavaMethodB() { doOverloadedMethodTest( "B", "" ); }
public void testOverloadedJavaMethodC() { doOverloadedMethodTest( "C", "" ); }
public void testOverloadedJavaMethodByte() { doOverloadedMethodTest( "byte", "1" ); }
public void testOverloadedJavaMethodChar() { doOverloadedMethodTest( "char", "65000" ); }
public void testOverloadedJavaMethodShort() { doOverloadedMethodTest( "short", "-32000" ); }
public void testOverloadedJavaMethodInt() { doOverloadedMethodTest( "int", "100000" ); }
public void testOverloadedJavaMethodLong() { doOverloadedMethodTest( "long", "50000000000" ); }
public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest( "float", "6.5" ); }
public void testOverloadedJavaMethodDouble() { doOverloadedMethodTest( "double", "3.141592653589793" ); }
private void doOverloadedMethodTest( String typename, String value ) {
String script =
"local a = luajava.newInstance('"+B.class.getName()+"');\n" +
"local b = a:set(a:get"+typename+"())\n" +
"local c = a:setr(a:get"+typename+"())\n" +
"return b,c";
Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
if ( ! chunk.arg1().toboolean() )
fail( chunk.arg(2).toString() );
Varargs results = chunk.arg1().invoke();
int nresults = results.narg();
assertEquals( 2, nresults );
LuaValue b = results.arg(1);
LuaValue c = results.arg(2);
String sb = b.tojstring();
String sc = c.tojstring();
assertEquals( "set("+typename+") "+value, sb );
assertEquals( "setr("+typename+") "+value, sc );
}
public void testClassInheritanceLevels() {
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(Object.class, Object.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, String.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, A.class) );
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(Object.class, B.class) );
assertEquals( 3, CoerceLuaToJava.inheritanceLevels(Object.class, C.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, Object.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, String.class) );
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(A.class, A.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(A.class, B.class) );
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(A.class, C.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, Object.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, String.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, A.class) );
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(B.class, B.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(B.class, C.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, Object.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, String.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, A.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, B.class) );
assertEquals( 0, CoerceLuaToJava.inheritanceLevels(C.class, C.class) );
}
public void testInterfaceInheritanceLevels() {
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, A.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IB.class, B.class) );
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IA.class, B.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IC.class, C.class) );
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IB.class, C.class) );
assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IA.class, C.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, D.class) );
assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IC.class, D.class) );
assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IB.class, D.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, A.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, A.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, B.class) );
assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, IA.class) );
assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, IB.class) );
}
public void testCoerceJavaToLuaLuaValue() {
assertSame(LuaValue.NIL, CoerceJavaToLua.coerce(LuaValue.NIL));
assertSame(LuaValue.ZERO, CoerceJavaToLua.coerce(LuaValue.ZERO));
assertSame(LuaValue.ONE, CoerceJavaToLua.coerce(LuaValue.ONE));
assertSame(LuaValue.INDEX, CoerceJavaToLua.coerce(LuaValue.INDEX));
LuaTable table = LuaValue.tableOf();
assertSame(table, CoerceJavaToLua.coerce(table));
}
public void testCoerceJavaToLuaByeArray() {
byte[] bytes = "abcd".getBytes();
LuaValue value = CoerceJavaToLua.coerce(bytes);
assertEquals(LuaString.class, value.getClass());
assertEquals(LuaValue.valueOf("abcd"), value);
}
}

View File

@@ -0,0 +1,68 @@
package org.luaj.vm2.libs.jse;
import junit.framework.TestCase;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
public class LuajavaAccessibleMembersTest extends TestCase {
private Globals globals;
protected void setUp() throws Exception {
super.setUp();
globals = JsePlatform.standardGlobals();
}
private String invokeScript(String script) {
try {
LuaValue c = globals.load(script, "script");
return c.call().tojstring();
} catch ( Exception e ) {
fail("exception: "+e );
return "failed";
}
}
public void testAccessFromPrivateClassImplementedMethod() {
assertEquals("privateImpl-aaa-interface_method(bar)", invokeScript(
"b = luajava.newInstance('"+TestClass.class.getName()+"');" +
"a = b:create_PrivateImpl('aaa');" +
"return a:interface_method('bar');"));
}
public void testAccessFromPrivateClassPublicMethod() {
assertEquals("privateImpl-aaa-public_method", invokeScript(
"b = luajava.newInstance('"+TestClass.class.getName()+"');" +
"a = b:create_PrivateImpl('aaa');" +
"return a:public_method();"));
}
public void testAccessFromPrivateClassGetPublicField() {
assertEquals("aaa", invokeScript(
"b = luajava.newInstance('"+TestClass.class.getName()+"');" +
"a = b:create_PrivateImpl('aaa');" +
"return a.public_field;"));
}
public void testAccessFromPrivateClassSetPublicField() {
assertEquals("foo", invokeScript(
"b = luajava.newInstance('"+TestClass.class.getName()+"');" +
"a = b:create_PrivateImpl('aaa');" +
"a.public_field = 'foo';" +
"return a.public_field;"));
}
public void testAccessFromPrivateClassPublicConstructor() {
assertEquals("privateImpl-constructor", invokeScript(
"b = luajava.newInstance('"+TestClass.class.getName()+"');" +
"c = b:get_PrivateImplClass();" +
"return luajava.new(c);"));
}
public void testAccessPublicEnum() {
assertEquals("class org.luaj.vm2.lib.jse.TestClass$SomeEnum", invokeScript(
"b = luajava.newInstance('"+TestClass.class.getName()+"');" +
"return b.SomeEnum"));
}
}

View File

@@ -0,0 +1,238 @@
package org.luaj.vm2.libs.jse;
import junit.framework.TestCase;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
public class LuajavaClassMembersTest extends TestCase {
public static class A {
protected A() {}
}
public static class B extends A {
public byte m_byte_field;
public int m_int_field;
public double m_double_field;
public String m_string_field;
protected B() {}
public B(int i) { m_int_field = i; }
public String setString( String x ) { return "setString(String) "+x; }
public String getString() { return "abc"; }
public int getint() { return 100000; }
public String uniq() { return "uniq()"; }
public String uniqs(String s) { return "uniqs(string:"+s+")"; }
public String uniqi(int i) { return "uniqi(int:"+i+")"; }
public String uniqsi(String s, int i) { return "uniqsi(string:"+s+",int:"+i+")"; }
public String uniqis(int i, String s) { return "uniqis(int:"+i+",string:"+s+")"; }
public String pick() { return "pick()"; }
public String pick(String s) { return "pick(string:"+s+")"; }
public String pick(int i) { return "pick(int:"+i+")"; }
public String pick(String s, int i) { return "pick(string:"+s+",int:"+i+")"; }
public String pick(int i, String s) { return "pick(int:"+i+",string:"+s+")"; }
public static String staticpick() { return "static-pick()"; }
public static String staticpick(String s) { return "static-pick(string:"+s+")"; }
public static String staticpick(int i) { return "static-pick(int:"+i+")"; }
public static String staticpick(String s, int i) { return "static-pick(string:"+s+",int:"+i+")"; }
public static String staticpick(int i, String s) { return "static-pick(int:"+i+",string:"+s+")"; }
}
public static class C extends B {
public C() {}
public C(String s) { m_string_field = s; }
public C(int i) { m_int_field = i; }
public C(String s, int i) { m_string_field = s; m_int_field = i; }
public int getint() { return 200000; }
public String pick(String s) { return "class-c-pick(string:"+s+")"; }
public String pick(int i) { return "class-c-pick(int:"+i+")"; }
public static class D {
public static String name() { return "name-of-D"; }
}
}
static LuaValue ZERO = LuaValue.ZERO;
static LuaValue ONE = LuaValue.ONE;
static LuaValue PI = LuaValue.valueOf(Math.PI);
static LuaValue THREE = LuaValue.valueOf(3);
static LuaValue NUMS = LuaValue.valueOf(123);
static LuaValue ABC = LuaValue.valueOf("abc");
static LuaValue SOMEA = CoerceJavaToLua.coerce(new A());
static LuaValue SOMEB = CoerceJavaToLua.coerce(new B());
static LuaValue SOMEC = CoerceJavaToLua.coerce(new C());
public void testSetByteField() {
B b = new B();
JavaInstance i = new JavaInstance(b);
i.set("m_byte_field", ONE ); assertEquals( 1, b.m_byte_field ); assertEquals( ONE, i.get("m_byte_field") );
i.set("m_byte_field", PI ); assertEquals( 3, b.m_byte_field ); assertEquals( THREE, i.get("m_byte_field") );
i.set("m_byte_field", ABC ); assertEquals( 0, b.m_byte_field ); assertEquals( ZERO, i.get("m_byte_field") );
}
public void testSetDoubleField() {
B b = new B();
JavaInstance i = new JavaInstance(b);
i.set("m_double_field", ONE ); assertEquals( 1., b.m_double_field ); assertEquals( ONE, i.get("m_double_field") );
i.set("m_double_field", PI ); assertEquals( Math.PI, b.m_double_field ); assertEquals( PI, i.get("m_double_field") );
i.set("m_double_field", ABC ); assertEquals( 0., b.m_double_field ); assertEquals( ZERO, i.get("m_double_field") );
}
public void testNoFactory() {
JavaClass c = JavaClass.forClass(A.class);
try {
c.call();
fail( "did not throw lua error as expected" );
} catch ( LuaError e ) {
}
}
public void testUniqueFactoryCoercible() {
JavaClass c = JavaClass.forClass(B.class);
assertEquals( JavaClass.class, c.getClass() );
LuaValue constr = c.get("new");
assertEquals( JavaConstructor.class, constr.getClass() );
LuaValue v = constr.call(NUMS);
Object b = v.touserdata();
assertEquals( B.class, b.getClass() );
assertEquals( 123, ((B)b).m_int_field );
Object b0 = constr.call().touserdata();
assertEquals( B.class, b0.getClass() );
assertEquals( 0, ((B)b0).m_int_field );
}
public void testUniqueFactoryUncoercible() {
JavaClass f = JavaClass.forClass(B.class);
LuaValue constr = f.get("new");
assertEquals( JavaConstructor.class, constr.getClass() );
try {
LuaValue v = constr.call(LuaValue.userdataOf(new Object()));
Object b = v.touserdata();
// fail( "did not throw lua error as expected" );
assertEquals( 0, ((B)b).m_int_field );
} catch ( LuaError e ) {
}
}
public void testOverloadedFactoryCoercible() {
JavaClass f = JavaClass.forClass(C.class);
LuaValue constr = f.get("new");
assertEquals( JavaConstructor.Overload.class, constr.getClass() );
Object c = constr.call().touserdata();
Object ci = constr.call(LuaValue.valueOf(123)).touserdata();
Object cs = constr.call(LuaValue.valueOf("abc")).touserdata();
Object csi = constr.call( LuaValue.valueOf("def"), LuaValue.valueOf(456) ).touserdata();
assertEquals( C.class, c.getClass() );
assertEquals( C.class, ci.getClass() );
assertEquals( C.class, cs.getClass() );
assertEquals( C.class, csi.getClass() );
assertEquals( null, ((C)c).m_string_field );
assertEquals( 0, ((C)c).m_int_field );
assertEquals( "abc", ((C)cs).m_string_field );
assertEquals( 0, ((C)cs).m_int_field );
assertEquals( null, ((C)ci).m_string_field );
assertEquals( 123, ((C)ci).m_int_field );
assertEquals( "def", ((C)csi).m_string_field );
assertEquals( 456, ((C)csi).m_int_field );
}
public void testOverloadedFactoryUncoercible() {
JavaClass f = JavaClass.forClass(C.class);
try {
Object c = f.call(LuaValue.userdataOf(new Object()));
// fail( "did not throw lua error as expected" );
assertEquals( 0, ((C)c).m_int_field );
assertEquals( null, ((C)c).m_string_field );
} catch ( LuaError e ) {
}
}
public void testNoAttribute() {
JavaClass f = JavaClass.forClass(A.class);
LuaValue v = f.get("bogus");
assertEquals( v, LuaValue.NIL );
try {
f.set("bogus",ONE);
fail( "did not throw lua error as expected" );
} catch ( LuaError e ) {}
}
public void testFieldAttributeCoercible() {
JavaInstance i = new JavaInstance(new B());
i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() );
i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() );
i = new JavaInstance(new C());
i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() );
i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() );
}
public void testUniqueMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue b_getString = ib.get("getString");
LuaValue b_getint = ib.get("getint");
assertEquals( JavaMethod.class, b_getString.getClass() );
assertEquals( JavaMethod.class, b_getint.getClass() );
assertEquals( "abc", b_getString.call(SOMEB).tojstring() );
assertEquals( 100000, b_getint.call(SOMEB).toint());
assertEquals( "abc", b_getString.call(SOMEC).tojstring() );
assertEquals( 200000, b_getint.call(SOMEC).toint());
}
public void testUniqueMethodAttributeArgsCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue uniq = ib.get("uniq");
LuaValue uniqs = ib.get("uniqs");
LuaValue uniqi = ib.get("uniqi");
LuaValue uniqsi = ib.get("uniqsi");
LuaValue uniqis = ib.get("uniqis");
assertEquals( JavaMethod.class, uniq.getClass() );
assertEquals( JavaMethod.class, uniqs.getClass() );
assertEquals( JavaMethod.class, uniqi.getClass() );
assertEquals( JavaMethod.class, uniqsi.getClass() );
assertEquals( JavaMethod.class, uniqis.getClass() );
assertEquals( "uniq()", uniq.call(SOMEB).tojstring() );
assertEquals( "uniqs(string:abc)", uniqs.call(SOMEB,ABC).tojstring() );
assertEquals( "uniqi(int:1)", uniqi.call(SOMEB,ONE).tojstring() );
assertEquals( "uniqsi(string:abc,int:1)", uniqsi.call(SOMEB,ABC,ONE).tojstring() );
assertEquals( "uniqis(int:1,string:abc)", uniqis.call(SOMEB,ONE,ABC).tojstring() );
assertEquals( "uniqis(int:1,string:abc)", uniqis.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() );
}
public void testOverloadedMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue p = ib.get("pick");
assertEquals( "pick()", p.call(SOMEB).tojstring() );
assertEquals( "pick(string:abc)", p.call(SOMEB,ABC).tojstring() );
assertEquals( "pick(int:1)", p.call(SOMEB,ONE).tojstring() );
assertEquals( "pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() );
assertEquals( "pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() );
assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() );
}
public void testUnboundOverloadedMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue p = ib.get("pick");
assertEquals( JavaMethod.Overload.class, p.getClass() );
assertEquals( "pick()", p.call(SOMEC).tojstring() );
assertEquals( "class-c-pick(string:abc)", p.call(SOMEC,ABC).tojstring() );
assertEquals( "class-c-pick(int:1)", p.call(SOMEC,ONE).tojstring() );
assertEquals( "pick(string:abc,int:1)", p.call(SOMEC,ABC,ONE).tojstring() );
assertEquals( "pick(int:1,string:abc)", p.call(SOMEC,ONE,ABC).tojstring() );
assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEC,ONE,ABC,ONE})).arg1().tojstring() );
}
public void testOverloadedStaticMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue p = ib.get("staticpick");
assertEquals( "static-pick()", p.call(SOMEB).tojstring() );
assertEquals( "static-pick(string:abc)", p.call(SOMEB,ABC).tojstring() );
assertEquals( "static-pick(int:1)", p.call(SOMEB,ONE).tojstring() );
assertEquals( "static-pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() );
assertEquals( "static-pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() );
assertEquals( "static-pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() );
}
public void testGetInnerClass() {
C c = new C();
JavaInstance ic = new JavaInstance(c);
LuaValue d = ic.get("D");
assertFalse(d.isnil());
assertSame(d, JavaClass.forClass(C.D.class));
LuaValue e = ic.get("E");
assertTrue(e.isnil());
}
}

View File

@@ -0,0 +1,77 @@
package org.luaj.vm2.libs.jse;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.libs.jme.JmePlatform;
import junit.framework.TestCase;
public class OsLibTest extends TestCase {
LuaValue jme_lib;
LuaValue jse_lib;
double time;
public void setUp() {
jse_lib = JsePlatform.standardGlobals().get("os");;
jme_lib = JmePlatform.standardGlobals().get("os");;
time = new java.util.Date(2001-1900, 7, 23, 14, 55, 02).getTime() / 1000.0;
}
void t(String format, String expected) {
String actual = jme_lib.get("date").call(LuaValue.valueOf(format), LuaValue.valueOf(time)).tojstring();
assertEquals(expected, actual);
}
public void testStringDateChars() { t("foo", "foo"); }
public void testStringDate_a() { t("%a", "Thu"); }
public void testStringDate_A() { t("%A", "Thursday"); }
public void testStringDate_b() { t("%b", "Aug"); }
public void testStringDate_B() { t("%B", "August"); }
public void testStringDate_c() { t("%c", "Thu Aug 23 14:55:02 2001"); }
public void testStringDate_d() { t("%d", "23"); }
public void testStringDate_H() { t("%H", "14"); }
public void testStringDate_I() { t("%I", "02"); }
public void testStringDate_j() { t("%j", "235"); }
public void testStringDate_m() { t("%m", "08"); }
public void testStringDate_M() { t("%M", "55"); }
public void testStringDate_p() { t("%p", "PM"); }
public void testStringDate_S() { t("%S", "02"); }
public void testStringDate_U() { t("%U", "33"); }
public void testStringDate_w() { t("%w", "4"); }
public void testStringDate_W() { t("%W", "34"); }
public void testStringDate_x() { t("%x", "08/23/01"); }
public void testStringDate_X() { t("%X", "14:55:02"); }
public void testStringDate_y() { t("%y", "01"); }
public void testStringDate_Y() { t("%Y", "2001"); }
public void testStringDate_Pct() { t("%%", "%"); }
static final double DAY = 24. * 3600.;
public void testStringDate_UW_neg4() { time-=4*DAY; t("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); }
public void testStringDate_UW_neg3() { time-=3*DAY; t("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); }
public void testStringDate_UW_neg2() { time-=2*DAY; t("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); }
public void testStringDate_UW_neg1() { time-=DAY; t("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); }
public void testStringDate_UW_pos0() { time+=0; t("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); }
public void testStringDate_UW_pos1() { time+=DAY; t("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); }
public void testStringDate_UW_pos2() { time+=2*DAY; t("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); }
public void testStringDate_UW_pos3() { time+=3*DAY; t("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); }
public void testStringDate_UW_pos4() { time+=4*DAY; t("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); }
public void testJseOsGetenvForEnvVariables() {
LuaValue USER = LuaValue.valueOf("USER");
LuaValue jse_user = jse_lib.get("getenv").call(USER);
LuaValue jme_user = jme_lib.get("getenv").call(USER);
assertFalse(jse_user.isnil());
assertTrue(jme_user.isnil());
System.out.println("User: " + jse_user);
}
public void testJseOsGetenvForSystemProperties() {
System.setProperty("test.key.foo", "test.value.bar");
LuaValue key = LuaValue.valueOf("test.key.foo");
LuaValue value = LuaValue.valueOf("test.value.bar");
LuaValue jse_value = jse_lib.get("getenv").call(key);
LuaValue jme_value = jme_lib.get("getenv").call(key);
assertEquals(value, jse_value);
assertEquals(value, jme_value);
}
}

View File

@@ -0,0 +1,22 @@
package org.luaj.vm2.libs.jse;
public class TestClass {
private static class PrivateImpl implements TestInterface {
public String public_field;
public PrivateImpl() {
this.public_field = "privateImpl-constructor";
}
PrivateImpl(String f) {
this.public_field = f;
}
public String public_method() { return "privateImpl-"+public_field+"-public_method"; }
public String interface_method(String x) { return "privateImpl-"+public_field+"-interface_method("+x+")"; }
public String toString() { return public_field; }
}
public TestInterface create_PrivateImpl(String f) { return new PrivateImpl(f); }
public Class get_PrivateImplClass() { return PrivateImpl.class; }
public enum SomeEnum {
ValueOne,
ValueTwo,
}
}

View File

@@ -0,0 +1,5 @@
package org.luaj.vm2.libs.jse;
public interface TestInterface {
String interface_method(String x);
}