diff options
| author | slewis | 2005-03-17 06:37:31 +0000 |
|---|---|---|
| committer | slewis | 2005-03-17 06:37:31 +0000 |
| commit | dd20a57e6942292b88a1dcdfe4399be48790500c (patch) | |
| tree | 05763f59663301402315e3854ba4a41e916cd252 | |
| parent | 862d3f0097f894c8d9c320bd2b205b463c55313b (diff) | |
| download | org.eclipse.ecf-dd20a57e6942292b88a1dcdfe4399be48790500c.tar.gz org.eclipse.ecf-dd20a57e6942292b88a1dcdfe4399be48790500c.tar.xz org.eclipse.ecf-dd20a57e6942292b88a1dcdfe4399be48790500c.zip | |
Added mechanism and interfaces to support the name-based lookup of classloaders during object deserialization. When shared objects send messages to remote replicas (via ISharedObjectContext.sendMessage(ID,message)), the provided message class is annotated on the IdentifiableObjectOutputStream with the shared object ID (actually the sharedobjectid.getName() value). When received, the name is read and the IdentifiableObjectOutputStream does a lookup on a container-provided instance of IClassLoaderMapper, to map a name to a classloader. In most implementations, the container will compare this name against it's known set of shared objects, and if found it will use that object's classloader to attempt to load the class for deserialization. In this way, shared objects can serialize and deserialize classes that are not known to the container/provider's classloader.
6 files changed, 72 insertions, 21 deletions
diff --git a/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ClientSOContainer.java b/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ClientSOContainer.java index 0ac846b00..78f0e0b4b 100644 --- a/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ClientSOContainer.java +++ b/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ClientSOContainer.java @@ -271,7 +271,7 @@ public abstract class ClientSOContainer extends SOContainer { synchronized (connection) { try { connection.sendSynch(groupID, - getBytesForObject(ContainerMessage + serializeObject(ContainerMessage .makeLeaveGroupMessage(getID(), groupID, getNextSequenceNumber(), @@ -301,7 +301,7 @@ public abstract class ClientSOContainer extends SOContainer { throws IOException { // Do it connection.sendAsynch(message.getToContainerID(), - getBytesForObject(message)); + serializeObject(message)); } protected void forwardExcluding(ID from, ID excluding, byte msg, diff --git a/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/SOContainer.java b/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/SOContainer.java index fd984a73b..491311695 100644 --- a/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/SOContainer.java +++ b/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/SOContainer.java @@ -11,6 +11,7 @@ package org.eclipse.ecf.provider.generic; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; @@ -44,7 +45,10 @@ import org.eclipse.ecf.core.events.SharedObjectContainerDepartedEvent; import org.eclipse.ecf.core.events.SharedObjectContainerDisposeEvent; import org.eclipse.ecf.core.identity.ID; import org.eclipse.ecf.core.util.Event; +import org.eclipse.ecf.core.util.IClassLoaderMapper; import org.eclipse.ecf.core.util.IQueueEnqueue; +import org.eclipse.ecf.core.util.IdentifiableObjectInputStream; +import org.eclipse.ecf.core.util.IdentifiableObjectOutputStream; import org.eclipse.ecf.provider.Trace; import org.eclipse.ecf.provider.generic.gmm.Member; @@ -477,7 +481,7 @@ public abstract class SOContainer implements ISharedObjectContainer { return null; } - protected byte[] getBytesForObject(Serializable obj) throws IOException { + protected byte[] serializeObject(Serializable obj) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); @@ -556,7 +560,7 @@ public abstract class SOContainer implements ISharedObjectContainer { return sequenceNumber++; } - protected ContainerMessage getObjectFromBytes(byte[] bytes) + protected ContainerMessage deserializeContainerMessage(byte[] bytes) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); @@ -741,11 +745,21 @@ public abstract class SOContainer implements ISharedObjectContainer { long seq = mess.getSequence(); ContainerMessage.SharedObjectMessage resp = (ContainerMessage.SharedObjectMessage) mess .getData(); + + // Get bytes from SharedObjectMessage instance + byte [] databytes = (byte []) resp.getData(); + Serializable obj = null; + try { + obj = (Serializable) deserializeSharedObjectMessage(databytes); + } catch (ClassNotFoundException e) { + dumpStack("Classnotfoundexception in handleSharedObjectMessage",e); + e.printStackTrace(System.err); + } synchronized (getGroupMembershipLock()) { SOWrapper sow = getSharedObjectWrapper(resp .getFromSharedObjectID()); if (sow != null) { - sow.deliverSharedObjectMessage(fromID, resp.getData()); + sow.deliverSharedObjectMessage(fromID, obj); } forward(fromID, toID, mess); } @@ -921,7 +935,7 @@ public abstract class SOContainer implements ISharedObjectContainer { if (!(obj instanceof byte[])) { debug("Ignoring event without valid data " + e); } - ContainerMessage mess = validateContainerMessage(getObjectFromBytes((byte[]) obj)); + ContainerMessage mess = validateContainerMessage(deserializeContainerMessage((byte[]) obj)); if (mess == null) { return; } @@ -970,7 +984,7 @@ public abstract class SOContainer implements ISharedObjectContainer { protected Serializable processSynch(SynchConnectionEvent e) throws IOException { debug("processSynch:" + e); - ContainerMessage mess = getObjectFromBytes((byte[]) e.getData()); + ContainerMessage mess = deserializeContainerMessage((byte[]) e.getData()); Serializable data = mess.getData(); // Must be non null if (data != null && data instanceof ContainerMessage.LeaveGroupMessage) { @@ -1081,16 +1095,50 @@ public abstract class SOContainer implements ISharedObjectContainer { } } + protected byte [] serializeSharedObjectMessage(ID sharedObjectID, Object message) throws IOException { + if (!(message instanceof Serializable)) throw new NotSerializableException("sharedobjectmessage "+message+" not serializable"); + ByteArrayOutputStream bouts = new ByteArrayOutputStream(); + IdentifiableObjectOutputStream ioos = new IdentifiableObjectOutputStream(sharedObjectID,bouts); + ioos.writeObject(message); + return bouts.toByteArray(); + } + protected Object deserializeSharedObjectMessage(byte [] bytes) throws IOException, ClassNotFoundException { + ByteArrayInputStream bins = new ByteArrayInputStream(bytes); + IdentifiableObjectInputStream iins = new IdentifiableObjectInputStream(new IClassLoaderMapper() { + public ClassLoader mapNameToClassLoader(String name) { + ISharedObjectManager manager = getSharedObjectManager(); + ID [] ids = manager.getSharedObjectIDs(); + ID found = null; + for(int i=0; i < ids.length; i++) { + ID id = ids[i]; + if (name.equals(id.getName())) { + found = id; + break; + } + } + if (found == null) return null; + ISharedObject obj = manager.getSharedObject(found); + if (obj == null) return null; + return obj.getClass().getClassLoader(); + } + + },bins); + Object obj = iins.readObject(); + return obj; + } protected void sendMessage(ID toContainerID, ID sharedObjectID, Object message) throws IOException { if (message == null) return; + byte [] sendData = serializeSharedObjectMessage(sharedObjectID,message); sendSharedObjectMessage(toContainerID, sharedObjectID, - (Serializable) message); + sendData); } protected void sendSharedObjectMessage(ID toContainerID, ID fromSharedObject, Serializable data) throws IOException { + + sendMessage(ContainerMessage.makeSharedObjectMessage(getID(), toContainerID, getNextSequenceNumber(), fromSharedObject, data)); } diff --git a/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ServerSOContainer.java b/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ServerSOContainer.java index ff5e88b8b..c43824b38 100644 --- a/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ServerSOContainer.java +++ b/framework/bundles/org.eclipse.ecf.provider/src/org/eclipse/ecf/provider/generic/ServerSOContainer.java @@ -59,7 +59,7 @@ public class ServerSOContainer extends SOContainer implements ISharedObjectConta .getToContainerID()); if (conn != null) conn.sendAsynch(message.getToContainerID(), - getBytesForObject(message)); + serializeObject(message)); } } @@ -84,7 +84,7 @@ public class ServerSOContainer extends SOContainer implements ISharedObjectConta if (conn != null) { try { conn.sendAsynch(oldID, - getBytesForObject(new ContainerMessage( + serializeObject(new ContainerMessage( from, oldID, getNextSequenceNumber(), data .getData()))); @@ -191,7 +191,7 @@ public class ServerSOContainer extends SOContainer implements ISharedObjectConta if (conn == null) return; try { - conn.sendSynch(memberID, getBytesForObject(ContainerMessage + conn.sendSynch(memberID, serializeObject(ContainerMessage .makeLeaveGroupMessage(getID(), memberID, getNextSequenceNumber(), reason))); } catch (Exception e) { @@ -246,7 +246,7 @@ public class ServerSOContainer extends SOContainer implements ISharedObjectConta if (conn != null) { try { conn.sendAsynch(message.getToContainerID(), - getBytesForObject(message)); + serializeObject(message)); } catch (IOException e) { logException("Exception in queueToAll for ContainerMessage "+message,e); } diff --git a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IClassLoaderMapper.java b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IClassLoaderMapper.java index 4a4635e25..0d142443a 100644 --- a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IClassLoaderMapper.java +++ b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IClassLoaderMapper.java @@ -9,10 +9,14 @@ package org.eclipse.ecf.core.util; -import org.eclipse.ecf.core.identity.ID; - +/** + * Map a given name onto a classloader. The container that provides an IClassLoaderMapper to + * the constructor of an IdentifiableObjectInputStream can use the name provided to lookup + * a shared object of same name and map that name to a classloader instance + * + */ public interface IClassLoaderMapper { - public ClassLoader mapIDToClassLoader(ID id); + public ClassLoader mapNameToClassLoader(String name); } diff --git a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectInputStream.java b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectInputStream.java index 1ca8f187e..41e11e5ee 100644 --- a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectInputStream.java +++ b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectInputStream.java @@ -14,7 +14,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; -import org.eclipse.ecf.core.identity.ID; /** * Restores Java objects from the underlying stream by using the classloader @@ -40,12 +39,11 @@ public class IdentifiableObjectInputStream extends ObjectInputStream { */ protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - - ID annotateID = (ID) readObject(); - if (annotateID == null || mapper == null) { + String name = readUTF(); + if (name == null || mapper == null) { return super.resolveClass(desc); } else { - ClassLoader cl = mapper.mapIDToClassLoader(annotateID); + ClassLoader cl = mapper.mapNameToClassLoader(name); if (cl == null) return super.resolveClass(desc); else return cl.loadClass(desc.getName()); } diff --git a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectOutputStream.java b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectOutputStream.java index 07b6db021..8b0ec92e2 100644 --- a/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectOutputStream.java +++ b/framework/bundles/org.eclipse.ecf/src/org/eclipse/ecf/core/util/IdentifiableObjectOutputStream.java @@ -37,7 +37,8 @@ public class IdentifiableObjectOutputStream extends ObjectOutputStream { * @see java.io.ObjectOutputStream#annotateClass(java.lang.Class) */ protected void annotateClass(Class cl) throws IOException { - writeObject(objectID); + String name = objectID.getName(); + writeUTF(name); } } |
