Much work on generalizing the notion of message "transport" and
allowing the use of annotations to customize transport for DObject fields and service/receiver methods. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5099 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -46,6 +46,7 @@ import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
@@ -61,6 +62,9 @@ import com.samskivert.util.SortableArrayList;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.velocity.VelocityUtil;
|
||||
|
||||
import com.threerings.presents.annotation.TransportHint;
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
import com.threerings.presents.dobj.OidList;
|
||||
@@ -85,6 +89,11 @@ public class GenDObjectTask extends Task
|
||||
{
|
||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||
getProject(), pathref);
|
||||
|
||||
// set the parent of the classloader to be the classloader used to load this task,
|
||||
// rather than the classloader used to load Ant, so that we have access to Narya
|
||||
// classes like TransportHint
|
||||
((AntClassLoader)_cloader).setParent(getClass().getClassLoader());
|
||||
}
|
||||
|
||||
/** Performs the actual work of the task. */
|
||||
@@ -107,6 +116,7 @@ public class GenDObjectTask extends Task
|
||||
_doclass = _cloader.loadClass(DObject.class.getName());
|
||||
_dsclass = _cloader.loadClass(DSet.class.getName());
|
||||
_olclass = _cloader.loadClass(OidList.class.getName());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new BuildException("Can't resolve InvocationListener", e);
|
||||
}
|
||||
@@ -198,6 +208,18 @@ public class GenDObjectTask extends Task
|
||||
ctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase());
|
||||
ctx.put("upfield", StringUtils.capitalize(fname));
|
||||
|
||||
// determine the type of transport
|
||||
TransportHint hint = f.getAnnotation(TransportHint.class);
|
||||
String transport;
|
||||
if (hint == null) {
|
||||
transport = "DEFAULT";
|
||||
} else {
|
||||
transport = "getInstance(\n" +
|
||||
" com.threerings.presents.net.Transport.Type." +
|
||||
hint.type().name() + ", " + hint.channel() + ")";
|
||||
}
|
||||
ctx.put("transport", "com.threerings.presents.net.Transport." + transport);
|
||||
|
||||
// if this field is an array, we need its component types
|
||||
if (ftype.isArray()) {
|
||||
Class<?> etype = ftype.getComponentType();
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.net.Transport;
|
||||
import com.threerings.presents.server.InvocationSender;
|
||||
|
||||
/**
|
||||
@@ -85,7 +86,7 @@ public class GenReceiverTask extends InvocationTask
|
||||
methods.add(new ServiceMethod(m, imports));
|
||||
}
|
||||
methods.sort();
|
||||
|
||||
|
||||
// get rid of primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
@@ -106,6 +107,7 @@ public class GenReceiverTask extends InvocationTask
|
||||
CollectionUtil.addAll(implist, imports);
|
||||
checkedAdd(implist, ClientObject.class.getName());
|
||||
checkedAdd(implist, InvocationSender.class.getName());
|
||||
checkedAdd(implist, Transport.class.getName());
|
||||
String dname = StringUtil.replace(rname, "Receiver", "Decoder");
|
||||
checkedAdd(implist, rpackage + "." + dname);
|
||||
implist.sort();
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||
import com.threerings.presents.net.Transport;
|
||||
import com.threerings.presents.server.InvocationDispatcher;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationProvider;
|
||||
@@ -46,11 +47,11 @@ import com.threerings.presents.server.InvocationProvider;
|
||||
/**
|
||||
* An Ant task for generating invocation service marshalling and
|
||||
* unmarshalling classes.
|
||||
* TODO: when generating the imports for exported action script files, there are just enough
|
||||
* TODO: when generating the imports for exported action script files, there are just enough
|
||||
* conversions of primitive types (e.g. float -> Number), array types (e.g. int[] -> TypedArray)
|
||||
* and three rings utility types (e.g. float -> Float) to make the existing serivces work. It
|
||||
* should be possible to create a complete list of these conversions so that future services
|
||||
* can be generated without problems.
|
||||
* can be generated without problems.
|
||||
*/
|
||||
public class GenServiceTask extends InvocationTask
|
||||
{
|
||||
@@ -61,7 +62,7 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
public ComparableArrayList<ServiceMethod> methods =
|
||||
new ComparableArrayList<ServiceMethod>();
|
||||
|
||||
|
||||
/** Contains all imports required for the parameters of the methods in this listener. */
|
||||
public ImportSet imports = new ImportSet();
|
||||
|
||||
@@ -77,12 +78,12 @@ public class GenServiceTask extends InvocationTask
|
||||
continue;
|
||||
}
|
||||
if (_verbose) {
|
||||
System.out.println("Adding " + m + ", imports are " +
|
||||
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 " +
|
||||
System.out.println("Added " + m + ", imports are " +
|
||||
StringUtil.toString(imports));
|
||||
}
|
||||
}
|
||||
@@ -137,7 +138,7 @@ public class GenServiceTask extends InvocationTask
|
||||
protected void processService (File source, Class service)
|
||||
{
|
||||
System.out.println("Processing " + service.getName() + "...");
|
||||
|
||||
|
||||
// verify that the service class name is as we expect it to be
|
||||
if (!service.getName().endsWith("Service")) {
|
||||
System.err.println("Cannot process '" + service.getName() + "':");
|
||||
@@ -167,7 +168,7 @@ public class GenServiceTask extends InvocationTask
|
||||
sdesc.spackage, ".client", ".data");
|
||||
|
||||
// ----------- Part I - java marshaller
|
||||
|
||||
|
||||
// start with all imports (service methods and listener methods)
|
||||
ImportSet imports = sdesc.constructAllImports();
|
||||
|
||||
@@ -175,30 +176,31 @@ public class GenServiceTask extends InvocationTask
|
||||
imports.add(sdesc.service);
|
||||
imports.add(Client.class);
|
||||
imports.add(InvocationMarshaller.class);
|
||||
imports.add(Transport.class);
|
||||
|
||||
// if any listeners are to be present, they need the response event
|
||||
if (sdesc.listeners.size() > 0) {
|
||||
imports.add(InvocationResponseEvent.class);
|
||||
}
|
||||
|
||||
|
||||
// import classes contained in arrays
|
||||
imports.translateClassArrays();
|
||||
|
||||
|
||||
// get rid of java.lang stuff and primitives
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of all arrays (they are automatic in java)
|
||||
imports.removeArrays();
|
||||
|
||||
|
||||
// for each listener type, also import the corresponding marshaller
|
||||
imports.duplicateAndMunge("*Listener",
|
||||
imports.duplicateAndMunge("*Listener",
|
||||
"Service", "Marshaller",
|
||||
"Listener", "Marshaller",
|
||||
".client.", ".data.");
|
||||
|
||||
// import the parent class of Foo$Bar
|
||||
imports.swapInnerClassesForParents();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(mpackage);
|
||||
|
||||
@@ -234,15 +236,15 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// start with the service method imports
|
||||
imports = sdesc.imports.clone();
|
||||
|
||||
|
||||
// add some things that marshallers just need
|
||||
imports.add(sdesc.service);
|
||||
imports.add(Client.class);
|
||||
imports.add(InvocationMarshaller.class);
|
||||
|
||||
|
||||
// replace inner classes with action script equivalents
|
||||
imports.translateInnerClasses();
|
||||
|
||||
|
||||
// replace primitive types with OOO types (required for unboxing)
|
||||
imports.replace("byte", "com.threerings.util.Byte");
|
||||
imports.replace("int", "com.threerings.util.Integer");
|
||||
@@ -268,7 +270,7 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// get rid of java.lang stuff and any remaining primitives
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
if (imports.removeAll("[L*") > 0) {
|
||||
imports.add("com.threerings.io.TypedArray");
|
||||
}
|
||||
@@ -304,20 +306,20 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// start imports with just those used by listener methods
|
||||
imports = listener.imports.clone();
|
||||
|
||||
|
||||
// always need the super class and the listener class
|
||||
imports.add(imlm);
|
||||
imports.add(listener.listener);
|
||||
|
||||
|
||||
// replace '$' with '_' for action script naming convention
|
||||
imports.translateInnerClasses();
|
||||
|
||||
|
||||
// convert primitive java types to ooo util types
|
||||
imports.replace("long", "com.threerings.util.Long");
|
||||
|
||||
// get rid of remaining primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(mpackage);
|
||||
|
||||
@@ -359,7 +361,7 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// get rid of primitives and java.lang classes
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of remaining arrays
|
||||
imports.removeArrays();
|
||||
|
||||
@@ -394,20 +396,20 @@ public class GenServiceTask extends InvocationTask
|
||||
|
||||
// start with just the imports needed by listener methods
|
||||
imports = listener.imports.clone();
|
||||
|
||||
|
||||
// add things needed by all listeners
|
||||
imports.add(isil);
|
||||
imports.add(listener.listener);
|
||||
|
||||
|
||||
// change Foo$Bar to Foo_Bar
|
||||
imports.translateInnerClasses();
|
||||
|
||||
// convert java primitive types to ooo util types
|
||||
|
||||
// convert java primitive types to ooo util types
|
||||
imports.replace("long", "com.threerings.util.Long");
|
||||
|
||||
|
||||
// get rid of remaining primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(sdesc.spackage);
|
||||
|
||||
@@ -450,29 +452,29 @@ public class GenServiceTask extends InvocationTask
|
||||
// swap Client for ClientObject
|
||||
imports.add(ClientObject.class);
|
||||
imports.remove(Client.class);
|
||||
|
||||
|
||||
// add some classes required for all dispatchers
|
||||
imports.add(InvocationMarshaller.class);
|
||||
imports.add(InvocationDispatcher.class);
|
||||
imports.add(InvocationException.class);
|
||||
|
||||
|
||||
// import classes contained in arrays
|
||||
imports.translateClassArrays();
|
||||
|
||||
|
||||
// get rid of primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of arrays
|
||||
imports.removeArrays();
|
||||
|
||||
// import the Marshaller corresponding to the service
|
||||
imports.addMunged(sdesc.service,
|
||||
imports.addMunged(sdesc.service,
|
||||
"Service", "Marshaller",
|
||||
".client.", ".data.");
|
||||
|
||||
// import Foo instead of Foo$Bar
|
||||
imports.swapInnerClassesForParents();
|
||||
|
||||
|
||||
// remove imports in our own package
|
||||
imports.removeSamePackage(dpackage);
|
||||
|
||||
@@ -504,7 +506,7 @@ public class GenServiceTask extends InvocationTask
|
||||
if (_verbose) {
|
||||
System.out.println("Generating provider");
|
||||
}
|
||||
|
||||
|
||||
String name = StringUtil.replace(sdesc.sname, "Service", "");
|
||||
String mpackage = StringUtil.replace(
|
||||
sdesc.spackage, ".client", ".server");
|
||||
@@ -515,24 +517,24 @@ public class GenServiceTask extends InvocationTask
|
||||
// swap Client for ClientObject
|
||||
imports.add(ClientObject.class);
|
||||
imports.remove(Client.class);
|
||||
|
||||
|
||||
// import superclass
|
||||
imports.add(InvocationProvider.class);
|
||||
|
||||
// any method that takes a listener may throw this
|
||||
|
||||
// any method that takes a listener may throw this
|
||||
if (sdesc.hasAnyListenerArgs()) {
|
||||
imports.add(InvocationException.class);
|
||||
}
|
||||
|
||||
|
||||
// import classes contained in arrays
|
||||
imports.translateClassArrays();
|
||||
|
||||
|
||||
// get rid of primitives and java.lang types
|
||||
imports.removeGlobals();
|
||||
|
||||
|
||||
// get rid of arrays
|
||||
imports.removeArrays();
|
||||
|
||||
|
||||
// import Foo instead of Foo$Bar
|
||||
imports.swapInnerClassesForParents();
|
||||
|
||||
@@ -593,19 +595,19 @@ public class GenServiceTask extends InvocationTask
|
||||
}
|
||||
}
|
||||
if (_verbose) {
|
||||
System.out.println("Adding " + m + ", imports are " +
|
||||
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 " +
|
||||
System.out.println("Added " + m + ", imports are " +
|
||||
StringUtil.toString(imports));
|
||||
}
|
||||
}
|
||||
listeners.sort();
|
||||
methods.sort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if any of the service method arguments are listener types.
|
||||
*/
|
||||
@@ -640,7 +642,7 @@ public class GenServiceTask extends InvocationTask
|
||||
ComparableArrayList<ServiceListener> listeners =
|
||||
new ComparableArrayList<ServiceListener>();
|
||||
}
|
||||
|
||||
|
||||
/** The path to our ActionScript source files. */
|
||||
protected File _asroot;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.List;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
@@ -46,6 +47,9 @@ import org.apache.velocity.app.VelocityEngine;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.velocity.VelocityUtil;
|
||||
|
||||
import com.threerings.presents.annotation.TransportHint;
|
||||
import com.threerings.presents.net.Transport;
|
||||
|
||||
import com.threerings.presents.client.InvocationService.InvocationListener;
|
||||
|
||||
/**
|
||||
@@ -90,7 +94,7 @@ public abstract class InvocationTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to keep track of invocation service methods or listener
|
||||
/** Used to keep track of invocation service methods or listener
|
||||
* methods. */
|
||||
public class ServiceMethod implements Comparable<ServiceMethod>
|
||||
{
|
||||
@@ -101,13 +105,13 @@ public abstract class InvocationTask extends Task
|
||||
|
||||
/**
|
||||
* Creates a new service method.
|
||||
* @param method the method to inspect
|
||||
* @param method the method to inspect
|
||||
* @param imports will be filled with the types required by the method
|
||||
*/
|
||||
public ServiceMethod (Method method, ImportSet imports)
|
||||
{
|
||||
this.method = method;
|
||||
|
||||
|
||||
// we need to look through our arguments and note any needed
|
||||
// imports in the supplied table
|
||||
Class<?>[] args = method.getParameterTypes();
|
||||
@@ -249,6 +253,16 @@ public abstract class InvocationTask extends Task
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getTransport ()
|
||||
{
|
||||
TransportHint hint = method.getAnnotation(TransportHint.class);
|
||||
if (hint == null) {
|
||||
return "Transport.DEFAULT";
|
||||
}
|
||||
return "Transport.getInstance(Transport.Type." +
|
||||
hint.type().name() + ", " + hint.channel() + ")";
|
||||
}
|
||||
|
||||
protected String boxArgument (Class<?> clazz, int index)
|
||||
{
|
||||
if (_ilistener.isAssignableFrom(clazz)) {
|
||||
@@ -306,6 +320,11 @@ public abstract class InvocationTask extends Task
|
||||
{
|
||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||
getProject(), pathref);
|
||||
|
||||
// set the parent of the classloader to be the classloader used to load this task,
|
||||
// rather than the classloader used to load Ant, so that we have access to Narya
|
||||
// classes like TransportHint
|
||||
((AntClassLoader)_cloader).setParent(getClass().getClassLoader());
|
||||
}
|
||||
|
||||
/** Performs the actual work of the task. */
|
||||
@@ -405,7 +424,7 @@ public abstract class InvocationTask extends Task
|
||||
|
||||
/** Show extra output if set. */
|
||||
protected boolean _verbose;
|
||||
|
||||
|
||||
/** Used to do our own classpath business. */
|
||||
protected ClassLoader _cloader;
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
{
|
||||
$type ovalue = this.$field;
|
||||
requestAttributeChange(
|
||||
$capfield, $wrapfield, $wrapofield);
|
||||
$capfield, $wrapfield, $wrapofield,
|
||||
$transport);
|
||||
this.$field = $clonefield;
|
||||
}
|
||||
#if ($elemtype)
|
||||
@@ -28,7 +29,8 @@
|
||||
{
|
||||
$elemtype ovalue = this.$field[index];
|
||||
requestElementUpdate(
|
||||
$capfield, index, $wrapelem, $wrapoelem);
|
||||
$capfield, index, $wrapelem, $wrapoelem,
|
||||
$transport);
|
||||
this.$field[index] = value;
|
||||
}
|
||||
#end
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
*/
|
||||
public void update$upfield ($etype elem)
|
||||
{
|
||||
requestEntryUpdate($capfield, $field, elem);
|
||||
requestEntryUpdate(
|
||||
$capfield, $field, elem,
|
||||
$transport);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,7 @@ public class ${name}Marshaller extends InvocationMarshaller
|
||||
_invId = null;
|
||||
omgr.postEvent(new InvocationResponseEvent(
|
||||
callerOid, requestId, $lm.code,
|
||||
new Object[] { $lm.getWrappedArgList(false) }));
|
||||
new Object[] { $lm.getWrappedArgList(false) }, transport));
|
||||
}
|
||||
|
||||
#end
|
||||
@@ -71,7 +71,7 @@ public class ${name}Marshaller extends InvocationMarshaller
|
||||
#end
|
||||
sendRequest(arg1, $m.code, new Object[] {
|
||||
$m.getWrappedArgList(true)
|
||||
});
|
||||
}, $m.transport);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class ${name}Sender extends InvocationSender
|
||||
{
|
||||
sendNotification(
|
||||
target, ${name}Decoder.RECEIVER_CODE, ${name}Decoder.$m.code,
|
||||
new Object[] { $m.getWrappedArgList(false) });
|
||||
new Object[] { $m.getWrappedArgList(false) }, $m.transport);
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
Reference in New Issue
Block a user