java - 拦截Rhino中java对象的字段访问

标签 java javascript rhino

是否可以在执行的 JavaScript 代码中拦截 Java 对象的字段(和方法)访问?就像 JSCocoa 中允许处理属性和方法访问的委托(delegate)一样。

最佳答案

您可以使用 Context.setWrapFactory 来指定如何包装 Java 对象。 这里显示了打印字段访问和方法调用的包装器:

InterceptWrapFactory.java

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.WrapFactory;
public class InterceptWrapFactory extends WrapFactory{
    @Override
    public Scriptable wrapAsJavaObject(Context cx, Scriptable scope,
            Object javaObject, Class<?> staticType) {
        return new InterceptNativeObject(scope, javaObject, staticType);
    }
}

拦截NativeObject.java

import org.mozilla.javascript.NativeJavaMethod;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
public class InterceptNativeObject extends NativeJavaObject {
    @Override
    public Object get(String name, Scriptable start) {
        Object res = super.get(name, start);
        System.out.println("Field get name="+name+" result="+res);
        if (res instanceof NativeJavaMethod) {
            NativeJavaMethod method = (NativeJavaMethod) res;
            return new JavaMethodWrapper(method);
        }
        return res;
    }
    public InterceptNativeObject(Scriptable scope, Object javaObject,
            Class<?> staticType) {
        super(scope, javaObject, staticType);
    }
}

JavaMethodWrapper.java

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeJavaMethod;
import org.mozilla.javascript.Scriptable;

public class JavaMethodWrapper implements Function {
    NativeJavaMethod method;
    public JavaMethodWrapper(NativeJavaMethod method) {
        this.method = method;
    }
    public boolean hasInstance(Scriptable instance) {
        return method.hasInstance(instance);
    }
    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
            Object[] args) {
        System.out.println("Call method: "+method);
        return method.call(cx, scope, thisObj, args);
    }
    public boolean has(int index, Scriptable start) {
        return method.has(index, start);
    }
    public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
        return method.construct(cx, scope, args);
    }
    public void put(int index, Scriptable start, Object value) {
        method.put(index, start, value);
    }
    public void delete(int index) {
        method.delete(index);
    }
    public Scriptable createObject(Context cx, Scriptable scope) {
        return method.createObject(cx, scope);
    }
    public boolean has(String name, Scriptable start) {
        return method.has(name, start);
    }
    public void defineConst(String name, Scriptable start) {
        method.defineConst(name, start);
    }
    public void put(String name, Scriptable start, Object value) {
        method.put(name, start, value);
    }
    public void delete(String name) {
        method.delete(name);
    }
    public Scriptable getPrototype() {
        return method.getPrototype();
    }
    public void setPrototype(Scriptable m) {
        method.setPrototype(m);
    }
    public Scriptable getParentScope() {
        return method.getParentScope();
    }
    public void setParentScope(Scriptable m) {
        method.setParentScope(m);
    }
    public Object[] getIds() {
        return method.getIds();
    }
    public Object get(int index, Scriptable start) {
        return method.get(index, start);
    }
    public Object get(String name, Scriptable start) {
        return method.get(name, start);
    }
    public String getClassName() {
        return method.getClassName();
    }
    public Object getDefaultValue(Class<?> typeHint) {
        return method.getDefaultValue(typeHint);
    }
}

这是一个测试代码:

import java.util.Vector;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;


public class InterceptTest {
    public static void main(String[] args) {
        Context cx=Context.enter();
        cx.setWrapFactory(new InterceptWrapFactory());
        Scriptable root=cx.initStandardObjects();
        ScriptableObject.putProperty(root,"v", new Vector<String>());
        cx.evaluateString(root, "v.add('foo'); v.get(0)", "src", 1, null);
    }
}

关于java - 拦截Rhino中java对象的字段访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10483422/

相关文章:

java - 应用程序打开时黑屏

java - 在 Java 中存储程序设置

javascript - Nodejs 如何在 Controller 中动态操作 MongoDB 聚合?

java - 激活 JComboBox 上的 ActionListener setSelectedItem()

java - 我需要一个具有允许通配符的枚举类型的 XML 模式

javascript - 使用位置固定子项滚动 Div

javascript - 如何使用 jQuery 访问以编程方式生成的元素

java - 如何在 Java 应用程序中通过 JavaScript 启动程序?

java - 在 Android 上嵌入 Rhino 的问题

java - Rhino:在 Javascript 实现中访问 Java 接口(interface)变量