mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 05:45:37 +00:00
Use reflection to access JavaAdapter to allow to use NativeJavaObject with JavaAdapter classes absent.
This commit is contained in:
parent
04d207ce3a
commit
7d26c9eb27
@ -44,7 +44,7 @@ package org.mozilla.javascript;
|
||||
|
||||
import org.mozilla.classfile.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public final class JavaAdapter
|
||||
@ -268,22 +268,56 @@ public final class JavaAdapter
|
||||
}
|
||||
}
|
||||
|
||||
// Needed by NativeJavaObject de-serializer
|
||||
|
||||
static Object createAdapterClass(Scriptable scope, Class superClass,
|
||||
Class[] interfaces,
|
||||
Scriptable obj, Scriptable self)
|
||||
throws ClassNotFoundException
|
||||
// Needed by NativeJavaObject serializer
|
||||
public static void writeAdapterObject(Object javaObject,
|
||||
ObjectOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
Class adapterClass = getAdapterClass(scope, superClass, interfaces,
|
||||
obj);
|
||||
Class cl = javaObject.getClass();
|
||||
out.writeObject(cl.getSuperclass().getName());
|
||||
|
||||
Class[] interfaces = cl.getInterfaces();
|
||||
String[] interfaceNames = new String[interfaces.length];
|
||||
|
||||
for (int i=0; i < interfaces.length; i++)
|
||||
interfaceNames[i] = interfaces[i].getName();
|
||||
|
||||
out.writeObject(interfaceNames);
|
||||
|
||||
try {
|
||||
Class[] ctorParms = {
|
||||
ScriptRuntime.ScriptableClass,
|
||||
ScriptRuntime.ScriptableClass
|
||||
};
|
||||
Object[] ctorArgs = { obj, self };
|
||||
Object delegee = cl.getField("delegee").get(javaObject);
|
||||
out.writeObject(delegee);
|
||||
return;
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
// Needed by NativeJavaObject de-serializer
|
||||
public static Object readAdapterObject(Scriptable self,
|
||||
ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
Class superClass = Class.forName((String)in.readObject());
|
||||
|
||||
String[] interfaceNames = (String[])in.readObject();
|
||||
Class[] interfaces = new Class[interfaceNames.length];
|
||||
|
||||
for (int i=0; i < interfaceNames.length; i++)
|
||||
interfaces[i] = Class.forName(interfaceNames[i]);
|
||||
|
||||
Scriptable delegee = (Scriptable)in.readObject();
|
||||
|
||||
Class adapterClass = getAdapterClass(self, superClass, interfaces,
|
||||
delegee);
|
||||
|
||||
Class[] ctorParms = {
|
||||
ScriptRuntime.ScriptableClass,
|
||||
ScriptRuntime.ScriptableClass
|
||||
};
|
||||
Object[] ctorArgs = { delegee, self };
|
||||
try {
|
||||
return adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
|
||||
} catch(InstantiationException e) {
|
||||
} catch(IllegalAccessException e) {
|
||||
@ -463,7 +497,7 @@ public final class JavaAdapter
|
||||
* Make glue object implementing single-method interface cl that will
|
||||
* call the supplied JS function when called.
|
||||
*/
|
||||
static IFGlue makeIFGlue(Class cl, Function f)
|
||||
public static IFGlue makeIFGlue(Class cl, Function f)
|
||||
{
|
||||
ClassCache cache = ClassCache.get(f);
|
||||
Hashtable masters = cache.javaAdapterIFGlueMasters;
|
||||
|
@ -667,7 +667,7 @@ WrapFactory#wrap(Context cx, Scriptable scope, Object obj, Class)}
|
||||
reportConversionError(value, type, !useErrorHandler);
|
||||
}
|
||||
else if (type.isInterface()) {
|
||||
if (value instanceof Function) {
|
||||
if (value instanceof Function && adapter_makeIFGlue != null) {
|
||||
// Try to wrap function into interface with single method.
|
||||
Function f = (Function)value;
|
||||
|
||||
@ -686,7 +686,13 @@ WrapFactory#wrap(Context cx, Scriptable scope, Object obj, Class)}
|
||||
// Function was already wrapped
|
||||
return old;
|
||||
}
|
||||
Object glue = JavaAdapter.makeIFGlue(type, f);
|
||||
Object glue;
|
||||
Object[] args = { type, f };
|
||||
try {
|
||||
glue = adapter_makeIFGlue.invoke(null, args);
|
||||
} catch (Exception ex) {
|
||||
throw ScriptRuntime.throwAsUncheckedException(ex);
|
||||
}
|
||||
if (glue != null) {
|
||||
// Store for later retrival
|
||||
glue = so.associateValue(key, glue);
|
||||
@ -911,27 +917,15 @@ WrapFactory#wrap(Context cx, Scriptable scope, Object obj, Class)}
|
||||
if (javaObject != null) {
|
||||
Class joClass = javaObject.getClass();
|
||||
if (joClass.getName().startsWith("adapter")) {
|
||||
|
||||
out.writeBoolean(true);
|
||||
out.writeObject(joClass.getSuperclass().getName());
|
||||
|
||||
Class[] interfaces = joClass.getInterfaces();
|
||||
String[] interfaceNames = new String[interfaces.length];
|
||||
|
||||
for (int i=0; i < interfaces.length; i++)
|
||||
interfaceNames[i] = interfaces[i].getName();
|
||||
|
||||
out.writeObject(interfaceNames);
|
||||
|
||||
if (adapter_writeAdapterObject == null) {
|
||||
throw new IOException();
|
||||
}
|
||||
Object[] args = { javaObject, out };
|
||||
try {
|
||||
Object delegee
|
||||
= joClass.getField("delegee").get(javaObject);
|
||||
Object self
|
||||
= joClass.getField("self").get(javaObject);
|
||||
out.writeObject(delegee);
|
||||
out.writeObject(self);
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (NoSuchFieldException e) {
|
||||
adapter_writeAdapterObject.invoke(null, args);
|
||||
} catch (Exception ex) {
|
||||
throw new IOException();
|
||||
}
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
@ -955,17 +949,14 @@ WrapFactory#wrap(Context cx, Scriptable scope, Object obj, Class)}
|
||||
in.defaultReadObject();
|
||||
|
||||
if (in.readBoolean()) {
|
||||
Class superclass = Class.forName((String)in.readObject());
|
||||
|
||||
String[] interfaceNames = (String[])in.readObject();
|
||||
Class[] interfaces = new Class[interfaceNames.length];
|
||||
|
||||
for (int i=0; i < interfaceNames.length; i++)
|
||||
interfaces[i] = Class.forName(interfaceNames[i]);
|
||||
|
||||
javaObject = JavaAdapter.createAdapterClass(
|
||||
parent, superclass, interfaces,
|
||||
(Scriptable)in.readObject(), (Scriptable)in.readObject());
|
||||
if (adapter_readAdapterObject == null)
|
||||
throw new ClassNotFoundException();
|
||||
Object[] args = { this, in };
|
||||
try {
|
||||
javaObject = adapter_readAdapterObject.invoke(null, args);
|
||||
} catch (Exception ex) {
|
||||
throw new IOException();
|
||||
}
|
||||
} else {
|
||||
javaObject = in.readObject();
|
||||
}
|
||||
@ -997,4 +988,36 @@ WrapFactory#wrap(Context cx, Scriptable scope, Object obj, Class)}
|
||||
private transient Hashtable fieldAndMethods;
|
||||
|
||||
private static final Object COERCED_INTERFACE_KEY = new Object();
|
||||
private static Method adapter_makeIFGlue;
|
||||
private static Method adapter_writeAdapterObject;
|
||||
private static Method adapter_readAdapterObject;
|
||||
|
||||
static {
|
||||
// Reflection in java is verbose
|
||||
Class cl = Kit.classOrNull("org.mozilla.javascript.JavaAdapter");
|
||||
if (cl != null) {
|
||||
Class[] sig2 = new Class[2];
|
||||
try {
|
||||
sig2[0] = ScriptRuntime.ClassClass;
|
||||
sig2[1] = ScriptRuntime.FunctionClass;
|
||||
adapter_makeIFGlue = cl.getMethod("makeIFGlue", sig2);
|
||||
|
||||
sig2[0] = ScriptRuntime.ObjectClass;
|
||||
sig2[1] = Kit.classOrNull("java.io.ObjectOutputStream");
|
||||
adapter_writeAdapterObject = cl.getMethod("writeAdapterObject",
|
||||
sig2);
|
||||
|
||||
sig2[0] = ScriptRuntime.ScriptableClass;
|
||||
sig2[1] = Kit.classOrNull("java.io.ObjectInputStream");
|
||||
adapter_readAdapterObject = cl.getMethod("readAdapterObject",
|
||||
sig2);
|
||||
|
||||
} catch (Exception ex) {
|
||||
adapter_makeIFGlue = null;
|
||||
adapter_writeAdapterObject = null;
|
||||
adapter_readAdapterObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user