Let's actually use them fancy little methods.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4695 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2007-05-07 19:19:33 +00:00
parent 8df35549df
commit 2afd7b2e29
2 changed files with 82 additions and 6 deletions
@@ -22,9 +22,13 @@
package com.threerings.io;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import static com.threerings.NaryaLog.log;
/**
* Used to read and write a single field of a {@link Streamable} instance.
*/
@@ -53,6 +57,25 @@ public abstract class FieldMarshaller
createMarshallers();
}
// first look to see if this field has custom reader/writer methods
Method reader = null, writer = null;
try {
reader = field.getDeclaringClass().getMethod(
getReaderMethodName(field.getName()), READER_ARGS);
writer = field.getDeclaringClass().getMethod(
getWriterMethodName(field.getName()), WRITER_ARGS);
return new MethodFieldMarshaller(reader, writer);
} catch (NoSuchMethodException nsme) {
// no problem
}
if ((reader != null || writer != null) && (reader == null || writer == null)) {
log.warning("Class contains one but not both custom field reader and writer " +
"[class=" + field.getDeclaringClass().getName() +
", field=" + field.getName() + ", reader=" + reader +
", writer=" + writer + "].");
// fall through to using reflection on the fields...
}
Class ftype = field.getType();
if (ftype.isInterface()) {
// if the class is a pure interface, use Object.
@@ -70,6 +93,24 @@ public abstract class FieldMarshaller
return fm;
}
/**
* Returns the name of the custom reader method which will be used if it exists to stream a
* field with the supplied name.
*/
public static final String getReaderMethodName (String field)
{
return "readField_" + field;
}
/**
* Returns the name of the custom writer method which will be used if it exists to stream a
* field with the supplied name.
*/
public static final String getWriterMethodName (String field)
{
return "writeField_" + field;
}
/**
* Used to marshall and unmarshall classes for which we have a basic {@link Streamer}.
*/
@@ -110,6 +151,34 @@ public abstract class FieldMarshaller
protected Streamer _streamer;
}
/**
* Uses custom reader and writer methods to read and write a field.
*/
protected static class MethodFieldMarshaller extends FieldMarshaller
{
public MethodFieldMarshaller (Method reader, Method writer)
{
_reader = reader;
_writer = writer;
}
// documentation inherited
public void readField (Field field, Object target, ObjectInputStream in)
throws Exception
{
_reader.invoke(target, in);
}
// documentation inherited
public void writeField (Field field, Object source, ObjectOutputStream out)
throws Exception
{
_writer.invoke(source, out);
}
protected Method _reader, _writer;
}
/**
* Creates instances of all known field marshaller types and populates the {@link
* #_marshallers} table with them. This is called the first time a marshaller is requested.
@@ -240,4 +309,10 @@ public abstract class FieldMarshaller
/** Contains a mapping from field type to field marshaller instance for that type. */
protected static HashMap<Class,FieldMarshaller> _marshallers;
/** Defines the signature to a custom field reader method. */
protected static final Class[] READER_ARGS = { ObjectInputStream.class };
/** Defines the signature to a custom field writer method. */
protected static final Class[] WRITER_ARGS = { ObjectOutputStream.class };
}
@@ -45,6 +45,7 @@ import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import com.samskivert.io.StreamUtil;
import com.threerings.io.FieldMarshaller;
import com.threerings.io.Streamable;
/**
@@ -154,8 +155,6 @@ public class InstrumentStreamableTask extends Task
protected void processStreamable (File source, CtClass clazz)
throws NotFoundException
{
// System.err.println("Processing " + clazz.getName() + "...");
ArrayList<CtField> fields = new ArrayList<CtField>();
for (CtField field : clazz.getDeclaredFields()) {
int modifiers = field.getModifiers();
@@ -173,13 +172,13 @@ public class InstrumentStreamableTask extends Task
int added = 0;
for (CtField field : fields) {
String rname = "readField_" + field.getName();
String rname = FieldMarshaller.getReaderMethodName(field.getName());
if (!methods.contains(rname)) {
String reader =
"public void " + rname + " (com.threerings.io.ObjectInputStream ins) {\n" +
" " + field.getName() + " = " + getFieldReader(field) + ";\n" +
"}";
// System.err.println("Adding reader " + clazz.getName() + "." + rname);
// System.out.println("Adding reader " + clazz.getName() + "." + rname);
try {
clazz.addMethod(CtNewMethod.make(reader, clazz));
added++;
@@ -189,9 +188,10 @@ public class InstrumentStreamableTask extends Task
System.err.println(reader);
}
}
String wname = "writeField_" + field.getName();
String wname = FieldMarshaller.getWriterMethodName(field.getName());
if (!methods.contains(wname)) {
// System.err.println("Adding writer " + clazz.getName() + "." + wname);
// System.out.println("Adding writer " + clazz.getName() + "." + wname);
String writer =
"public void " + wname + " (com.threerings.io.ObjectOutputStream out) {\n" +
" out." + getFieldWriter(field) + ";\n" +
@@ -209,6 +209,7 @@ public class InstrumentStreamableTask extends Task
if (added > 0) {
try {
System.out.println("Instrumented '" + clazz.getName() + "'.");
clazz.writeFile(_outdir.getPath());
} catch (Exception e) {
System.err.println("Failed to write instrumented class [class=" + clazz +