With a magestic legacy as long and historied as Presents, nothing is ever easy.

We need to support legacy closures that have multiple constructors, one of
which will be a zero-argument constructor. All of the existing static inner
classes that extend NodeAction/NodeRequest will be such legacy classes. Whee!


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6555 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2011-03-30 00:14:22 +00:00
parent 73ef57ecc9
commit b759128425
2 changed files with 33 additions and 13 deletions
+14 -13
View File
@@ -457,23 +457,24 @@ public abstract class Streamer
}
}
// obtain the constructor we'll use to create instances
if (!isClosure) {
// locate our zero argument constructor
for (Constructor<?> ctor : _target.getDeclaredConstructors()) {
if (ctor.getParameterTypes().length == 0) {
_ctor = ctor;
break;
}
// if we have a zero argument constructor, we have to use that one
for (Constructor<?> ctor : _target.getDeclaredConstructors()) {
if (ctor.getParameterTypes().length == 0) {
_ctor = ctor;
_ctorArgs = ArrayUtil.EMPTY_OBJECT;
break;
}
_ctorArgs = ArrayUtil.EMPTY_OBJECT;
}
} else {
// a closure should have only one constructor
// if we're an anonymous closure, we also support having a single constructor to which
// we'll pass zero-valued arguments, which will then be overwritten by unstreaming
if (isClosure && _ctor == null) {
Constructor<?>[] ctors = _target.getDeclaredConstructors();
if (ctors.length > 1) {
throw new RuntimeException("Streamable closure classes must have only " +
"one constructor [class=" + _target.getName() + "]");
throw new RuntimeException(
"Streamable closure classes must have either a zero-argument constructor " +
"or a single argument-taking constructor; multiple argument-taking " +
"constructors are not allowed [class=" + _target.getName() + "]");
}
_ctor = ctors[0];
_ctor.setAccessible(true);
@@ -447,6 +447,25 @@ public class StreamableTest
assertEquals(act.act(), react.act());
}
protected static class LegacyClosure implements Streamable.Closure
{
public int arg;
public LegacyClosure (int arg) {
this.arg = arg;
}
public LegacyClosure () {
}
}
@Test
public void testLegacyZeroMultipleCtorHavingClosure ()
throws IOException, ClassNotFoundException
{
LegacyClosure inst = new LegacyClosure(42);
LegacyClosure reinst = (LegacyClosure)unflatten(flatten(inst));
assertEquals(inst.arg, reinst.arg);
}
protected int unsafeOuterCall ()
{
return 42;