diff --git a/build.xml b/build.xml index 3f524a3b5..86d24cdaa 100644 --- a/build.xml +++ b/build.xml @@ -209,7 +209,9 @@ - + + @@ -220,7 +222,12 @@ - + + + + + + diff --git a/etc/libs-incl.xml b/etc/libs-incl.xml index 660649f7b..b3021a384 100644 --- a/etc/libs-incl.xml +++ b/etc/libs-incl.xml @@ -14,6 +14,7 @@ + diff --git a/src/java/com/threerings/presents/tools/GenDObjectTask.java b/src/java/com/threerings/presents/tools/GenDObjectTask.java index a065d828d..039461bb6 100644 --- a/src/java/com/threerings/presents/tools/GenDObjectTask.java +++ b/src/java/com/threerings/presents/tools/GenDObjectTask.java @@ -27,15 +27,15 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import java.io.File; import java.io.IOException; -import java.io.StringWriter; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.types.FileSet; -import org.apache.velocity.VelocityContext; import com.google.common.collect.Lists; import com.samskivert.util.StringUtil; @@ -129,16 +129,16 @@ public class GenDObjectTask extends GenTask Class ftype = f.getType(); String fname = f.getName(); - // create our velocity context - VelocityContext ctx = new VelocityContext(); - ctx.put("field", fname); - ctx.put("generated", GenUtil.getGeneratedAnnotation(getClass(), 4, false)); - ctx.put("type", GenUtil.simpleName(f)); - ctx.put("wrapfield", GenUtil.boxArgument(ftype, "value")); - ctx.put("wrapofield", GenUtil.boxArgument(ftype, "ovalue")); - ctx.put("clonefield", GenUtil.cloneArgument(_dsclass, f, "value")); - ctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase()); - ctx.put("upfield", StringUtil.capitalize(fname)); + // create a map to hold our template data + Map data = new HashMap(); + data.put("field", fname); + data.put("generated", GenUtil.getGeneratedAnnotation(getClass(), 4, false)); + data.put("type", GenUtil.simpleName(f)); + data.put("wrapfield", GenUtil.boxArgument(ftype, "value")); + data.put("wrapofield", GenUtil.boxArgument(ftype, "ovalue")); + data.put("clonefield", GenUtil.cloneArgument(_dsclass, f, "value")); + data.put("capfield", StringUtil.unStudlyName(fname).toUpperCase()); + data.put("upfield", StringUtil.capitalize(fname)); // determine the type of transport TransportHint hint = f.getAnnotation(TransportHint.class); @@ -155,14 +155,14 @@ public class GenDObjectTask extends GenTask " com.threerings.presents.net.Transport.Type." + hint.type().name() + ", " + hint.channel() + ")"; } - ctx.put("transport", transport); + data.put("transport", transport); // if this field is an array, we need its component types if (ftype.isArray()) { Class etype = ftype.getComponentType(); - ctx.put("elemtype", GenUtil.simpleName(etype)); - ctx.put("wrapelem", GenUtil.boxArgument(etype, "value")); - ctx.put("wrapoelem", GenUtil.boxArgument(etype, "ovalue")); + data.put("elemtype", GenUtil.simpleName(etype)); + data.put("wrapelem", GenUtil.boxArgument(etype, "value")); + data.put("wrapoelem", GenUtil.boxArgument(etype, "ovalue")); } // if this field is a generic DSet, we need its bound type @@ -175,10 +175,10 @@ public class GenDObjectTask extends GenTask if (t instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType)t; if (pt.getActualTypeArguments().length > 0) { - ctx.put("etype", GenUtil.simpleName(pt.getActualTypeArguments()[0])); + data.put("etype", GenUtil.simpleName(pt.getActualTypeArguments()[0])); } } else { - ctx.put("etype", "DSet.Entry"); + data.put("etype", "DSet.Entry"); } } @@ -190,19 +190,13 @@ public class GenDObjectTask extends GenTask tname = "oidlist.tmpl"; } - // now generate our bits - StringWriter fwriter = new StringWriter(); - StringWriter mwriter = new StringWriter(); - _velocity.mergeTemplate(NAME_TMPL, "UTF-8", ctx, fwriter); - _velocity.mergeTemplate(BASE_TMPL + tname, "UTF-8", ctx, mwriter); - - // and append them as appropriate to the string buffers + // append the merged templates as appropriate to the string buffers if (ii > 0) { fsection.append("\n"); msection.append("\n"); } - fsection.append(fwriter.toString()); - msection.append(mwriter.toString()); + fsection.append(mergeTemplate(NAME_TMPL, data)); + msection.append(mergeTemplate(BASE_TMPL + tname, data)); } // now bolt everything back together into a class declaration diff --git a/src/java/com/threerings/presents/tools/GenReceiverTask.java b/src/java/com/threerings/presents/tools/GenReceiverTask.java index 36da3e39e..77e6ba602 100644 --- a/src/java/com/threerings/presents/tools/GenReceiverTask.java +++ b/src/java/com/threerings/presents/tools/GenReceiverTask.java @@ -28,12 +28,9 @@ import java.util.Iterator; import java.util.List; import java.io.File; -import java.io.StringWriter; import com.google.common.collect.Iterators; -import org.apache.velocity.VelocityContext; - import com.samskivert.util.ComparableArrayList; import com.samskivert.util.StringUtil; @@ -113,25 +110,20 @@ public class GenReceiverTask extends InvocationTask checkedAdd(implist, rpackage + "." + rname); implist.sort(); - VelocityContext ctx = new VelocityContext(); - ctx.put("name", name); - ctx.put("package", spackage); - ctx.put("methods", methods); - ctx.put("imports", implist); - - StringWriter sw = new StringWriter(); - _velocity.mergeTemplate(SENDER_TMPL, "UTF-8", ctx, sw); - // determine the path to our sender file String mpath = source.getPath(); mpath = mpath.replace("Receiver", "Sender"); mpath = replacePath(mpath, "/client/", "/server/"); - writeFile(mpath, sw.toString()); + writeFile(mpath, mergeTemplate(SENDER_TMPL, + "name", name, + "package", spackage, + "methods", methods, + "imports", implist)); } protected void generateDecoder (Class receiver, File source, String rname, String rpackage, - List methods, Iterator imports, String rcode) - throws Exception + List methods, Iterator imports, + String rcode) throws Exception { String name = rname.replace("Receiver", ""); @@ -141,20 +133,15 @@ public class GenReceiverTask extends InvocationTask checkedAdd(implist, InvocationDecoder.class.getName()); implist.sort(); - VelocityContext ctx = new VelocityContext(); - ctx.put("name", name); - ctx.put("receiver_code", rcode); - ctx.put("package", rpackage); - ctx.put("methods", methods); - ctx.put("imports", implist); - - StringWriter sw = new StringWriter(); - _velocity.mergeTemplate(DECODER_TMPL, "UTF-8", ctx, sw); - // determine the path to our sender file String mpath = source.getPath(); mpath = mpath.replace("Receiver", "Decoder"); - writeFile(mpath, sw.toString()); + writeFile(mpath, mergeTemplate(DECODER_TMPL, + "name", name, + "receiver_code", rcode, + "package", rpackage, + "methods", methods, + "imports", implist)); } /** Specifies the path to the sender template. */ diff --git a/src/java/com/threerings/presents/tools/GenServiceTask.java b/src/java/com/threerings/presents/tools/GenServiceTask.java index 608cc6685..54a1f6c78 100644 --- a/src/java/com/threerings/presents/tools/GenServiceTask.java +++ b/src/java/com/threerings/presents/tools/GenServiceTask.java @@ -24,12 +24,11 @@ package com.threerings.presents.tools; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import java.io.File; -import java.io.StringWriter; - -import org.apache.velocity.VelocityContext; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -260,7 +259,7 @@ public class GenServiceTask extends InvocationTask // remove imports in our own package imports.removeSamePackage(mpackage); - VelocityContext ctx = new VelocityContext(); + Map ctx = new HashMap(); ctx.put("name", name); ctx.put("generated", getGeneratedAnnotation(name)); ctx.put("package", mpackage); @@ -272,10 +271,7 @@ public class GenServiceTask extends InvocationTask String mpath = source.getPath(); mpath = mpath.replace("Service", "Marshaller"); mpath = replacePath(mpath, "/client/", "/data/"); - - StringWriter sw = new StringWriter(); - _velocity.mergeTemplate(MARSHALLER_TMPL, "UTF-8", ctx, sw); - writeFile(mpath, sw.toString()); + writeFile(mpath, mergeTemplate(MARSHALLER_TMPL, ctx)); // if we're not configured with an ActionScript source root, don't generate the // ActionScript versions @@ -345,9 +341,7 @@ public class GenServiceTask extends InvocationTask // generate an ActionScript version of our marshaller String ampath = _asroot + File.separator + mppath + File.separator + mname + ".as"; - sw = new StringWriter(); - _velocity.mergeTemplate(AS_MARSHALLER_TMPL, "UTF-8", ctx, sw); - writeFile(ampath, sw.toString()); + writeFile(ampath, mergeTemplate(AS_MARSHALLER_TMPL, ctx)); // ----------- Part III - as listener marshallers @@ -382,11 +376,9 @@ public class GenServiceTask extends InvocationTask ctx.put("imports", imports.toList()); ctx.put("listener", listener); - sw = new StringWriter(); - _velocity.mergeTemplate(AS_LISTENER_MARSHALLER_TMPL, "UTF-8", ctx, sw); String aslpath = _asroot + File.separator + mppath + File.separator + mname + "_" + listener.getName() + "Marshaller.as"; - writeFile(aslpath, sw.toString()); + writeFile(aslpath, mergeTemplate(AS_LISTENER_MARSHALLER_TMPL, ctx)); } // ----------- Part IV - as service @@ -433,9 +425,7 @@ public class GenServiceTask extends InvocationTask // generate an ActionScript version of our service String aspath = _asroot + File.separator + sppath + File.separator + sname + ".as"; - sw = new StringWriter(); - _velocity.mergeTemplate(AS_SERVICE_TMPL, "UTF-8", ctx, sw); - writeFile(aspath, sw.toString()); + writeFile(aspath, mergeTemplate(AS_SERVICE_TMPL, ctx)); // ----------- Part V - as service listeners Class isil = InvocationService.InvocationListener.class; @@ -470,20 +460,14 @@ public class GenServiceTask extends InvocationTask ctx.put("imports", imports.toList()); ctx.put("listener", listener); - sw = new StringWriter(); - _velocity.mergeTemplate(AS_LISTENER_SERVICE_TMPL, "UTF-8", ctx, sw); String aslpath = _asroot + File.separator + sppath + - File.separator + sname + "_" + - listener.getName() + "Listener.as"; - writeFile(aslpath, sw.toString()); + File.separator + sname + "_" + listener.getName() + "Listener.as"; + writeFile(aslpath, mergeTemplate(AS_LISTENER_SERVICE_TMPL, ctx)); if (_aslistenerAdapters.contains(sname)) { - sw = new StringWriter(); - _velocity.mergeTemplate(AS_LISTENER_ADAPTER_SERVICE_TMPL, "UTF-8", ctx, sw); String aslapath = _asroot + File.separator + sppath + - File.separator + sname + "_" + - listener.getName() + "ListenerAdapter.as"; - writeFile(aslapath, sw.toString()); + File.separator + sname + "_" + listener.getName() + "ListenerAdapter.as"; + writeFile(aslapath, mergeTemplate(AS_LISTENER_ADAPTER_SERVICE_TMPL, ctx)); } } } @@ -534,22 +518,16 @@ public class GenServiceTask extends InvocationTask // remove imports in our own package imports.removeSamePackage(dpackage); - VelocityContext ctx = new VelocityContext(); - ctx.put("name", name); - ctx.put("generated", getGeneratedAnnotation(name)); - ctx.put("package", dpackage); - ctx.put("methods", sdesc.methods); - ctx.put("imports", imports.toList()); - - StringWriter sw = new StringWriter(); - _velocity.mergeTemplate(DISPATCHER_TMPL, "UTF-8", ctx, sw); - // determine the path to our marshaller file String mpath = source.getPath(); mpath = mpath.replace("Service", "Dispatcher"); mpath = replacePath(mpath, "/client/", "/server/"); - - writeFile(mpath, sw.toString()); + writeFile(mpath, mergeTemplate(DISPATCHER_TMPL, + "name", name, + "generated", getGeneratedAnnotation(name), + "package", dpackage, + "methods", sdesc.methods, + "imports", imports.toList())); } protected void generateProvider (File source, ServiceDescription sdesc) @@ -593,23 +571,17 @@ public class GenServiceTask extends InvocationTask // remove imports in our own package imports.removeSamePackage(mpackage); - VelocityContext ctx = new VelocityContext(); - ctx.put("name", name); - ctx.put("generated", getGeneratedAnnotation(name)); - ctx.put("package", mpackage); - ctx.put("methods", sdesc.methods); - ctx.put("listeners", sdesc.listeners); - ctx.put("imports", imports.toList()); - - StringWriter sw = new StringWriter(); - _velocity.mergeTemplate(PROVIDER_TMPL, "UTF-8", ctx, sw); - // determine the path to our provider file String mpath = source.getPath(); mpath = mpath.replace("Service", "Provider"); mpath = replacePath(mpath, "/client/", "/server/"); - - writeFile(mpath, sw.toString()); + writeFile(mpath, mergeTemplate(PROVIDER_TMPL, + "name", name, + "generated", getGeneratedAnnotation(name), + "package", mpackage, + "methods", sdesc.methods, + "listeners", sdesc.listeners, + "imports", imports.toList())); } /** diff --git a/src/java/com/threerings/presents/tools/GenTask.java b/src/java/com/threerings/presents/tools/GenTask.java index 52f37b1bd..b3a9f1153 100644 --- a/src/java/com/threerings/presents/tools/GenTask.java +++ b/src/java/com/threerings/presents/tools/GenTask.java @@ -21,11 +21,17 @@ package com.threerings.presents.tools; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.util.ClasspathUtils; + +import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import com.samskivert.velocity.VelocityUtil; @@ -60,6 +66,49 @@ public abstract class GenTask extends Task ((AntClassLoader)_cloader).setParent(getClass().getClassLoader()); } + /** + * Merges the specified template using the supplied mapping of keys to objects. + * + * @param data a series of key, value pairs where the keys must be strings and the values can + * be any object. + */ + protected String mergeTemplate (String template, Object... data) + throws Exception + { + VelocityContext ctx = new VelocityContext(); + for (int ii = 0; ii < data.length; ii += 2) { + ctx.put((String)data[ii], data[ii+1]); + } + return mergeTemplate(template, ctx); + } + + /** + * Merges the specified template using the supplied mapping of string keys to objects. + * + * @return a string containing the merged text. + */ + protected String mergeTemplate (String template, Map data) + throws Exception + { + VelocityContext ctx = new VelocityContext(); + for (Map.Entry entry : data.entrySet()) { + ctx.put(entry.getKey(), entry.getValue()); + } + return mergeTemplate(template, ctx); + } + + /** + * A helper function for {@link #mergeTemplate(String, Map)} and friends. Don't + * use this directly as you'll end up depending on Velocity and your code won't build. + */ + protected String mergeTemplate (String template, VelocityContext ctx) + throws Exception + { + StringWriter writer = new StringWriter(); + _velocity.mergeTemplate(template, "UTF-8", ctx, writer); + return writer.toString(); + } + protected Class loadClass (String name) { if (_cloader == null) { @@ -81,6 +130,7 @@ public abstract class GenTask extends Task /** Used to do our own classpath business. */ protected ClassLoader _cloader; - /** Used to generate source files from templates. */ + /** Used to generate source files from templates. Don't use this directly from derived classes, + * use {@link #mergeTemplate}. */ protected VelocityEngine _velocity; }