Implemented issue: #82
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/CoerceJavaToLua.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/CoerceJavaToLua.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/CoerceLuaToJava.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/CoerceLuaToJava.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaArray.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaArray.class
Normal file
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaClass.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaClass.class
Normal file
Binary file not shown.
@@ -56,6 +56,10 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
||||
Map methods;
|
||||
Map innerclasses;
|
||||
|
||||
static void flushClassCache() {
|
||||
classes.clear();
|
||||
}
|
||||
|
||||
static JavaClass forClass(Class c) {
|
||||
JavaClass j = (JavaClass) classes.get(c);
|
||||
if ( j == null )
|
||||
@@ -75,10 +79,11 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
||||
Field getField(LuaValue key) {
|
||||
if ( fields == null ) {
|
||||
Map m = new HashMap();
|
||||
Field[] f = ((Class)m_instance).getFields();
|
||||
Class clazz = (Class) m_instance;
|
||||
Field[] f = clazz.getFields();
|
||||
for ( int i=0; i<f.length; i++ ) {
|
||||
Field fi = f[i];
|
||||
if ( Modifier.isPublic(fi.getModifiers()) ) {
|
||||
if ( Modifier.isPublic(fi.getModifiers()) && LuajavaLib.isFieldVisible(clazz, fi) ) {
|
||||
m.put(LuaValue.valueOf(fi.getName()), fi);
|
||||
try {
|
||||
if (!fi.isAccessible())
|
||||
@@ -95,10 +100,11 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
||||
LuaValue getMethod(LuaValue key) {
|
||||
if ( methods == null ) {
|
||||
Map namedlists = new HashMap();
|
||||
Method[] m = ((Class)m_instance).getMethods();
|
||||
Class clazz = (Class) m_instance;
|
||||
Method[] m = clazz.getMethods();
|
||||
for ( int i=0; i<m.length; i++ ) {
|
||||
Method mi = m[i];
|
||||
if ( Modifier.isPublic( mi.getModifiers()) ) {
|
||||
if ( Modifier.isPublic( mi.getModifiers()) && LuajavaLib.isMethodVisible(clazz, mi) ) {
|
||||
String name = mi.getName();
|
||||
List list = (List) namedlists.get(name);
|
||||
if ( list == null )
|
||||
@@ -107,10 +113,10 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
||||
}
|
||||
}
|
||||
Map map = new HashMap();
|
||||
Constructor[] c = ((Class)m_instance).getConstructors();
|
||||
Constructor[] c = clazz.getConstructors();
|
||||
List list = new ArrayList();
|
||||
for ( int i=0; i<c.length; i++ )
|
||||
if ( Modifier.isPublic(c[i].getModifiers()) )
|
||||
if ( Modifier.isPublic(c[i].getModifiers()) && LuajavaLib.isConstructorVisible(clazz, c[i]) )
|
||||
list.add( JavaConstructor.forConstructor(c[i]) );
|
||||
switch ( list.size() ) {
|
||||
case 0: break;
|
||||
@@ -135,13 +141,16 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
||||
Class getInnerClass(LuaValue key) {
|
||||
if ( innerclasses == null ) {
|
||||
Map m = new HashMap();
|
||||
Class[] c = ((Class)m_instance).getClasses();
|
||||
Class clazz = (Class) m_instance;
|
||||
Class[] c = clazz.getClasses();
|
||||
for ( int i=0; i<c.length; i++ ) {
|
||||
Class ci = c[i];
|
||||
if (LuajavaLib.isInnerClassVisible(clazz, ci)) {
|
||||
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);
|
||||
|
||||
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaConstructor.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaConstructor.class
Normal file
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaInstance.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaInstance.class
Normal file
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaMember.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaMember.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaMethod.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/JavaMethod.class
Normal file
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/LuajavaLib$1.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/LuajavaLib$1.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/LuajavaLib.class
Normal file
BIN
jse/src/main/java/org/luaj/vm2/libs/jse/LuajavaLib.class
Normal file
Binary file not shown.
@@ -23,6 +23,8 @@ package org.luaj.vm2.libs.jse;
|
||||
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -83,6 +85,38 @@ import org.luaj.vm2.libs.VarArgFunction;
|
||||
*/
|
||||
public class LuajavaLib extends VarArgFunction {
|
||||
|
||||
public interface VisibilityPolicy {
|
||||
boolean isClassVisible(Class clazz);
|
||||
boolean isInnerClassVisible(Class owner, Class innerClass);
|
||||
boolean isFieldVisible(Class owner, Field field);
|
||||
boolean isMethodVisible(Class owner, Method method);
|
||||
boolean isConstructorVisible(Class owner, Constructor constructor);
|
||||
}
|
||||
|
||||
private static final VisibilityPolicy PUBLIC_MEMBERS_POLICY = new VisibilityPolicy() {
|
||||
public boolean isClassVisible(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isInnerClassVisible(Class owner, Class innerClass) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFieldVisible(Class owner, Field field) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isMethodVisible(Class owner, Method method) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isConstructorVisible(Class owner, Constructor constructor) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private static volatile VisibilityPolicy visibilityPolicy = PUBLIC_MEMBERS_POLICY;
|
||||
|
||||
static final int INIT = 0;
|
||||
static final int BINDCLASS = 1;
|
||||
static final int NEWINSTANCE = 2;
|
||||
@@ -103,6 +137,35 @@ public class LuajavaLib extends VarArgFunction {
|
||||
public LuajavaLib() {
|
||||
}
|
||||
|
||||
public static void setVisibilityPolicy(VisibilityPolicy policy) {
|
||||
visibilityPolicy = policy != null ? policy : PUBLIC_MEMBERS_POLICY;
|
||||
JavaClass.flushClassCache();
|
||||
}
|
||||
|
||||
public static VisibilityPolicy getVisibilityPolicy() {
|
||||
return visibilityPolicy;
|
||||
}
|
||||
|
||||
static boolean isClassVisible(Class clazz) {
|
||||
return visibilityPolicy.isClassVisible(clazz);
|
||||
}
|
||||
|
||||
static boolean isInnerClassVisible(Class owner, Class innerClass) {
|
||||
return visibilityPolicy.isInnerClassVisible(owner, innerClass);
|
||||
}
|
||||
|
||||
static boolean isFieldVisible(Class owner, Field field) {
|
||||
return visibilityPolicy.isFieldVisible(owner, field);
|
||||
}
|
||||
|
||||
static boolean isMethodVisible(Class owner, Method method) {
|
||||
return visibilityPolicy.isMethodVisible(owner, method);
|
||||
}
|
||||
|
||||
static boolean isConstructorVisible(Class owner, Constructor constructor) {
|
||||
return visibilityPolicy.isConstructorVisible(owner, constructor);
|
||||
}
|
||||
|
||||
public Varargs invoke(Varargs args) {
|
||||
try {
|
||||
switch ( opcode ) {
|
||||
@@ -117,6 +180,8 @@ public class LuajavaLib extends VarArgFunction {
|
||||
}
|
||||
case BINDCLASS: {
|
||||
final Class clazz = classForName(args.checkjstring(1));
|
||||
if (!isClassVisible(clazz))
|
||||
throw new LuaError("class is not visible: " + clazz.getName());
|
||||
return JavaClass.forClass(clazz);
|
||||
}
|
||||
case NEWINSTANCE:
|
||||
@@ -124,6 +189,8 @@ public class LuajavaLib extends VarArgFunction {
|
||||
// get constructor
|
||||
final LuaValue c = args.checkvalue(1);
|
||||
final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
|
||||
if (!isClassVisible(clazz))
|
||||
throw new LuaError("class is not visible: " + clazz.getName());
|
||||
final Varargs consargs = args.subargs(2);
|
||||
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
|
||||
}
|
||||
@@ -175,7 +242,10 @@ public class LuajavaLib extends VarArgFunction {
|
||||
|
||||
// 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());
|
||||
Class clazz = Class.forName(name, true, ClassLoader.getSystemClassLoader());
|
||||
if (!isClassVisible(clazz))
|
||||
throw new ClassNotFoundException("class is not visible: " + name);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
private static final class ProxyInvocationHandler implements InvocationHandler {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.luaj.vm2.libs.jse;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.luaj.vm2.LuaError;
|
||||
@@ -235,4 +239,49 @@ public class LuajavaClassMembersTest extends TestCase {
|
||||
LuaValue e = ic.get("E");
|
||||
assertTrue(e.isnil());
|
||||
}
|
||||
|
||||
public void testVisibilityPolicyCanRestrictVisibleMembers() {
|
||||
LuajavaLib.VisibilityPolicy previous = LuajavaLib.getVisibilityPolicy();
|
||||
try {
|
||||
LuajavaLib.setVisibilityPolicy(new LuajavaLib.VisibilityPolicy() {
|
||||
public boolean isClassVisible(Class clazz) {
|
||||
return clazz == B.class || clazz == C.class || clazz == C.D.class;
|
||||
}
|
||||
|
||||
public boolean isInnerClassVisible(Class owner, Class innerClass) {
|
||||
return innerClass == C.D.class;
|
||||
}
|
||||
|
||||
public boolean isFieldVisible(Class owner, Field field) {
|
||||
return "m_int_field".equals(field.getName());
|
||||
}
|
||||
|
||||
public boolean isMethodVisible(Class owner, Method method) {
|
||||
String name = method.getName();
|
||||
return "getint".equals(name) || "pick".equals(name);
|
||||
}
|
||||
|
||||
public boolean isConstructorVisible(Class owner, Constructor constructor) {
|
||||
return owner == B.class && constructor.getParameterTypes().length == 0;
|
||||
}
|
||||
});
|
||||
|
||||
JavaInstance instance = new JavaInstance(new B());
|
||||
assertFalse(instance.get("m_int_field").isnil());
|
||||
assertTrue(instance.get("m_string_field").isnil());
|
||||
assertFalse(instance.get("getint").isnil());
|
||||
assertTrue(instance.get("getString").isnil());
|
||||
|
||||
JavaClass bClass = JavaClass.forClass(B.class);
|
||||
assertFalse(bClass.get("new").isnil());
|
||||
|
||||
JavaClass cClass = JavaClass.forClass(C.class);
|
||||
assertTrue(cClass.get("new").isnil());
|
||||
|
||||
JavaInstance cInstance = new JavaInstance(new C());
|
||||
assertFalse(cInstance.get("D").isnil());
|
||||
} finally {
|
||||
LuajavaLib.setVisibilityPolicy(previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user