Skip to content

Commit

Permalink
* Implement proper serialization proxies to fix serialization of Java…
Browse files Browse the repository at this point in the history
…script objects/functions.
  • Loading branch information
hns committed Feb 6, 2008
1 parent 2d12eed commit 3d85121
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 33 deletions.
45 changes: 12 additions & 33 deletions src/helma/scripting/rhino/RhinoEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -523,15 +523,17 @@ public DocApplication getDoc() {
*/
public void serialize(Object obj, OutputStream out) throws IOException {
core.contextFactory.enter();
engines.set(this);
try {
// use a special ScriptableOutputStream that unwraps Wrappers
ScriptableOutputStream sout = new ScriptableOutputStream(out, core.global) {
protected Object replaceObject(Object obj) throws IOException {
// FIXME doesn't work because we need a transactor thread for deserialization
// if (obj instanceof Wrapper)
// obj = ((Wrapper) obj).unwrap();
// if (obj instanceof helma.objectmodel.db.Node)
// return ((helma.objectmodel.db.Node) obj).getHandle();
if (obj instanceof HopObject)
return new HopObjectProxy((HopObject) obj);
if (obj instanceof helma.objectmodel.db.Node)
return new HopObjectProxy((helma.objectmodel.db.Node) obj);
if (obj instanceof GlobalObject)
return new GlobalProxy((GlobalObject) obj);
if (obj instanceof ApplicationBean)
return new ScriptBeanProxy("app");
if (obj instanceof RequestBean)
Expand All @@ -543,8 +545,8 @@ protected Object replaceObject(Object obj) throws IOException {
return super.replaceObject(obj);
}
};
sout.addExcludedName("Xml");
sout.addExcludedName("global");
// sout.addExcludedName("Xml");
// sout.addExcludedName("global");

sout.writeObject(obj);
sout.flush();
Expand All @@ -564,15 +566,12 @@ protected Object replaceObject(Object obj) throws IOException {
*/
public Object deserialize(InputStream in) throws IOException, ClassNotFoundException {
core.contextFactory.enter();
engines.set(this);
try {
ObjectInputStream sin = new ScriptableInputStream(in, core.global) {
protected Object resolveObject(Object obj) throws IOException {
if (obj instanceof NodeHandle) {
// FIXME doesn't work unless we have a transactor thread
// Object node = ((NodeHandle) obj).getNode(app.getNodeManager().safe);
// return Context.toObject(node, global);
} else if (obj instanceof ScriptBeanProxy) {
return ((ScriptBeanProxy) obj).getObject();
if (obj instanceof SerializationProxy) {
return ((SerializationProxy) obj).getObject(RhinoEngine.this);
}
return super.resolveObject(obj);
}
Expand Down Expand Up @@ -687,24 +686,4 @@ public Skin getSkin(String protoName, String skinName) throws IOException {
return skin;
}

/**
* Serialization proxy for app, req, res, path objects.
*/
class ScriptBeanProxy implements Serializable {
String name;

ScriptBeanProxy(String name) {
this.name = name;
}

/**
* Lookup the actual object in the current scope
* @return the object represented by this proxy
*/
Object getObject() {
return global.get(name, global);
}

}

}
113 changes: 113 additions & 0 deletions src/helma/scripting/rhino/SerializationProxy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 2008 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/

package helma.scripting.rhino;

import helma.objectmodel.INode;
import helma.objectmodel.db.NodeHandle;
import org.mozilla.javascript.Context;

import java.io.Serializable;

/**
* Serialization proxy/placeholder interface. This is used for
* for various Helma and Rhino related classes..
*/
public interface SerializationProxy extends Serializable {
public Object getObject(RhinoEngine engine);
}

/**
* Serialization proxy for app, req, res, path objects.
*/
class ScriptBeanProxy implements SerializationProxy {
String name;

ScriptBeanProxy(String name) {
this.name = name;
}

/**
* Lookup the actual object in the current scope
*
* @return the object represented by this proxy
*/
public Object getObject(RhinoEngine engine) {
return engine.global.get(name, engine.global);
}

}

/**
* Serialization proxy for global scope
*/
class GlobalProxy implements SerializationProxy {
boolean shared;

GlobalProxy(GlobalObject scope) {
shared = !scope.isThreadScope;
}

/**
* Lookup the actual object in the current scope
*
* @return the object represented by this proxy
*/
public Object getObject(RhinoEngine engine) {
return shared ? engine.core.global : engine.global;
}
}

/**
* Serialization proxy for various flavors of HopObjects/Nodes
*/
class HopObjectProxy implements SerializationProxy {
Object ref;
boolean wrapped = false;

HopObjectProxy(HopObject obj) {
INode n = obj.getNode();
if (n == null)
ref = obj.getClassName();
else {
if (n instanceof helma.objectmodel.db.Node)
ref = new NodeHandle(((helma.objectmodel.db.Node) n).getKey());
else
ref = n;
}
wrapped = true;
}

HopObjectProxy(helma.objectmodel.db.Node node) {
ref = new NodeHandle(node.getKey());
}

/**
* Lookup the actual object in the current scope
*
* @return the object represented by this proxy
*/
public Object getObject(RhinoEngine engine) {
if (ref instanceof String)
return engine.core.getPrototype((String) ref);
else if (ref instanceof NodeHandle) {
Object n = ((NodeHandle) ref).getNode(engine.app.getWrappedNodeManager());
return wrapped ? Context.toObject(n, engine.global) : n;
}
return Context.toObject(ref, engine.global);
}

}

0 comments on commit 3d85121

Please sign in to comment.