зеркало из https://github.com/mozilla/pjs.git
JavaAdapter serialization contribution from Kemal Bayram.
This commit is contained in:
Родитель
86d6633b25
Коммит
35421e718f
|
@ -121,7 +121,10 @@ public class JavaAdapter extends ScriptableObject {
|
|||
ClassSignature sig = new ClassSignature(superClass, interfaces, obj);
|
||||
Class adapterClass = (Class) generatedClasses.get(sig);
|
||||
if (adapterClass == null) {
|
||||
String adapterName = "adapter" + serial++;
|
||||
String adapterName;
|
||||
synchronized (generatedClasses) {
|
||||
adapterName = "adapter" + serial++;
|
||||
}
|
||||
adapterClass = createAdapterClass(cx, obj, adapterName,
|
||||
superClass, interfaces,
|
||||
null, null);
|
||||
|
@ -134,6 +137,44 @@ public class JavaAdapter extends ScriptableObject {
|
|||
return getAdapterSelf(adapterClass, adapter);
|
||||
}
|
||||
|
||||
// Needed by NativeJavaObject de-serializer
|
||||
|
||||
public static Object createAdapterClass(Class superClass,
|
||||
Class[] interfaces,
|
||||
Scriptable obj, Scriptable self)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
ClassSignature sig = new ClassSignature(superClass, interfaces, obj);
|
||||
Class adapterClass = (Class) generatedClasses.get(sig);
|
||||
if (adapterClass == null) {
|
||||
String adapterName;
|
||||
synchronized (generatedClasses) {
|
||||
adapterName = "adapter" + serial++;
|
||||
}
|
||||
try {
|
||||
adapterClass = createAdapterClass(Context.enter(), obj,
|
||||
adapterName, superClass,
|
||||
interfaces, null, null);
|
||||
generatedClasses.put(sig, adapterClass);
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Class[] ctorParms = { Scriptable.class, Scriptable.class };
|
||||
Object[] ctorArgs = { obj, self };
|
||||
|
||||
return adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
|
||||
} catch(InstantiationException e) {
|
||||
} catch(IllegalAccessException e) {
|
||||
} catch(InvocationTargetException e) {
|
||||
} catch(NoSuchMethodException e) {
|
||||
}
|
||||
|
||||
throw new ClassNotFoundException("adapter");
|
||||
}
|
||||
|
||||
public static Class createAdapterClass(Context cx, Scriptable jsObj,
|
||||
String adapterName, Class superClass,
|
||||
Class[] interfaces,
|
||||
|
@ -158,6 +199,7 @@ public class JavaAdapter extends ScriptableObject {
|
|||
|
||||
String superName = superClass.getName().replace('.', '/');
|
||||
generateCtor(cfw, adapterName, superName);
|
||||
generateSerialCtor(cfw, adapterName, superName);
|
||||
if (scriptClassName != null)
|
||||
generateEmptyCtor(cfw, adapterName, superName, scriptClassName);
|
||||
|
||||
|
@ -379,7 +421,34 @@ public class JavaAdapter extends ScriptableObject {
|
|||
cfw.add(ByteCode.RETURN);
|
||||
cfw.stopMethod((short)20, null); // TODO: magic number "20"
|
||||
}
|
||||
|
||||
private static void generateSerialCtor(ClassFileWriter cfw, String adapterName,
|
||||
String superName)
|
||||
{
|
||||
cfw.startMethod("<init>",
|
||||
"(Lorg/mozilla/javascript/Scriptable;Lorg/mozilla/javascript/Scriptable;)V",
|
||||
ClassFileWriter.ACC_PUBLIC);
|
||||
|
||||
// Invoke base class constructor
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.INVOKESPECIAL, superName, "<init>", "()", "V");
|
||||
|
||||
// Save parameter in instance variable "delegee"
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.ALOAD_1); // first arg
|
||||
cfw.add(ByteCode.PUTFIELD, adapterName, "delegee",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
|
||||
// save self
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.ALOAD_2); // second arg
|
||||
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
|
||||
cfw.add(ByteCode.RETURN);
|
||||
cfw.stopMethod((short)20, null); // TODO: magic number "20"
|
||||
}
|
||||
|
||||
private static void generateEmptyCtor(ClassFileWriter cfw, String adapterName,
|
||||
String superName, String scriptClassName)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Norris Boyd
|
||||
* Frank Mitchell
|
||||
* Mike Shaver
|
||||
* Kemal Bayram
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
|
@ -38,6 +39,7 @@
|
|||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This class reflects Java arrays into the JavaScript environment.
|
||||
|
@ -152,4 +154,26 @@ public class NativeJavaArray extends NativeJavaObject {
|
|||
int length;
|
||||
Class cls;
|
||||
Scriptable prototype;
|
||||
|
||||
public void writeExternal(ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
super.writeExternal(out);
|
||||
|
||||
out.writeObject(array);
|
||||
out.writeInt(length);
|
||||
out.writeObject(cls.getName());
|
||||
out.writeObject(prototype);
|
||||
}
|
||||
|
||||
public void readExternal(ObjectInput in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
super.readExternal(in);
|
||||
|
||||
array = in.readObject();
|
||||
length = in.readInt();
|
||||
cls = Class.forName((String)in.readObject());
|
||||
prototype = (Scriptable)in.readObject();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Frank Mitchell
|
||||
* Mike Shaver
|
||||
* Kurt Westerfeld
|
||||
* Kemal Bayram
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
|
@ -40,6 +41,7 @@ package org.mozilla.javascript;
|
|||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Hashtable;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This class reflects Java classes into the JavaScript environment, mainly
|
||||
|
@ -272,4 +274,18 @@ public class NativeJavaClass extends NativeJavaObject implements Function {
|
|||
|
||||
// beard: need a scope for finding top-level prototypes.
|
||||
private Scriptable parent;
|
||||
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
super.writeExternal(out);
|
||||
out.writeObject(parent);
|
||||
}
|
||||
|
||||
public void readExternal(ObjectInput in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
super.readExternal(in);
|
||||
parent = (Scriptable)in.readObject();
|
||||
fieldAndMethods = members.getFieldAndMethodsObjects(this, javaObject,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Igor Bukanov
|
||||
* Frank Mitchell
|
||||
* Mike Shaver
|
||||
* Kemal Bayram
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
|
@ -38,6 +39,7 @@
|
|||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
@ -53,7 +55,10 @@ import java.util.Enumeration;
|
|||
* @see NativeJavaClass
|
||||
*/
|
||||
|
||||
public class NativeJavaObject implements Scriptable, Wrapper {
|
||||
public class NativeJavaObject implements Scriptable, Wrapper, Externalizable {
|
||||
|
||||
public NativeJavaObject() {
|
||||
}
|
||||
|
||||
public NativeJavaObject(Scriptable scope, Object javaObject,
|
||||
JavaMembers members)
|
||||
|
@ -68,6 +73,7 @@ public class NativeJavaObject implements Scriptable, Wrapper {
|
|||
{
|
||||
this.parent = scope;
|
||||
this.javaObject = javaObject;
|
||||
this.staticType = staticType;
|
||||
Class dynamicType = javaObject != null ? javaObject.getClass()
|
||||
: staticType;
|
||||
members = JavaMembers.lookupClass(scope, dynamicType, staticType);
|
||||
|
@ -918,9 +924,82 @@ public class NativeJavaObject implements Scriptable, Wrapper {
|
|||
|
||||
protected Object javaObject;
|
||||
protected JavaMembers members;
|
||||
protected Class staticType;
|
||||
private Hashtable fieldAndMethods;
|
||||
static Class jsObjectClass;
|
||||
static Constructor jsObjectCtor;
|
||||
static Method jsObjectGetScriptable;
|
||||
|
||||
public void writeExternal(ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeObject(prototype);
|
||||
out.writeObject(parent);
|
||||
out.writeObject(staticType != null ? staticType.getClass().getName()
|
||||
: null);
|
||||
|
||||
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);
|
||||
|
||||
try {
|
||||
out.writeObject(joClass.getField("delegee").get(javaObject));
|
||||
out.writeObject(joClass.getField("self").get(javaObject));
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
out.writeObject(javaObject);
|
||||
}
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
out.writeObject(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void readExternal(ObjectInput in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
prototype = (Scriptable)in.readObject();
|
||||
parent = (Scriptable)in.readObject();
|
||||
|
||||
String className = (String)in.readObject();
|
||||
staticType = className != null ? Class.forName(className) : null;
|
||||
|
||||
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(superclass, interfaces,
|
||||
(Scriptable)in.readObject(), (Scriptable)in.readObject());
|
||||
} else {
|
||||
javaObject = in.readObject();
|
||||
}
|
||||
|
||||
Class dynamicType = javaObject != null ? javaObject.getClass()
|
||||
: staticType;
|
||||
members = JavaMembers.lookupClass(parent, dynamicType, staticType);
|
||||
fieldAndMethods = members.getFieldAndMethodsObjects(this, javaObject,
|
||||
false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче