I'm having a strange error happen when using rhino with my own WrapFactory implementation from within a Servlet Container. If I run the application outside the servlet container everything works fine. I added my own WrapFactory so that I could make Java collections more closely mimic Javascript Arrays and Objects. Problem is when an script is executed for the first time it can't find the .length parameter on a Java Collection. After it errors out that one time it starts working without a problem. In the debugger I can see that Rhino is using the custom WrapFactory, and the NativeJavaObject extension is being created for that java.util.List. However, the get() method is never called which is where the extension to add the ".length" parameter support is. As I said if I take it out of the container get() method is called as expected, but within the servlet container it doesn't do it the first time. Any ideas what's going on? I'm using the latest stable release of Rhino.
Here's my code: public class EnhancedWrapFactory extends WrapFactory { private boolean scriptableJavaObjects = false; public EnhancedWrapFactory() { setJavaPrimitiveWrap(false); } public EnhancedWrapFactory( boolean scriptableJavaObjects ) { this(); this.scriptableJavaObjects = scriptableJavaObjects; } public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class staticType) { if (javaObject instanceof Map) { return new NativeMapAdapter(cx, scope, javaObject, staticType); } else if (javaObject instanceof List) { return new NativeListAdapter(cx, scope, javaObject, staticType); } else if( scriptableJavaObjects ) { return new ScriptableNativeJavaObject(scope,javaObject,staticType); } else { return new NativeJavaObject(scope, javaObject, staticType); } } } public class NativeListAdapter extends NativeJavaObject { public NativeListAdapter(Context cx, Scriptable scope, Object javaObject, Class staticType) { super(scope, javaObject, staticType); Scriptable scriptable = (Scriptable) cx.evaluateString( scope, "Array.prototype", "internal" , 1, null); setPrototype(scriptable); } private List getList() { return (List) javaObject; } @Override public Object get(String name, Scriptable start) { if( name.equals("length") ) return getList().size(); return super.get(name, start); } public void delete(int index) { try { getList().remove(index); } catch (RuntimeException e) { throw Context.throwAsScriptRuntimeEx(e); } } public Object get(int index, Scriptable start) { Context cx = Context.getCurrentContext(); try { int s = getList().size(); if( index >= 0 && index < s ) { return cx.getWrapFactory().wrap(cx, this, getList().get(index), null); } else { return Context.getUndefinedValue(); } } catch (RuntimeException e) { throw Context.throwAsScriptRuntimeEx(e); } } public String getClassName() { return "NativeListAdapter"; } public Object[] getIds() { int size = getList().size(); Integer[] ids = new Integer[size]; for (int i = 0; i < size; ++i) { ids[i] = i; } return ids; } public boolean has(int index, Scriptable start) { return index >= 0 && index < getList().size(); } public void put(int index, Scriptable start, Object value) { try { getList().set(index, Context.jsToJava(value, org.mozilla.javascript.ScriptRuntime.ObjectClass)); } catch (RuntimeException e) { Context.throwAsScriptRuntimeEx(e); } } @Override public boolean hasInstance(Scriptable value) { return true; } public String toString() { return javaObject.toString(); } } _______________________________________________ dev-tech-js-engine-rhino mailing list dev-tech-js-engine-rhino@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino