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, Long.class,
Float.class, Float.class,
Double.class, Double.class,
Class.class,
String.class, String.class,
boolean[].class, boolean[].class,
byte[].class, byte[].class,
@@ -68,6 +69,7 @@ public class BasicStreamers
new LongStreamer(), new LongStreamer(),
new FloatStreamer(), new FloatStreamer(),
new DoubleStreamer(), new DoubleStreamer(),
new ClassStreamer(),
new StringStreamer(), new StringStreamer(),
new BooleanArrayStreamer(), new BooleanArrayStreamer(),
new ByteArrayStreamer(), 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. */ /** Streams {@link String} instances. */
public static class StringStreamer extends BasicStreamer public static class StringStreamer extends BasicStreamer
{ {
@@ -76,8 +76,38 @@ public class ObjectInputStream extends DataInputStream
public Object readObject () public Object readObject ()
throws IOException, ClassNotFoundException 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 // create our classmap if necessary
if (_classmap == null) { if (_classmap == null) {
_classmap = new ArrayList<ClassMapping>(); _classmap = new ArrayList<ClassMapping>();
@@ -85,15 +115,11 @@ public class ObjectInputStream extends DataInputStream
_classmap.add(null); _classmap.add(null);
} }
try {
// read in the class code for this instance // read in the class code for this instance
short code = readShort(); short code = readShort();
// a zero code indicates a null value // a zero code indicates a null value
if (code == 0) { if (code == 0) {
if (STREAM_DEBUG) {
log.info(hashCode() + ": Read null.");
}
return null; return null;
// if the code is negative, that means that we've never seen it before and class // 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 // create the class mapping
cmap = mapClass(code, cname); return mapClass(code, cname);
} else { } else {
cmap = _classmap.get(code); ClassMapping cmap = _classmap.get(code);
// sanity check // sanity check
if (cmap == null) { if (cmap == null) {
@@ -129,19 +155,7 @@ public class ObjectInputStream extends DataInputStream
"metadata [code=" + code + "]"; "metadata [code=" + code + "]";
throw new RuntimeException(errmsg); throw new RuntimeException(errmsg);
} }
} return cmap;
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);
} }
} }
@@ -71,13 +71,25 @@ public class ObjectOutputStream extends DataOutputStream
return; 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 // create our classmap if necessary
if (_classmap == null) { if (_classmap == null) {
_classmap = new HashMap<Class<?>, ClassMapping>(); _classmap = new HashMap<Class<?>, ClassMapping>();
} }
// otherwise, look up the class mapping record // look up the class mapping record
Class<?> sclass = Streamer.getStreamerClass(object);
ClassMapping cmap = _classmap.get(sclass); ClassMapping cmap = _classmap.get(sclass);
// create a class mapping for this class if we've not got one // create a class mapping for this class if we've not got one
@@ -103,8 +115,7 @@ public class ObjectOutputStream extends DataOutputStream
} else { } else {
writeExistingClassMapping(cmap); writeExistingClassMapping(cmap);
} }
return cmap;
writeBareObject(object, cmap.streamer, true);
} }
/** /**