簡體   English   中英

如何在Rhino Script Engine中隱藏類方法?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM