Generalize velocity creation and classloader setting for code generation ant tasks into GenTask

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6109 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Charlie Groves
2010-08-10 00:38:46 +00:00
parent 1236121ff6
commit 4ea22628f7
3 changed files with 77 additions and 114 deletions
@@ -31,22 +31,14 @@ import java.util.ArrayList;
import java.io.File;
import java.io.StringWriter;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
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.google.common.collect.Lists;
import com.samskivert.util.StringUtil;
import com.samskivert.velocity.VelocityUtil;
import com.threerings.presents.annotation.TransportHint;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.DSet;
@@ -55,7 +47,7 @@ import com.threerings.presents.dobj.OidList;
/**
* Generates necessary additional distributed object declarations and methods.
*/
public class GenDObjectTask extends Task
public class GenDObjectTask extends GenTask
{
/**
* Adds a nested <fileset> element which enumerates service declaration source files.
@@ -65,41 +57,13 @@ public class GenDObjectTask extends Task
_filesets.add(set);
}
/** Configures our classpath which we'll use to load service classes. */
public void setClasspathref (Reference pathref)
{
_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());
}
@Override
public void execute ()
{
if (_cloader == null) {
String errmsg = "This task requires a 'classpathref' attribute " +
"to be set to the project's classpath.";
throw new BuildException(errmsg);
}
try {
_velocity = VelocityUtil.createEngine();
} catch (Exception e) {
throw new BuildException("Failure initializing Velocity", e);
}
// resolve the DObject class using our classloader
try {
_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);
}
_doclass = loadClass(DObject.class.getName());
_dsclass = loadClass(DSet.class.getName());
_olclass = loadClass(OidList.class.getName());
for (FileSet fs : _filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
@@ -116,17 +80,12 @@ public class GenDObjectTask extends Task
{
// load up the file and determine it's package and classname
String name = null;
Class<?> klass = loadClass(name);
try {
// System.err.println("Processing " + source + "...");
name = GenUtil.readClassName(source);
processObject(source, _cloader.loadClass(name));
} catch (ClassNotFoundException cnfe) {
System.err.println("Failed to load " + name + ".\n" +
"Missing class: " + cnfe.getMessage());
System.err.println("Be sure to set the 'classpathref' attribute to a classpath\n" +
"that contains your projects invocation service classes.");
processObject(source, klass);
} catch (Exception e) {
throw new BuildException("Failed to process " + source.getName() + ": " + e, e);
throw new BuildException("Failed to process " + source.getName(), e);
}
}
@@ -248,12 +207,6 @@ public class GenDObjectTask extends Task
/** A list of filesets that contain tile images. */
protected ArrayList<FileSet> _filesets = Lists.newArrayList();
/** Used to do our own classpath business. */
protected ClassLoader _cloader;
/** Used to generate source files from templates. */
protected VelocityEngine _velocity;
/** {@link DObject} resolved with the proper classloader so that we
* can compare it to loaded derived classes. */
protected Class<?> _doclass;
@@ -0,0 +1,66 @@
package com.threerings.presents.tools;
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.app.VelocityEngine;
import com.samskivert.velocity.VelocityUtil;
public abstract class GenTask extends Task
{
public GenTask ()
{
try {
_velocity = VelocityUtil.createEngine();
} catch (Exception e) {
throw new BuildException("Failure initializing Velocity", e);
}
}
/**
* Configures to output extra information when generating code.
*/
public void setVerbose (boolean verbose)
{
_verbose = verbose;
}
/** Configures our classpath which we'll use to load service classes. */
public void setClasspathref (Reference pathref)
{
_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());
}
protected Class<?> loadClass (String name)
{
if (_cloader == null) {
throw new BuildException("This task requires a 'classpathref' attribute " +
"to be set to the project's classpath.");
}
try {
return _cloader.loadClass(name);
} catch (ClassNotFoundException cnfe) {
throw new BuildException(
"Failed to load " + name + ". Be sure to set the 'classpathref' attribute to a " +
"classpath that contains your project's presents classes.", cnfe);
}
}
/** Show extra output if set. */
protected boolean _verbose;
/** Used to do our own classpath business. */
protected ClassLoader _cloader;
/** Used to generate source files from templates. */
protected VelocityEngine _velocity;
}
@@ -35,15 +35,9 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.ClasspathUtils;
import org.apache.velocity.app.VelocityEngine;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -51,8 +45,6 @@ import com.google.common.collect.Lists;
import com.samskivert.io.StreamUtil;
import com.samskivert.util.Logger;
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;
@@ -61,7 +53,7 @@ import com.threerings.presents.client.InvocationService.InvocationListener;
* A base Ant task for generating invocation service related marshalling
* and unmarshalling classes.
*/
public abstract class InvocationTask extends Task
public abstract class InvocationTask extends GenTask
{
/** Used to keep track of invocation service method listener arguments. */
public class ListenerArgument
@@ -371,46 +363,11 @@ public abstract class InvocationTask extends Task
}
}
/**
* Configures to output extra information when generating code.
*/
public void setVerbose (boolean verbose)
{
_verbose = verbose;
}
/** Configures our classpath which we'll use to load service classes. */
public void setClasspathref (Reference pathref)
{
_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());
}
@Override
public void execute ()
{
if (_cloader == null) {
String errmsg = "This task requires a 'classpathref' attribute " +
"to be set to the project's classpath.";
throw new BuildException(errmsg);
}
try {
_velocity = VelocityUtil.createEngine();
} catch (Exception e) {
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);
}
_ilistener = loadClass(InvocationListener.class.getName());
for (FileSet fs : _filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
@@ -434,13 +391,9 @@ public abstract class InvocationTask extends Task
throw new BuildException("Failed to parse " + source + ": " + e.getMessage());
}
Class<?> serviceClass = loadClass(name);
try {
processService(source, _cloader.loadClass(name));
} catch (ClassNotFoundException cnfe) {
System.err.println("Failed to load " + name + ".\n" +
"Missing class: " + cnfe.getMessage());
System.err.println("Be sure to set the 'classpathref' attribute to a classpath\n" +
"that contains your projects invocation service classes.");
processService(source, serviceClass);
} catch (Exception e) {
throw new BuildException("Failed to process " + source.getName() + ": " + e, e);
}
@@ -480,15 +433,6 @@ public abstract class InvocationTask extends Task
/** A header to put on all generated source files. */
protected String _header;
/** Show extra output if set. */
protected boolean _verbose;
/** Used to do our own classpath business. */
protected ClassLoader _cloader;
/** 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;