diff --git a/src/java/com/threerings/presents/tools/GenServiceTask.java b/src/java/com/threerings/presents/tools/GenServiceTask.java index d99a4fece..b775b6aee 100644 --- a/src/java/com/threerings/presents/tools/GenServiceTask.java +++ b/src/java/com/threerings/presents/tools/GenServiceTask.java @@ -12,6 +12,7 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import org.apache.velocity.VelocityContext; @@ -34,11 +35,11 @@ import com.threerings.presents.server.InvocationException; public class GenServiceTask extends InvocationTask { /** Used to keep track of custom InvocationListener derivations. */ - public static class ServiceListener + public class ServiceListener implements Comparable { public Class listener; - public ArrayList methods = new ArrayList(); + public SortableArrayList methods = new SortableArrayList(); public ServiceListener (Class service, Class listener, HashMap imports) { @@ -53,6 +54,12 @@ public class GenServiceTask extends InvocationTask } methods.add(new ServiceMethod(service, m, imports)); } + methods.sort(); + } + + public int compareTo (ServiceListener other) + { + return getName().compareTo(other.getName()); } public String getName () @@ -85,8 +92,8 @@ public class GenServiceTask extends InvocationTask } HashMap imports = new HashMap(); - ArrayList methods = new ArrayList(); - ArrayList listeners = new ArrayList(); + SortableArrayList methods = new SortableArrayList(); + SortableArrayList listeners = new SortableArrayList(); // we need to import the service itself imports.put(importify(service.getName()), Boolean.TRUE); @@ -104,7 +111,7 @@ public class GenServiceTask extends InvocationTask // check this method for custom listener declarations Class[] args = m.getParameterTypes(); for (int aa = 0; aa < args.length; aa++) { - if (InvocationListener.class.isAssignableFrom(args[aa]) && + if (_ilistener.isAssignableFrom(args[aa]) && simpleName(args[aa]).startsWith(sname + ".")) { listeners.add(new ServiceListener( service, args[aa], imports)); @@ -112,6 +119,8 @@ public class GenServiceTask extends InvocationTask } methods.add(new ServiceMethod(service, m, imports)); } + listeners.sort(); + methods.sort(); generateMarshaller(source, sname, spackage, methods, listeners, imports.keySet().iterator()); @@ -120,8 +129,8 @@ public class GenServiceTask extends InvocationTask } protected void generateMarshaller ( - File source, String sname, String spackage, ArrayList methods, - ArrayList listeners, Iterator imports) + File source, String sname, String spackage, List methods, + List listeners, Iterator imports) { String name = StringUtil.replace(sname, "Service", ""); String mname = StringUtil.replace(sname, "Service", "Marshaller"); @@ -160,7 +169,7 @@ public class GenServiceTask extends InvocationTask } protected void generateDispatcher ( - File source, String sname, String spackage, ArrayList methods, + File source, String sname, String spackage, List methods, Iterator imports) { String name = StringUtil.replace(sname, "Service", ""); diff --git a/src/java/com/threerings/presents/tools/InvocationTask.java b/src/java/com/threerings/presents/tools/InvocationTask.java index 5551958be..11b60bab6 100644 --- a/src/java/com/threerings/presents/tools/InvocationTask.java +++ b/src/java/com/threerings/presents/tools/InvocationTask.java @@ -43,7 +43,7 @@ import com.threerings.presents.client.InvocationService.InvocationListener; public abstract class InvocationTask extends Task { /** Used to keep track of invocation service method listener arguments. */ - public static class ListenerArgument + public class ListenerArgument { public int index; @@ -68,7 +68,7 @@ public abstract class InvocationTask extends Task } /** Used to keep track of invocation service methods. */ - public static class ServiceMethod + public class ServiceMethod implements Comparable { public Method method; @@ -89,7 +89,7 @@ public abstract class InvocationTask extends Task // if this is a listener, we need to add a listener // argument info for it - if (InvocationListener.class.isAssignableFrom(arg)) { + if (_ilistener.isAssignableFrom(arg)) { listenerArgs.add(new ListenerArgument(ii, arg)); } @@ -106,7 +106,7 @@ public abstract class InvocationTask extends Task // if it's a listener and not one of the special // InvocationService listeners, we need to import its // marshaller as well - if (InvocationListener.class.isAssignableFrom(arg) && + if (_ilistener.isAssignableFrom(arg) && !simpleName(arg).startsWith("InvocationService")) { String mname = arg.getName(); mname = StringUtil.replace(mname, "Service", "Marshaller"); @@ -153,6 +153,11 @@ public abstract class InvocationTask extends Task return (method.getParameterTypes().length > 1); } + public int compareTo (ServiceMethod other) + { + return getCode().compareTo(other.getCode()); + } + public String getUnwrappedArgList (boolean listenerMode) { StringBuffer buf = new StringBuffer(); @@ -185,7 +190,7 @@ public abstract class InvocationTask extends Task return "new Float(arg" + index + ")"; } else if (clazz == Double.TYPE) { return "new Double(arg" + index + ")"; - } else if (InvocationListener.class.isAssignableFrom(clazz)) { + } else if (_ilistener.isAssignableFrom(clazz)) { return "listener" + index; } else { return "arg" + index; @@ -211,8 +216,7 @@ public abstract class InvocationTask extends Task return "((Float)args[" + index + "]).floatValue()"; } else if (clazz == Double.TYPE) { return "((Double)args[" + index + "]).doubleValue()"; - } else if (listenerMode && - InvocationListener.class.isAssignableFrom(clazz)) { + } else if (listenerMode && _ilistener.isAssignableFrom(clazz)) { return "listener" + index; } else { return "(" + simpleName(clazz) + ")args[" + index + "]"; @@ -265,6 +269,13 @@ public abstract class InvocationTask extends Task throw new BuildException("Failure initializing Velocity", e); } + // resolve the InvocationListener class using our classloader + try { + _ilistener = _cloader.loadClass(InvocationListener.class.getName()); + } catch (Exception e) { + throw new BuildException("Can't resolve InvocationListener", e); + } + ArrayList files = new ArrayList(); for (Iterator iter = _filesets.iterator(); iter.hasNext(); ) { FileSet fs = (FileSet)iter.next(); @@ -379,6 +390,10 @@ public abstract class InvocationTask extends Task /** Used to generate source files from templates. */ protected VelocityEngine _velocity; + /** {@link InvocationListener} resolved with the proper classloader so + * that we can compare it to loaded derived classes. */ + protected Class _ilistener; + /** A regular expression for matching the package declaration. */ protected static final Pattern PACKAGE_PATTERN = Pattern.compile("^\\s*package\\s+(\\S+)\\W");