Allow streaming Class references.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5524 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Andrzej Kapolka
2008-11-08 01:57:42 +00:00
parent 4b9477ca91
commit 28c7609df8
3 changed files with 97 additions and 52 deletions
@@ -44,6 +44,7 @@ public class BasicStreamers
Long.class,
Float.class,
Double.class,
Class.class,
String.class,
boolean[].class,
byte[].class,
@@ -68,6 +69,7 @@ public class BasicStreamers
new LongStreamer(),
new FloatStreamer(),
new DoubleStreamer(),
new ClassStreamer(),
new StringStreamer(),
new BooleanArrayStreamer(),
new ByteArrayStreamer(),
@@ -225,6 +227,24 @@ public class BasicStreamers
}
}
/** Streams {@link Class} instances. */
public static class ClassStreamer extends BasicStreamer
{
@Override
public Object createObject (ObjectInputStream in)
throws IOException, ClassNotFoundException
{
return in.readClassMapping().sclass;
}
@Override
public void writeObject (Object object, ObjectOutputStream out, boolean useWriter)
throws IOException
{
out.writeClassMapping((Class)object);
}
}
/** Streams {@link String} instances. */
public static class StringStreamer extends BasicStreamer
{
@@ -76,8 +76,38 @@ public class ObjectInputStream extends DataInputStream
public Object readObject ()
throws IOException, ClassNotFoundException
{
ClassMapping cmap;
try {
// read the class mapping
ClassMapping cmap = readClassMapping();
if (cmap == null) {
if (STREAM_DEBUG) {
log.info(hashCode() + ": Read null.");
}
return null;
}
if (STREAM_DEBUG) {
log.info(hashCode() + ": Reading with " + cmap.streamer + ".");
}
// create an instance of the appropriate object
Object target = cmap.streamer.createObject(this);
readBareObject(target, cmap.streamer, true);
return target;
} catch (OutOfMemoryError oome) {
throw (IOException)new IOException("Malformed object data").initCause(oome);
}
}
/**
* Reads a class mapping from the stream.
*
* @return the class mapping, or <code>null</code> to represent a null value.
*/
protected ClassMapping readClassMapping ()
throws IOException, ClassNotFoundException
{
// create our classmap if necessary
if (_classmap == null) {
_classmap = new ArrayList<ClassMapping>();
@@ -85,15 +115,11 @@ public class ObjectInputStream extends DataInputStream
_classmap.add(null);
}
try {
// read in the class code for this instance
short code = readShort();
// a zero code indicates a null value
if (code == 0) {
if (STREAM_DEBUG) {
log.info(hashCode() + ": Read null.");
}
return null;
// if the code is negative, that means that we've never seen it before and class
@@ -114,10 +140,10 @@ public class ObjectInputStream extends DataInputStream
}
// create the class mapping
cmap = mapClass(code, cname);
return mapClass(code, cname);
} else {
cmap = _classmap.get(code);
ClassMapping cmap = _classmap.get(code);
// sanity check
if (cmap == null) {
@@ -129,19 +155,7 @@ public class ObjectInputStream extends DataInputStream
"metadata [code=" + code + "]";
throw new RuntimeException(errmsg);
}
}
if (STREAM_DEBUG) {
log.info(hashCode() + ": Reading with " + cmap.streamer + ".");
}
// create an instance of the appropriate object
Object target = cmap.streamer.createObject(this);
readBareObject(target, cmap.streamer, true);
return target;
} catch (OutOfMemoryError oome) {
throw (IOException)new IOException("Malformed object data").initCause(oome);
return cmap;
}
}
@@ -71,13 +71,25 @@ public class ObjectOutputStream extends DataOutputStream
return;
}
// otherwise, write the class mapping, then the bare object
Class<?> sclass = Streamer.getStreamerClass(object);
ClassMapping cmap = writeClassMapping(sclass);
writeBareObject(object, cmap.streamer, true);
}
/**
* Retrieves or creates the class mapping for the supplied class, writes it out to the stream,
* and returns a reference to it.
*/
protected ClassMapping writeClassMapping (Class<?> sclass)
throws IOException
{
// create our classmap if necessary
if (_classmap == null) {
_classmap = new HashMap<Class<?>, ClassMapping>();
}
// otherwise, look up the class mapping record
Class<?> sclass = Streamer.getStreamerClass(object);
// look up the class mapping record
ClassMapping cmap = _classmap.get(sclass);
// create a class mapping for this class if we've not got one
@@ -103,8 +115,7 @@ public class ObjectOutputStream extends DataOutputStream
} else {
writeExistingClassMapping(cmap);
}
writeBareObject(object, cmap.streamer, true);
return cmap;
}
/**