Here's what I was hoping would work, but I couldn't find any way to
call a Java superclass's method from within a JavaAdapter's method
implementation. Is it possible?
var cx = Packages.org.mozilla.javascript.Context.enter();
var scope = new Packages.org.mozilla.javascript.ScriptableObject({
className : function() {
return "HookedScriptableObject";
},
put : function(name, start, value) {
java.lang.System.out.println("putting: " + name);
// need equivalent to "super.put(name, start, value)"
}
});
scope = cx.initStandardObjects(scope);
I also tried subclassing ScriptableObject directly in Java. This sort
of worked when I just instantiated it directly:
js> a = new Packages.HookedScriptableObject()
Default for class java.lang.String
test4567
js> a.asdf = "1234"
Putting: asdf => 1234
1234
js> a.asdf
Getting: asdf
1234
But when calling initStandardObjects I get "Can't find method
org.mozilla.javascript.Context.initStandardObjects(object)":
var cx = Packages.org.mozilla.javascript.Context.enter();
scope = cx.initStandardObjects(new
Packages.HookedScriptableObject());
Here's HookedScriptableObject.java:
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
class HookedScriptableObject extends ScriptableObject
{
public HookedScriptableObject()
{
super();
}
public String getClassName()
{
return "test1234";
}
public Object getDefaultValue(Class typeHint)
{
System.out.println("Default for " + typeHint);
return "test4567";
}
public Object get(int index, Scriptable start)
{
System.out.println("Getting index: " + index);
return super.get(index, start);
}
public Object get(String name, Scriptable start)
{
System.out.println("Getting: " + name);
return super.get(name, start);
}
public void put(String name, Scriptable start, Object value)
{
System.out.println("Putting: " + name + " => " + value);
super.put(name, start, value);
}
public void put(int index, Scriptable start, Object value)
{
System.out.println("Putting index: " + index + " => " +
value);
super.put(index,start, value);
}
}
I feel like there must be a way to do this pretty easily, I'm just
missing something...
Ideally the code would be entirely in JavaScript, but some Java is
ok. This portion of the code should be in JavaScript, if possible:
var cx = Packages.org.mozilla.javascript.Context.enter();
scope = cx.initStandardObjects(whatever);
Thanks in advance.
-Tom
Yes, use super$methodName() to invoke super methods. This should be
documented at
http://www.mozilla.org/rhino/ScriptingJava.html#javaAdapter
> var cx = Packages.org.mozilla.javascript.Context.enter();
Note that you don't need to call Context.enter() as you are already
running in a rhino context. You may just use
Context.getCurrentContext() instead.
> var scope = new Packages.org.mozilla.javascript.ScriptableObject({
> className : function() {
> return "HookedScriptableObject";
> },
> put : function(name, start, value) {
> java.lang.System.out.println("putting: " + name);
> // need equivalent to "super.put(name, start, value)"
> }
> });
> scope = cx.initStandardObjects(scope);
Neat idea, but it won't work that way, as the JavaAdapter will be
wrapped as java object.
> I also tried subclassing ScriptableObject directly in Java. This sort
> of worked when I just instantiated it directly:
>
> js> a = new Packages.HookedScriptableObject()
> Default for class java.lang.String
> test4567
> js> a.asdf = "1234"
> Putting: asdf => 1234
> 1234
> js> a.asdf
> Getting: asdf
> 1234
>
> But when calling initStandardObjects I get "Can't find method
> org.mozilla.javascript.Context.initStandardObjects(object)":
>
> var cx = Packages.org.mozilla.javascript.Context.enter();
> scope = cx.initStandardObjects(new
> Packages.HookedScriptableObject());
This is a bug in the java method lookup code. I filed a bug for this:
https://bugzilla.mozilla.org/show_bug.cgi?id=456546
The following will work (with the fix for bug 456546 above):
var rhino = org.mozilla.javascript;
var cx = rhino.Context.currentContext;
var scope = new JavaAdapter(rhino.NativeObject, {
getClassName: function() { return "Foo"; },
put: function(name, start, value) {
this.super$put(name, this, value);
},
});
scope = rhino.Context.currentContext.jsToJava(scope,
rhino.Scriptable);
scope.__proto__ = Object.prototype;
cx.initStandardObjects(scope);
Be careful not to calling value.toString() in the put function, as it
will dive into infinite recursion while the scope is being
initialized.
hannes
> -Tom
Maybe push more of the code (i.e. currentContext and
initStandardObjects) into Java, to eliminate the JavaAdapter use?
-Tom
On Sep 23, 5:27 am, Hannes Wallnoefer <hann...@gmail.com> wrote:
> On Sep 23, 4:14 am, tlrobinson <yacht...@gmail.com> wrote:
>
> > I'm trying to create Rhino context (in JS code running in Rhino) with
> > a scope object that reports to me whenever a property is set or
> > accessed. I've tried a number of things, but can't seem to find the
> > right combination.
>
> > Here's what I was hoping would work, but I couldn't find any way to
> > call a Java superclass's method from within a JavaAdapter's method
> > implementation. Is it possible?
>
> Yes, use super$methodName() to invoke super methods. This should be
> documented athttp://www.mozilla.org/rhino/ScriptingJava.html#javaAdapter