Use reflection to access JavaAdapter to allow to use NativeJavaObject with JavaAdapter classes absent.

This commit is contained in:
igor%mir2.org 2003-11-03 19:55:37 +00:00
parent 04d207ce3a
commit 7d26c9eb27
2 changed files with 104 additions and 47 deletions

View File

@ -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;

View File

@ -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;
}
}
}
}