[英]How do I hide a class method from Rhino Script Engine?
如果我使用Java將對象傳遞給Rhino,是否可以在該對象的類中使用注釋來隱藏Rhino JavaScript的方法\\字段,以使JavaScript無法訪問它們? 或執行此操作的任何其他方法?
我做了一些研究,看起來我可以用Scriptable包裝對象,但這似乎是一個比可能更容易實現的方案更混亂的解決方案,因為這似乎是一個相當標准的功能。
謝謝。
我在Rhino引擎中找不到對此的任何支持(如果有人知道這樣的事情,請這么說。)
也就是說,這很容易實現。 您需要實現自己的WrapFactory和自己的NativeJavaObject。 您還需要調用創建自己的ContextFactory,以確保在腳本引擎中使用的所有Context對象上都使用WrapFactory。 這聽起來像是很多工作……但實際上,實際上只是很多包裝器代碼。 這是我的實現的摘要。 缺少什么:是對ContextFactory.initGlobal的實際調用,用於將全局ContextFactory設置為您的ContextFactory實現。
顯然,此代碼不是線程安全的
class ProtectedContextFactory extends ContextFactory
{
private static final ProtectedWrapFactory wrapper = new ProtectedWrapFactory();
@Override
protected Context makeContext()
{
Context c = super.makeContext();
c.setWrapFactory(wrapper);
return c;
}
}
class ProtectedWrapFactory extends WrapFactory
{
@Override
public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class<?> staticType)
{
return new ProtectedNativeJavaObject(scope, javaObject, staticType);
}
}
class ProtectedNativeJavaObject extends NativeJavaObject
{
private static final HashMap<Class<?>, ArrayList<String>> CLASS_PROTECTION_CACHE = new HashMap<Class<?>, ArrayList<String>>();
private ArrayList<String> m_protectedMembers;
public ProtectedNativeJavaObject(Scriptable scope, Object javaObject, Class<?> staticType)
{
super(scope, javaObject, staticType);
Class<?> clazz = javaObject != null ? javaObject.getClass() : staticType;
m_protectedMembers = CLASS_PROTECTION_CACHE.get(clazz);
if(m_protectedMembers == null)
m_protectedMembers = processClass(clazz);
}
private static ArrayList<String> processClass(Class<?> clazz)
{
ArrayList<String> protectedMethods = new ArrayList<String>();
CLASS_PROTECTION_CACHE.put(clazz, protectedMethods);
for(Method m : clazz.getMethods())
{
if(m.getAnnotation(ScriptHiddenMember.class) != null)
protectedMethods.add(m.getName());
}
for(Field f : clazz.getFields())
{
if(f.getAnnotation(ScriptHiddenMember.class) != null)
protectedMethods.add(f.getName());
}
return protectedMethods;
}
@Override
public boolean has(String name, Scriptable start)
{
if(m_protectedMembers.contains(name))
return false;
else
return super.has(name, start);
}
@Override
public Object get(String name, Scriptable start)
{
if(m_protectedMembers.contains(name))
return NOT_FOUND;
else
return super.get(name, start);
}
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ScriptHiddenMember {}
使用接口並通過不將其包含在接口中來隱藏方法將不起作用,即使在將對象強制轉換為接口的同時將對象添加到引擎中,該腳本仍將能夠訪問接口中沒有簽名的方法。 我發現隱藏方法的方法是將它們聲明為private,protected或(無修飾符) ; 這使腳本無法訪問。 如果您使用protected或(無修飾符) ,那么您仍可以在將它們從JS中隱藏的同時,在其他類的代碼中使用它們(假定您從有效位置調用它們)。
對於變量,只要將它們聲明為private,protected或(沒有修飾符) ,並且不包括任何getter方法,該變量將被隱藏。 即使沒有getter方法,也可以訪問公共變量。
使用此界面:
public interface NodeInterface {
public int getPosition();
}
這個實現類:
public class Node implements NodeInterface{
private int x = 5;
public int y = 8;
private int position = 0;
public int getPosition(){return position;}
private String getString(){return "hello";}
public String getBing(){return "bing";}
}
此代碼中的結果:
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
NodeInterface node = (NodeInterface)new Node();
engine.put("node", node);
try {
engine.eval("println(node.x)");//undefined
engine.eval("println(node.y)");//8
engine.eval("println(node.position)");//0
engine.eval("println(node.getPosition())");//0
engine.eval("println(node.getBing());");//hello
engine.eval("println(node.getString())");//TypeError: Cannot find function getString.
} catch (ScriptException e1) {
e1.printStackTrace();
}
為什么不嘗試使用Java接口。 對於將要向Rhino公開的每個類,定義一個接口,其中包含要公開的字段的getter和setter和要公開的方法。
在Rhino上可以找到有關如何訪問Java接口的更多信息:在Javascript實現中訪問Java接口變量
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.