Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

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

1 Answer

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...