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:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user