Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
165 views
in Technique[技术] by (71.8m points)

java - How do I hide a class method from Rhino Script Engine?

If I pass an object to Rhino in Java, is there an annotation I can use in that object's class to hide methodsfields from Rhino JavaScripts to make them inaccessible to the JavaScripts? Or any other method of doing this?

I did some research, and it looks like I could wrap the Objects with Scriptable, but that seems like a messier solution than what might be potentially really easy to do as it seems like it would be a fairly standard feature.

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I wasn't able to find any support for this in the Rhino engine (if anyone knows of such a thing, please say so.)

That said, it is easy to implement. You need to implement your own WrapFactory, and your own NativeJavaObject. You also need to invoke create your own ContextFactory to assure your WrapFactory is being used on all Context objects used throughout the script engine. This sounds like a lot of work... but really it is actually just a lot of wrapper code. Here is a snippet of my implementation. WHAT IS MISSING: is the actual call to ContextFactory.initGlobal to set the global ContextFactory to your implementation of ContextFactory.

Obviously this code is not thread safe

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 {}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...