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.File;
import java.io.StringWriter; import java.io.StringWriter;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner; 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.FileSet;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.ClasspathUtils;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.samskivert.velocity.VelocityUtil;
import com.threerings.presents.annotation.TransportHint; import com.threerings.presents.annotation.TransportHint;
import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.DSet; import com.threerings.presents.dobj.DSet;
@@ -55,7 +47,7 @@ import com.threerings.presents.dobj.OidList;
/** /**
* Generates necessary additional distributed object declarations and methods. * 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. * Adds a nested <fileset> element which enumerates service declaration source files.
@@ -65,41 +57,13 @@ public class GenDObjectTask extends Task
_filesets.add(set); _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 @Override
public void execute () 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 // resolve the DObject class using our classloader
try { _doclass = loadClass(DObject.class.getName());
_doclass = _cloader.loadClass(DObject.class.getName()); _dsclass = loadClass(DSet.class.getName());
_dsclass = _cloader.loadClass(DSet.class.getName()); _olclass = loadClass(OidList.class.getName());
_olclass = _cloader.loadClass(OidList.class.getName());
} catch (Exception e) {
throw new BuildException("Can't resolve InvocationListener", e);
}
for (FileSet fs : _filesets) { for (FileSet fs : _filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); 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 // load up the file and determine it's package and classname
String name = null; String name = null;
Class<?> klass = loadClass(name);
try { try {
// System.err.println("Processing " + source + "...");
name = GenUtil.readClassName(source); name = GenUtil.readClassName(source);
processObject(source, _cloader.loadClass(name)); processObject(source, klass);
} 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.");
} catch (Exception e) { } 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. */ /** A list of filesets that contain tile images. */
protected ArrayList<FileSet> _filesets = Lists.newArrayList(); 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 /** {@link DObject} resolved with the proper classloader so that we
* can compare it to loaded derived classes. */ * can compare it to loaded derived classes. */
protected Class<?> _doclass; 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.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner; 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.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.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -51,8 +45,6 @@ import com.google.common.collect.Lists;
import com.samskivert.io.StreamUtil; import com.samskivert.io.StreamUtil;
import com.samskivert.util.Logger; import com.samskivert.util.Logger;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.samskivert.velocity.VelocityUtil;
import com.threerings.presents.annotation.TransportHint; import com.threerings.presents.annotation.TransportHint;
import com.threerings.presents.net.Transport; import com.threerings.presents.net.Transport;
import com.threerings.presents.client.InvocationService.InvocationListener; 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 * A base Ant task for generating invocation service related marshalling
* and unmarshalling classes. * 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. */ /** Used to keep track of invocation service method listener arguments. */
public class ListenerArgument 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 @Override
public void execute () 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 // resolve the InvocationListener class using our classloader
try { _ilistener = loadClass(InvocationListener.class.getName());
_ilistener = _cloader.loadClass(InvocationListener.class.getName());
} catch (Exception e) {
throw new BuildException("Can't resolve InvocationListener", e);
}
for (FileSet fs : _filesets) { for (FileSet fs : _filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); DirectoryScanner ds = fs.getDirectoryScanner(getProject());
@@ -434,13 +391,9 @@ public abstract class InvocationTask extends Task
throw new BuildException("Failed to parse " + source + ": " + e.getMessage()); throw new BuildException("Failed to parse " + source + ": " + e.getMessage());
} }
Class<?> serviceClass = loadClass(name);
try { try {
processService(source, _cloader.loadClass(name)); processService(source, serviceClass);
} 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.");
} catch (Exception e) { } catch (Exception e) {
throw new BuildException("Failed to process " + source.getName() + ": " + e, 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. */ /** A header to put on all generated source files. */
protected String _header; 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 /** {@link InvocationListener} resolved with the proper classloader so
* that we can compare it to loaded derived classes. */ * that we can compare it to loaded derived classes. */
protected Class<?> _ilistener; protected Class<?> _ilistener;