From c0499674e9b3f863af60973c39bf30c89f3c1b8b Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Tue, 28 Jul 2009 21:34:13 +0000 Subject: [PATCH] Allow an InvocationListener interface to extend another InvocationListener interface. The way this works is a little tricky, but it all works out. We have a service SceneService with SceneMoveListener declaration. You can make FooSceneService and have a method in that service take a FooMoveListener which extends SceneMoveListener. An instance of FooMoveMarshaller will only be created if you call the method on FooSceneService and that will result in an object on the server side that implements SceneMoveListener, but calls to the SceneMoveListener response methods will result in the FooSceneService response codes being marshalled and sent back to the caller. So you can pass the FooMoveListener around to code on the server that expects a SceneMoveListener and it will magically do the right thing when server code calls through the SceneMoveListener interface. You can even turn around and pass the FooMoveMarshaller to another invocation service method (on a peer perhaps) that takes SceneMoveListener and it will work because the SceneService call will generate a SceneMoveMarshaller on the remote server, which will use the SceneMoveMarshaller's codes to communicate the response back to the first peer, which will unmap those and call the methods on the SceneMoveListener interface which will remarshal them with the FooMoveListener's codes and send them back to the client, and bob is everyone's uncle. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5891 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../presents/tools/GenServiceTask.java | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/java/com/threerings/presents/tools/GenServiceTask.java b/src/java/com/threerings/presents/tools/GenServiceTask.java index d654c65f0..ed01d733e 100644 --- a/src/java/com/threerings/presents/tools/GenServiceTask.java +++ b/src/java/com/threerings/presents/tools/GenServiceTask.java @@ -24,7 +24,7 @@ package com.threerings.presents.tools; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.HashSet; +import java.util.Set; import java.io.File; import java.io.StringWriter; @@ -74,26 +74,46 @@ public class GenServiceTask extends InvocationTask public ServiceListener (Class service, Class listener) { this.listener = listener; - Method[] methdecls = listener.getDeclaredMethods(); - for (Method m : methdecls) { - // service interface methods must be public and abstract - if (!Modifier.isPublic(m.getModifiers()) && - !Modifier.isAbstract(m.getModifiers())) { - continue; - } - if (_verbose) { - System.out.println("Adding " + m + ", imports are " + - StringUtil.toString(imports)); - } - methods.add(new ServiceMethod(m, imports)); - if (_verbose) { - System.out.println("Added " + m + ", imports are " + - StringUtil.toString(imports)); + + // compute the union of all InvocationListener extensions implemented by this interface + Set> ifaces = Sets.newHashSet(); + addInterfaces(listener, ifaces); + + // add method marshallers for all methods in all interfaces (the marshaller will not + // extend the marshallers for its parent interfaces and will use its own codes) + for (Class iface : ifaces) { + Method[] methdecls = iface.getDeclaredMethods(); + for (Method m : methdecls) { + // service interface methods must be public and abstract + if (!Modifier.isPublic(m.getModifiers()) && + !Modifier.isAbstract(m.getModifiers())) { + continue; + } + if (_verbose) { + System.out.println("Adding " + m + ", imports are " + + StringUtil.toString(imports)); + } + methods.add(new ServiceMethod(m, imports)); + if (_verbose) { + System.out.println("Added " + m + ", imports are " + + StringUtil.toString(imports)); + } } } methods.sort(); } + protected void addInterfaces (Class listener, Set> ifaces) + { + if (!_ilistener.isAssignableFrom(listener) || _ilistener.equals(listener)) { + return; + } + ifaces.add(listener); + for (Class iface : listener.getInterfaces()) { + addInterfaces(iface, ifaces); + } + } + /** * Checks whether any of our methods have parameterized types. */ @@ -668,10 +688,10 @@ public class GenServiceTask extends InvocationTask protected File _asroot; /** Services for which we should not generate provider interfaces. */ - protected HashSet _providerless = Sets.newHashSet(); + protected Set _providerless = Sets.newHashSet(); /** Services for which we should generate actionscript listener adapters. */ - protected HashSet _aslistenerAdapters = Sets.newHashSet(); + protected Set _aslistenerAdapters = Sets.newHashSet(); /** Specifies the path to the marshaller template. */ protected static final String MARSHALLER_TMPL =