зеркало из 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);
|
ClassSignature sig = new ClassSignature(superClass, interfaces, obj);
|
||||||
Class adapterClass = (Class) generatedClasses.get(sig);
|
Class adapterClass = (Class) generatedClasses.get(sig);
|
||||||
if (adapterClass == null) {
|
if (adapterClass == null) {
|
||||||
String adapterName = "adapter" + serial++;
|
String adapterName;
|
||||||
|
synchronized (generatedClasses) {
|
||||||
|
adapterName = "adapter" + serial++;
|
||||||
|
}
|
||||||
adapterClass = createAdapterClass(cx, obj, adapterName,
|
adapterClass = createAdapterClass(cx, obj, adapterName,
|
||||||
superClass, interfaces,
|
superClass, interfaces,
|
||||||
null, null);
|
null, null);
|
||||||
|
@ -134,6 +137,44 @@ public class JavaAdapter extends ScriptableObject {
|
||||||
return getAdapterSelf(adapterClass, adapter);
|
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,
|
public static Class createAdapterClass(Context cx, Scriptable jsObj,
|
||||||
String adapterName, Class superClass,
|
String adapterName, Class superClass,
|
||||||
Class[] interfaces,
|
Class[] interfaces,
|
||||||
|
@ -158,6 +199,7 @@ public class JavaAdapter extends ScriptableObject {
|
||||||
|
|
||||||
String superName = superClass.getName().replace('.', '/');
|
String superName = superClass.getName().replace('.', '/');
|
||||||
generateCtor(cfw, adapterName, superName);
|
generateCtor(cfw, adapterName, superName);
|
||||||
|
generateSerialCtor(cfw, adapterName, superName);
|
||||||
if (scriptClassName != null)
|
if (scriptClassName != null)
|
||||||
generateEmptyCtor(cfw, adapterName, superName, scriptClassName);
|
generateEmptyCtor(cfw, adapterName, superName, scriptClassName);
|
||||||
|
|
||||||
|
@ -379,7 +421,34 @@ public class JavaAdapter extends ScriptableObject {
|
||||||
cfw.add(ByteCode.RETURN);
|
cfw.add(ByteCode.RETURN);
|
||||||
cfw.stopMethod((short)20, null); // TODO: magic number "20"
|
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,
|
private static void generateEmptyCtor(ClassFileWriter cfw, String adapterName,
|
||||||
String superName, String scriptClassName)
|
String superName, String scriptClassName)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
* Norris Boyd
|
* Norris Boyd
|
||||||
* Frank Mitchell
|
* Frank Mitchell
|
||||||
* Mike Shaver
|
* Mike Shaver
|
||||||
|
* Kemal Bayram
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the
|
* Alternatively, the contents of this file may be used under the
|
||||||
* terms of the GNU Public License (the "GPL"), in which case the
|
* terms of the GNU Public License (the "GPL"), in which case the
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
package org.mozilla.javascript;
|
package org.mozilla.javascript;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class reflects Java arrays into the JavaScript environment.
|
* This class reflects Java arrays into the JavaScript environment.
|
||||||
|
@ -152,4 +154,26 @@ public class NativeJavaArray extends NativeJavaObject {
|
||||||
int length;
|
int length;
|
||||||
Class cls;
|
Class cls;
|
||||||
Scriptable prototype;
|
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
|
* Frank Mitchell
|
||||||
* Mike Shaver
|
* Mike Shaver
|
||||||
* Kurt Westerfeld
|
* Kurt Westerfeld
|
||||||
|
* Kemal Bayram
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the
|
* Alternatively, the contents of this file may be used under the
|
||||||
* terms of the GNU Public License (the "GPL"), in which case 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.lang.reflect.*;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class reflects Java classes into the JavaScript environment, mainly
|
* 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.
|
// beard: need a scope for finding top-level prototypes.
|
||||||
private Scriptable parent;
|
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
|
* Igor Bukanov
|
||||||
* Frank Mitchell
|
* Frank Mitchell
|
||||||
* Mike Shaver
|
* Mike Shaver
|
||||||
|
* Kemal Bayram
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the
|
* Alternatively, the contents of this file may be used under the
|
||||||
* terms of the GNU Public License (the "GPL"), in which case the
|
* terms of the GNU Public License (the "GPL"), in which case the
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
|
|
||||||
package org.mozilla.javascript;
|
package org.mozilla.javascript;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
@ -53,7 +55,10 @@ import java.util.Enumeration;
|
||||||
* @see NativeJavaClass
|
* @see NativeJavaClass
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NativeJavaObject implements Scriptable, Wrapper {
|
public class NativeJavaObject implements Scriptable, Wrapper, Externalizable {
|
||||||
|
|
||||||
|
public NativeJavaObject() {
|
||||||
|
}
|
||||||
|
|
||||||
public NativeJavaObject(Scriptable scope, Object javaObject,
|
public NativeJavaObject(Scriptable scope, Object javaObject,
|
||||||
JavaMembers members)
|
JavaMembers members)
|
||||||
|
@ -68,6 +73,7 @@ public class NativeJavaObject implements Scriptable, Wrapper {
|
||||||
{
|
{
|
||||||
this.parent = scope;
|
this.parent = scope;
|
||||||
this.javaObject = javaObject;
|
this.javaObject = javaObject;
|
||||||
|
this.staticType = staticType;
|
||||||
Class dynamicType = javaObject != null ? javaObject.getClass()
|
Class dynamicType = javaObject != null ? javaObject.getClass()
|
||||||
: staticType;
|
: staticType;
|
||||||
members = JavaMembers.lookupClass(scope, dynamicType, staticType);
|
members = JavaMembers.lookupClass(scope, dynamicType, staticType);
|
||||||
|
@ -918,9 +924,82 @@ public class NativeJavaObject implements Scriptable, Wrapper {
|
||||||
|
|
||||||
protected Object javaObject;
|
protected Object javaObject;
|
||||||
protected JavaMembers members;
|
protected JavaMembers members;
|
||||||
|
protected Class staticType;
|
||||||
private Hashtable fieldAndMethods;
|
private Hashtable fieldAndMethods;
|
||||||
static Class jsObjectClass;
|
static Class jsObjectClass;
|
||||||
static Constructor jsObjectCtor;
|
static Constructor jsObjectCtor;
|
||||||
static Method jsObjectGetScriptable;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче