зеркало из https://github.com/mozilla/gecko-dev.git
Fix for the following problem:
I'm having problems getting inner class objects with Rhino. I create a Hashmap, which is an implementation of Map. Map.Entry is an inner interface of Map with key-value pairs. If I have a Map object, "property", I should be able to get the key element with the expression "property.key". When I look at the "property" class name that Rhino returns I get: "java.util.HashMap$Entry". I don't believe Rhino has a notion of the inner Map.Entry object. The expression "property" succeeds. The expression "property.key", which should retrieve the Map.Entry keyValue(), fails with a "unexpected IllegalAccessException accessing Java field". I'm including a simple example that illustrates the problem. I hope you can shed some light on this. Thanks! Justyna < Justyna.Horwat@Sun.com > ---- import java.io.*; import java.util.*; import org.mozilla.javascript.*; public class MapTest { public static void main(String argv[]) { Test test = new Test(); test.testMap(); } } class Test { Map map; Set set; Iterator it; Map.Entry entry; public void testMap() { System.out.println("testMap"); map = new HashMap(); populate(); set = map.entrySet(); it = set.iterator(); // let's see if Map is populated correctly while (it.hasNext()) { entry = (Map.Entry) it.next(); System.out.println("entry: " + entry.getClass().getName()); System.out.println("key: " + entry.getKey()); System.out.println("value: " + entry.getValue()); } evaluate(); } void populate() { map.put("firstKey", "firstValue"); map.put("secondKey", "secondValue"); map.put("thirdKey", "thirdValue"); map.put("fourthKey", "fourthValue"); } public void evaluate() { Context cx = Context.enter(); Scriptable scope = cx.initStandardObjects(null); set = map.entrySet(); it = set.iterator(); while (it.hasNext()) { entry = (Map.Entry) it.next(); scope.put("property", scope, cx.toObject(entry,scope)); } Object eval = null; try { // attempt to get Map.Entry key value using Rhino eval = cx.evaluateString(scope, "property.key", "", 0, null); // Unwrap scoped object if (eval instanceof Wrapper) eval = ((Wrapper) eval).unwrap(); } catch (JavaScriptException jse) { System.out.println("EXCEPTION: " + jse.getMessage()); } // DELETE System.out.println("RHINO result: " + eval + ":"); System.out.println("RHINO class: " + eval.getClass().getName()); } }
This commit is contained in:
Родитель
7d17e005e1
Коммит
6642d0e4f2
|
@ -91,7 +91,15 @@ class JavaMembers {
|
|||
try {
|
||||
if (member instanceof BeanProperty) {
|
||||
BeanProperty bp = (BeanProperty) member;
|
||||
rval = bp.getter.invoke(javaObject, ScriptRuntime.emptyArgs);
|
||||
try {
|
||||
rval = bp.getter.invoke(javaObject, null);
|
||||
} catch (IllegalAccessException e) {
|
||||
rval = NativeJavaMethod.retryIllegalAccessInvoke(
|
||||
bp.getter,
|
||||
javaObject,
|
||||
null,
|
||||
e);
|
||||
}
|
||||
type = bp.getter.getReturnType();
|
||||
} else {
|
||||
Field field = (Field) member;
|
||||
|
|
|
@ -220,69 +220,94 @@ public class NativeJavaMethod extends NativeFunction implements Function {
|
|||
}
|
||||
javaObject = ((Wrapper) o).unwrap();
|
||||
}
|
||||
retry:
|
||||
for (int attempt=0; ; attempt++) {
|
||||
try {
|
||||
if (debug) {
|
||||
printDebug("Calling ", meth, args);
|
||||
}
|
||||
|
||||
Object retval;
|
||||
try {
|
||||
if (debug) {
|
||||
printDebug("Calling ", meth, args);
|
||||
}
|
||||
retval = meth.invoke(javaObject, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
retval = retryIllegalAccessInvoke(meth, javaObject, args, e);
|
||||
}
|
||||
Class staticType = meth.getReturnType();
|
||||
|
||||
Object retval = meth.invoke(javaObject, args);
|
||||
Class staticType = meth.getReturnType();
|
||||
if (debug) {
|
||||
Class actualType = (retval == null) ? null
|
||||
: retval.getClass();
|
||||
System.err.println(" ----- Returned " + retval +
|
||||
" actual = " + actualType +
|
||||
" expect = " + staticType);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
Class actualType = (retval == null) ? null
|
||||
: retval.getClass();
|
||||
System.err.println(" ----- Returned " + retval +
|
||||
" actual = " + actualType +
|
||||
" expect = " + staticType);
|
||||
}
|
||||
Object wrapped = NativeJavaObject.wrap(scope, retval, staticType);
|
||||
|
||||
Object wrapped = NativeJavaObject.wrap(scope, retval, staticType);
|
||||
if (debug) {
|
||||
Class actualType = (wrapped == null) ? null
|
||||
: wrapped.getClass();
|
||||
System.err.println(" ----- Wrapped as " + wrapped +
|
||||
" class = " + actualType);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
Class actualType = (wrapped == null) ? null
|
||||
: wrapped.getClass();
|
||||
System.err.println(" ----- Wrapped as " + wrapped +
|
||||
" class = " + actualType);
|
||||
}
|
||||
|
||||
if (wrapped == Undefined.instance)
|
||||
return wrapped;
|
||||
if (wrapped == null && staticType == Void.TYPE)
|
||||
return Undefined.instance;
|
||||
if (wrapped == Undefined.instance)
|
||||
return wrapped;
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
if (Modifier.isPublic(meth.getModifiers()) && attempt == 0) {
|
||||
/**
|
||||
* Due to a bug in Suns VM, public methods in private
|
||||
* classes are not accessible by default (Sun Bug #4071593).
|
||||
* We have to explicitly set the method accessible
|
||||
* via meth.setAccessible(true) but we have to use
|
||||
* reflection because the setAccessible() in Method is
|
||||
* not available under jdk 1.1. We wait until a failure
|
||||
* to retry to avoid the overhead of this call on cases
|
||||
* that don't require it.
|
||||
*/
|
||||
if (method_setAccessible != null) {
|
||||
Object[] args_wrapper = { Boolean.TRUE };
|
||||
try {
|
||||
method_setAccessible.invoke(meth, args_wrapper);
|
||||
}
|
||||
catch (IllegalAccessException ex) { }
|
||||
catch (IllegalArgumentException ex) { }
|
||||
catch (InvocationTargetException ex) { }
|
||||
}
|
||||
continue retry;
|
||||
if (wrapped == null && staticType == Void.TYPE)
|
||||
return Undefined.instance;
|
||||
return wrapped;
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
throw Context.reportRuntimeError(
|
||||
"While attempting to call \"" + meth.getName() +
|
||||
"\" in class \"" + meth.getDeclaringClass().getName() +
|
||||
"\" receieved " + accessEx.toString());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw JavaScriptException.wrapException(scope, e);
|
||||
}
|
||||
}
|
||||
|
||||
static Object retryIllegalAccessInvoke(Method method, Object obj,
|
||||
Object[] args,
|
||||
IllegalAccessException illegalAccess)
|
||||
throws IllegalAccessException, InvocationTargetException
|
||||
{
|
||||
if (Modifier.isPublic(method.getModifiers())) {
|
||||
String name = method.getName();
|
||||
Class[] parms = method.getParameterTypes();
|
||||
Class c = method.getDeclaringClass();
|
||||
Class[] intfs = c.getInterfaces();
|
||||
for (int i=0; i < intfs.length; i++) {
|
||||
c = intfs[i];
|
||||
try {
|
||||
Method m = c.getMethod(name, parms);
|
||||
return m.invoke(obj, args);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
continue;
|
||||
} catch (IllegalAccessException ex) {
|
||||
continue;
|
||||
}
|
||||
throw Context.reportRuntimeError(
|
||||
"While attempting to call \"" + meth.getName() +
|
||||
"\" in class \"" + meth.getDeclaringClass().getName() +
|
||||
"\" receieved " + accessEx.toString());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw JavaScriptException.wrapException(scope, e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Due to a bug in Sun's VM, public methods in private
|
||||
* classes are not accessible by default (Sun Bug #4071593).
|
||||
* We have to explicitly set the method accessible
|
||||
* via method.setAccessible(true) but we have to use
|
||||
* reflection because the setAccessible() in Method is
|
||||
* not available under jdk 1.1. We wait until a failure
|
||||
* to retry to avoid the overhead of this call on cases
|
||||
* that don't require it.
|
||||
*/
|
||||
if (method_setAccessible != null) {
|
||||
Object[] args_wrapper = { Boolean.TRUE };
|
||||
try {
|
||||
method_setAccessible.invoke(method, args_wrapper);
|
||||
}
|
||||
catch (IllegalAccessException ex) { }
|
||||
catch (IllegalArgumentException ex) { }
|
||||
catch (InvocationTargetException ex) { }
|
||||
return method.invoke(obj, args);
|
||||
}
|
||||
throw illegalAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче