Factored out the code that will be shared between GenServiceTask and
GenReceiverTask (not yet implemented). Modified the task so that it can load the service classes via a classpath declared inside ant, avoiding the need to put project classes in Ant's classpath. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3240 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
-467
@@ -1,467 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# $Id: genservice,v 1.6 2004/10/13 19:29:12 andrzej Exp $
|
||||
#
|
||||
# This script is used to generate invocation service marshaller and
|
||||
# unmarshaller classes based on invocation service interface definitions.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
use Template;
|
||||
use File::Basename;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
# use Dumpvalue;
|
||||
|
||||
my $usage = "Usage: $0 [--verbose] [--force] [--classpath classpath] " .
|
||||
"[--sourcedir sourcedir] <sourcedir/foo/bar/FooService.java> [...]\n";
|
||||
|
||||
# get our options
|
||||
my $verbose;
|
||||
my $force;
|
||||
my $classpath;
|
||||
my $sourcedir = ".";
|
||||
GetOptions("verbose" => \$verbose,
|
||||
"force" => \$force,
|
||||
"classpath=s" => \$classpath,
|
||||
"sourcedir=s" => \$sourcedir,
|
||||
);
|
||||
|
||||
# some standard business
|
||||
my $ISVC_CNAME = "com.threerings.presents.client.InvocationService";
|
||||
|
||||
# make sure we have at least one source file argument
|
||||
die $usage unless (@ARGV);
|
||||
|
||||
# locate a few necessary other files
|
||||
my $script = basename($0);
|
||||
my $rootdir = dirname($0); $rootdir =~ s:bin$:.:g;
|
||||
my $marshtmpl = "$rootdir/lib/marshaller.tmpl";
|
||||
my $disptmpl = "$rootdir/lib/dispatcher.tmpl";
|
||||
|
||||
# now process our source files
|
||||
my %imports;
|
||||
my $srcfile;
|
||||
my $spackage;
|
||||
|
||||
while ($srcfile = shift) {
|
||||
# do a quick check to see if the marshaller file is newer than the
|
||||
# service file in which case we can stop now
|
||||
my $tpath = $srcfile;
|
||||
$tpath =~ s/Service/Marshaller/;
|
||||
$tpath =~ s:/client/:/data/:;
|
||||
my $dmtime = (stat($tpath))[9];
|
||||
my $smtime = (stat($srcfile))[9];
|
||||
if (!$force && (defined $dmtime) && ($dmtime > $smtime)) {
|
||||
my @foo = split(/\//, $srcfile);
|
||||
my $rfile = pop @foo;
|
||||
warn "Skipping ...$rfile as generated files are up to date.\n"
|
||||
if ($verbose);
|
||||
next;
|
||||
}
|
||||
|
||||
# convert the source file given on the command line to a class name
|
||||
open(SRC, "$srcfile") or die "$script: Unable to read '$srcfile': $!\n";
|
||||
while (<SRC>) {
|
||||
if (/^package (\S+);/) {
|
||||
$spackage = $1;
|
||||
}
|
||||
}
|
||||
$srcfile =~ m:/([^/]+)\.java$:;
|
||||
my $class = "$spackage.$1";
|
||||
|
||||
# run javap on the interface class
|
||||
my $jpcp = (defined $classpath) ? "-classpath $classpath" : "";
|
||||
my $jpcmd = "/usr/local/j2sdk1.4.1/bin/javap $jpcp $class";
|
||||
|
||||
# clear out the imports table
|
||||
%imports = ();
|
||||
|
||||
my $ifcname;
|
||||
my @methods;
|
||||
my @listeners;
|
||||
my $listener;
|
||||
|
||||
my $methcount = 1;
|
||||
my $lmethcount = 0;
|
||||
|
||||
open(JPO, "$jpcmd|") or die "$script: Can't invoke '$jpcmd': $!\n";
|
||||
while (<JPO>) {
|
||||
if (/^public interface (\S+) extends ([^, ]+)/) {
|
||||
$ifcname = $1;
|
||||
$imports{$ifcname} = 1;
|
||||
my $sname = $2;
|
||||
|
||||
# if this interface does not extend InvocationService, we
|
||||
# don't want to do nothin'
|
||||
die "$script: $ifcname does not extend " .
|
||||
"InvocationService\n (extends $sname).\n"
|
||||
if ($sname ne $ISVC_CNAME);
|
||||
|
||||
} elsif (/^ public abstract void (\S+)\(([^\)]*)\)/) {
|
||||
my $methname = $1;
|
||||
my $rawargs = $2; $rawargs =~ s:\$:.:g;
|
||||
my @methargs = split(/, /, $rawargs);
|
||||
grab_imports(@methargs);
|
||||
my @trimmed_args = trim_args(@methargs);
|
||||
my @unwrap_args = @trimmed_args;
|
||||
shift @unwrap_args;
|
||||
push @methods, {
|
||||
"mname" => $methname,
|
||||
"mcode" => to_caps($methname),
|
||||
"mcodeval" => $methcount++,
|
||||
"arglist" => gen_arglist(@trimmed_args),
|
||||
"wrapped_args" => wrap_arglist(1, @trimmed_args),
|
||||
"unwrapped_args" => unwrap_arglist(@unwrap_args),
|
||||
"listener_args" => gen_listener_args(@trimmed_args),
|
||||
};
|
||||
|
||||
} elsif (/^\s+public static interface \S+\. (\S+) extends (\S+)\. (\S+)/) {
|
||||
my $inner = $1;
|
||||
my $eouter = $2;
|
||||
my $einner = $3;
|
||||
|
||||
if ($eouter ne $ISVC_CNAME) {
|
||||
warn "Unrecognized inner interface $inner (extends $2.$3). " .
|
||||
"Skipping.\n";
|
||||
undef $listener;
|
||||
next;
|
||||
}
|
||||
|
||||
die "$script: Invalid callback interface name $inner.\n" .
|
||||
"Must be of the form <foo>Listener\n"
|
||||
if ($inner !~ m/Listener$/);
|
||||
|
||||
# create a new listener table to hold info on this listener class
|
||||
$inner =~ s:Listener$::;
|
||||
my @lmethods = ();
|
||||
$listener = {
|
||||
"name" => $inner,
|
||||
"methods" => \@lmethods,
|
||||
};
|
||||
push @listeners, $listener;
|
||||
$lmethcount = 0;
|
||||
|
||||
} elsif (/^ public abstract void (\S+)\(([^\)]*)\)/) {
|
||||
my $methname = $1;
|
||||
my $rawargs = $2; $rawargs =~ s:\$:.:g;
|
||||
my @methargs = split(/, /, $rawargs);
|
||||
|
||||
# skip this method declaration if we're not parsing a valid
|
||||
# listener inner interface declaration
|
||||
next unless (defined $listener);
|
||||
|
||||
grab_imports(@methargs);
|
||||
my @trimmed_args = trim_args(@methargs);
|
||||
my $lmethod = {
|
||||
"mname" => $methname,
|
||||
"mcode" => to_caps($methname),
|
||||
"mcodeval" => ++$lmethcount,
|
||||
"arglist" => gen_arglist(@trimmed_args),
|
||||
"wrapped_args" => wrap_arglist(0, @trimmed_args),
|
||||
"unwrapped_args" => unwrap_arglist(@trimmed_args),
|
||||
};
|
||||
push @{$listener->{"methods"}}, $lmethod;
|
||||
|
||||
} elsif (/^Compiled from/ ||
|
||||
/ACC_SUPER/ ||
|
||||
/^\s*[{}]\s*$/) {
|
||||
# skip it
|
||||
|
||||
} else {
|
||||
warn "$script: ?: $_";
|
||||
}
|
||||
}
|
||||
|
||||
die "$script: Unable to parse primary interface definition.\n"
|
||||
unless (defined $ifcname);
|
||||
|
||||
print "$script: Processing $ifcname...\n";
|
||||
|
||||
# extract the package name
|
||||
my $ifcpkg = $ifcname;
|
||||
$ifcpkg =~ s/\.[^.]*$//g;
|
||||
|
||||
# extract the service name
|
||||
my $svcname = substr($ifcname, length($ifcpkg)+1);
|
||||
$svcname =~ s/Service$//g;
|
||||
die "$script: Unable to discern service name from $ifcname.\n".
|
||||
"Service interface definitions should be named <foo>Service.\n"
|
||||
if ($svcname eq $ifcname);
|
||||
|
||||
# assume everything's in the same package to start
|
||||
my $marshpkg = $ifcpkg;
|
||||
my $disppkg = $ifcpkg;
|
||||
|
||||
# if the interface is in a 'client' package, we'll put the marshaller
|
||||
# in the associated 'data' package and the dispatcher in the 'server'
|
||||
# package
|
||||
if ($ifcpkg =~ m/\.client$/) {
|
||||
$marshpkg =~ s/\.client$/.data/g;
|
||||
$disppkg =~ s/\.client$/.server/g;
|
||||
}
|
||||
|
||||
# create a template processor
|
||||
my $ttconfig = {
|
||||
RELATIVE => 1,
|
||||
ABSOLUTE => 1,
|
||||
};
|
||||
my $tt = Template->new($ttconfig);
|
||||
my $genstamp = strftime("%T %D", localtime);
|
||||
|
||||
# now we generate the <foo>Marshaller class definition
|
||||
my $marshpath = $marshpkg;
|
||||
$marshpath =~ s:\.:/:g;
|
||||
$marshpath = "$sourcedir/$marshpath/$svcname" . "Marshaller.java";
|
||||
|
||||
print "$script: Generating marshaller:\n" .
|
||||
" $marshpkg.${svcname}Marshaller in\n" .
|
||||
" $marshpath\n" if ($verbose);
|
||||
|
||||
# populate a data table with all the data we'll need to fill out our
|
||||
# marshaller template file
|
||||
my %mimports = %imports;
|
||||
$mimports{"com.threerings.presents.client.Client"} = 1;
|
||||
$mimports{"com.threerings.presents.data.InvocationMarshaller"} = 1;
|
||||
$mimports{"com.threerings.presents.dobj.InvocationResponseEvent"} = 1;
|
||||
my @mimportsl = sort keys %mimports;
|
||||
my %mdata = ( "idstr" => slurp_idstr($marshpath),
|
||||
"imports" => \@mimportsl,
|
||||
"name" => $svcname,
|
||||
"package" => $marshpkg,
|
||||
"listeners" => \@listeners,
|
||||
"methods" => \@methods,
|
||||
"genstamp" => $genstamp,
|
||||
);
|
||||
|
||||
# my $dumper = Dumpvalue->new;
|
||||
# $dumper->dumpValue(\%mdata);
|
||||
|
||||
$tt->process($marshtmpl, \%mdata, $marshpath) or
|
||||
die "$script: Unable to process template file '$marshtmpl': " .
|
||||
$tt->error() . "\n";
|
||||
|
||||
# now we generate the <foo>Dispatcher class definition
|
||||
my $disppath = $disppkg;
|
||||
$disppath =~ s:\.:/:g;
|
||||
$disppath = "$sourcedir/$disppath/$svcname" . "Dispatcher.java";
|
||||
|
||||
print "$script: Generating dispatcher:\n" .
|
||||
" $disppkg.${svcname}Dispatcher in\n" .
|
||||
" $disppath\n" if ($verbose);
|
||||
|
||||
# populate a data table with all the data we'll need to fill out our
|
||||
# dispatcher template file
|
||||
my %dimports = %imports;
|
||||
$dimports{"com.threerings.presents.data.ClientObject"} = 1;
|
||||
$dimports{"com.threerings.presents.data.InvocationMarshaller"} = 1;
|
||||
$dimports{"com.threerings.presents.server.InvocationDispatcher"} = 1;
|
||||
$dimports{"com.threerings.presents.server.InvocationException"} = 1;
|
||||
$dimports{"$marshpkg.${svcname}Marshaller"} = 1;
|
||||
my @dimportsl = sort keys %dimports;
|
||||
my %ddata = ( "idstr" => slurp_idstr($disppath),
|
||||
"imports" => \@dimportsl,
|
||||
"name" => $svcname,
|
||||
"package" => $disppkg,
|
||||
"listeners" => \@listeners,
|
||||
"methods" => \@methods,
|
||||
"genstamp" => $genstamp,
|
||||
);
|
||||
|
||||
# my $dumper = Dumpvalue->new;
|
||||
# $dumper->dumpValue(\%ddata);
|
||||
|
||||
$tt->process($disptmpl, \%ddata, $disppath) or
|
||||
die "$script: Unable to process template file '$disptmpl': " .
|
||||
$tt->error() . "\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Extracts the imports from the supplied list of arguments.
|
||||
#
|
||||
sub grab_imports {
|
||||
my $class;
|
||||
foreach $class (@_) {
|
||||
# skip classes in java.lang
|
||||
next if ($class =~ m/^java\.lang\.[^.]+$/);
|
||||
# skip primitive types
|
||||
next unless ($class =~ m/\./);
|
||||
|
||||
# trim array delimiters
|
||||
my $tclass = $class;
|
||||
$tclass =~ s:[\[\]]::g;
|
||||
|
||||
# stuff the class into our import table
|
||||
$imports{$tclass} = 1;
|
||||
|
||||
# if this class is a listener and not in the same package as the
|
||||
# service class we're currently processing, we need to import its
|
||||
# marshaller as well
|
||||
if ($tclass =~ m/Listener$/ &&
|
||||
$tclass !~ m/^$spackage/ &&
|
||||
$tclass !~ $ISVC_CNAME) {
|
||||
my $mclass = $tclass;
|
||||
$mclass =~ s:\.client\.:.data.:g;
|
||||
$mclass =~ s:Listener:Marshaller:g;
|
||||
$mclass =~ s:Service:Marshaller:g;
|
||||
$imports{$mclass} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Strips the package name from the method argument types.
|
||||
#
|
||||
sub trim_args {
|
||||
my @targs;
|
||||
my $arg;
|
||||
foreach $arg (@_) {
|
||||
$arg =~ s/^.*\.([^.]+)$/$1/;
|
||||
push @targs, $arg;
|
||||
}
|
||||
return @targs;
|
||||
}
|
||||
|
||||
#
|
||||
# Converts a mixed case name to uppercase with underscores.
|
||||
#
|
||||
sub to_caps {
|
||||
my ($fcode) = @_;
|
||||
$fcode =~ s/([a-z])([A-Z])/$1_$2/g;
|
||||
$fcode =~ tr/a-z/A-Z/;
|
||||
return $fcode;
|
||||
}
|
||||
|
||||
#
|
||||
# Generates an argument list with argument names from a list of argument
|
||||
# types.
|
||||
#
|
||||
sub gen_arglist {
|
||||
my $arg;
|
||||
my $arglist = "";
|
||||
my $i = 1;
|
||||
foreach $arg (@_) {
|
||||
$arglist .= ", " if (length($arglist) > 0);
|
||||
$arglist .= "$arg arg$i";
|
||||
$i++;
|
||||
}
|
||||
return $arglist;
|
||||
}
|
||||
|
||||
#
|
||||
# Converts the supplied argument type list into a list of values suitable
|
||||
# for use in an Object array initializer (meaning object types are used as
|
||||
# is and primitive types are wrapped).
|
||||
#
|
||||
sub wrap_arglist {
|
||||
my $skip = shift @_;
|
||||
my $argvals = "";
|
||||
my $i = 0;
|
||||
my $arg;
|
||||
foreach $arg (@_) {
|
||||
$i++;
|
||||
next if ($i <= $skip);
|
||||
$argvals .= ", " if (length($argvals) > 0);
|
||||
if ($arg eq "boolean") {
|
||||
$argvals .= "new Boolean(arg$i)";
|
||||
} elsif ($arg eq "byte") {
|
||||
$argvals .= "new Byte(arg$i)";
|
||||
} elsif ($arg eq "short") {
|
||||
$argvals .= "new Short(arg$i)";
|
||||
} elsif ($arg eq "char") {
|
||||
$argvals .= "new Char(arg$i)";
|
||||
} elsif ($arg eq "int") {
|
||||
$argvals .= "new Integer(arg$i)";
|
||||
} elsif ($arg eq "long") {
|
||||
$argvals .= "new Long(arg$i)";
|
||||
} elsif ($arg eq "float") {
|
||||
$argvals .= "new Float(arg$i)";
|
||||
} elsif ($arg eq "double") {
|
||||
$argvals .= "new Double(arg$i)";
|
||||
} elsif ($arg =~ /Listener$/) {
|
||||
$argvals .= "listener$i";
|
||||
} else {
|
||||
$argvals .= "arg$i";
|
||||
}
|
||||
}
|
||||
return $argvals;
|
||||
}
|
||||
|
||||
#
|
||||
# Converts the supplied argument type list into a list of values which
|
||||
# represent the unwrapped value of each element.
|
||||
#
|
||||
sub unwrap_arglist {
|
||||
my $argvals = "";
|
||||
my $i = 0;
|
||||
my $arg;
|
||||
foreach $arg (@_) {
|
||||
$argvals .= ", " if (length($argvals) > 0);
|
||||
if ($arg eq "boolean") {
|
||||
$argvals .= "((Boolean)args[$i]).booleanValue()";
|
||||
} elsif ($arg eq "byte") {
|
||||
$argvals .= "((Byte)args[$i]).byteValue()";
|
||||
} elsif ($arg eq "short") {
|
||||
$argvals .= "((Short)args[$i]).shortValue()";
|
||||
} elsif ($arg eq "char") {
|
||||
$argvals .= "((Char)args[$i]).charValue()";
|
||||
} elsif ($arg eq "int") {
|
||||
$argvals .= "((Integer)args[$i]).intValue()";
|
||||
} elsif ($arg eq "long") {
|
||||
$argvals .= "((Long)args[$i]).longValue()";
|
||||
} elsif ($arg eq "float") {
|
||||
$argvals .= "((Float)args[$i]).floatValue()";
|
||||
} elsif ($arg eq "double") {
|
||||
$argvals .= "((Double)args[$i]).doubleValue()";
|
||||
} else {
|
||||
$argvals .= "($arg)args[$i]";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return $argvals;
|
||||
}
|
||||
|
||||
#
|
||||
# Generates the necessary data to wrap listeners in listener marshaller
|
||||
# instances.
|
||||
#
|
||||
sub gen_listener_args {
|
||||
my $arg;
|
||||
my @listener_args = ();
|
||||
my $i = 0;
|
||||
foreach $arg (@_) {
|
||||
$i++;
|
||||
next unless ($arg =~ /Listener$/);
|
||||
|
||||
my $mtype = $arg;
|
||||
if ($mtype eq "InvocationListener") {
|
||||
$mtype = "ListenerMarshaller";
|
||||
} else {
|
||||
$mtype =~ s:Listener$:Marshaller:;
|
||||
}
|
||||
|
||||
push (@listener_args, { "mtype" => $mtype,
|
||||
"aname" => "listener$i",
|
||||
"oaname" => "arg$i" });
|
||||
}
|
||||
return \@listener_args;
|
||||
}
|
||||
|
||||
#
|
||||
# If the specified file exists, it is opened and its RCS Id string is read
|
||||
# and returned.
|
||||
#
|
||||
sub slurp_idstr {
|
||||
my ($path) = @_;
|
||||
my $idstr = "\$Id\$";
|
||||
if (-f $path && open(IN, "$path")) {
|
||||
while (<IN>) {
|
||||
if (/(\$[I][d]: .*\$)/) {
|
||||
$idstr = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close(IN);
|
||||
}
|
||||
return $idstr;
|
||||
}
|
||||
@@ -3,40 +3,21 @@
|
||||
|
||||
package com.threerings.presents.tools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
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.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
|
||||
import com.samskivert.util.CollectionUtil;
|
||||
import com.samskivert.util.ObjectUtil;
|
||||
import com.samskivert.util.SortableArrayList;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.velocity.VelocityUtil;
|
||||
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService.InvocationListener;
|
||||
@@ -50,186 +31,8 @@ import com.threerings.presents.server.InvocationException;
|
||||
* An Ant task for generating invocation service marshalling and
|
||||
* unmarshalling classes.
|
||||
*/
|
||||
public class GenServiceTask extends Task
|
||||
public class GenServiceTask extends InvocationTask
|
||||
{
|
||||
/** Used to keep track of invocation service method listener arguments. */
|
||||
public static class ListenerArgument
|
||||
{
|
||||
public int index;
|
||||
|
||||
public Class listener;
|
||||
|
||||
public ListenerArgument (int index, Class listener)
|
||||
{
|
||||
this.index = index+1;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public String getMarshaller ()
|
||||
{
|
||||
String name = simpleName(listener);
|
||||
// handle ye olde special case
|
||||
if (name.equals("InvocationService.InvocationListener")) {
|
||||
return "ListenerMarshaller";
|
||||
}
|
||||
name = StringUtil.replace(name, "Service", "Marshaller");
|
||||
return StringUtil.replace(name, "Listener", "Marshaller");
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to keep track of invocation service methods. */
|
||||
public static class ServiceMethod
|
||||
{
|
||||
public Method method;
|
||||
|
||||
public ArrayList listenerArgs = new ArrayList();
|
||||
|
||||
public ServiceMethod (Class service, Method method, HashMap imports)
|
||||
{
|
||||
this.method = method;
|
||||
|
||||
// we need to look through our arguments and note any needed
|
||||
// imports in the supplied table
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = 0; ii < args.length; ii++) {
|
||||
Class arg = args[ii];
|
||||
while (arg.isArray()) {
|
||||
arg = arg.getComponentType();
|
||||
}
|
||||
|
||||
// if this is a listener, we need to add a listener
|
||||
// argument info for it
|
||||
if (InvocationListener.class.isAssignableFrom(arg)) {
|
||||
listenerArgs.add(new ListenerArgument(ii, arg));
|
||||
}
|
||||
|
||||
// if it's not primitive, global or in our package, we
|
||||
// should add an import statement for it
|
||||
if (arg.isPrimitive() ||
|
||||
arg.getName().startsWith("java.lang") ||
|
||||
ObjectUtil.equals(
|
||||
arg.getPackage(), service.getPackage())) {
|
||||
continue;
|
||||
}
|
||||
imports.put(importify(arg.getName()), Boolean.TRUE);
|
||||
|
||||
// if it's a listener and not one of the special
|
||||
// InvocationService listeners, we need to import its
|
||||
// marshaller as well
|
||||
if (InvocationListener.class.isAssignableFrom(arg) &&
|
||||
!simpleName(arg).startsWith("InvocationService")) {
|
||||
String mname = arg.getName();
|
||||
mname = StringUtil.replace(mname, "Service", "Marshaller");
|
||||
mname = StringUtil.replace(mname, "Listener", "Marshaller");
|
||||
mname = StringUtil.replace(mname, ".client.", ".data.");
|
||||
imports.put(importify(mname), Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getCode ()
|
||||
{
|
||||
return StringUtil.unStudlyName(method.getName()).toUpperCase();
|
||||
}
|
||||
|
||||
public String getArgList ()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = 0; ii < args.length; ii++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(simpleName(args[ii])).append(" arg").append(ii+1);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getWrappedArgList (boolean skipFirst)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = (skipFirst ? 1 : 0); ii < args.length; ii++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(wrapArgument(args[ii], ii+1));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public boolean hasArgs ()
|
||||
{
|
||||
return (method.getParameterTypes().length > 1);
|
||||
}
|
||||
|
||||
public String getUnwrappedArgList (boolean listenerMode)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = (listenerMode ? 0 : 1); ii < args.length; ii++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(unwrapArgument(args[ii], listenerMode ? ii : ii-1,
|
||||
listenerMode));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected String wrapArgument (Class clazz, int index)
|
||||
{
|
||||
if (clazz == Boolean.TYPE) {
|
||||
return "new Boolean(arg" + index + ")";
|
||||
} else if (clazz == Byte.TYPE) {
|
||||
return "new Byte(arg" + index + ")";
|
||||
} else if (clazz == Character.TYPE) {
|
||||
return "new Character(arg" + index + ")";
|
||||
} else if (clazz == Short.TYPE) {
|
||||
return "new Short(arg" + index + ")";
|
||||
} else if (clazz == Integer.TYPE) {
|
||||
return "new Integer(arg" + index + ")";
|
||||
} else if (clazz == Long.TYPE) {
|
||||
return "new Long(arg" + index + ")";
|
||||
} else if (clazz == Float.TYPE) {
|
||||
return "new Float(arg" + index + ")";
|
||||
} else if (clazz == Double.TYPE) {
|
||||
return "new Double(arg" + index + ")";
|
||||
} else if (InvocationListener.class.isAssignableFrom(clazz)) {
|
||||
return "listener" + index;
|
||||
} else {
|
||||
return "arg" + index;
|
||||
}
|
||||
}
|
||||
|
||||
protected String unwrapArgument (
|
||||
Class clazz, int index, boolean listenerMode)
|
||||
{
|
||||
if (clazz == Boolean.TYPE) {
|
||||
return "((Boolean)args[" + index + "]).booleanValue()";
|
||||
} else if (clazz == Byte.TYPE) {
|
||||
return "((Byte)args[" + index + "]).byteValue()";
|
||||
} else if (clazz == Character.TYPE) {
|
||||
return "((Character)args[" + index + "]).charValue()";
|
||||
} else if (clazz == Short.TYPE) {
|
||||
return "((Short)args[" + index + "]).shortValue()";
|
||||
} else if (clazz == Integer.TYPE) {
|
||||
return "((Integer)args[" + index + "]).intValue()";
|
||||
} else if (clazz == Long.TYPE) {
|
||||
return "((Long)args[" + index + "]).longValue()";
|
||||
} else if (clazz == Float.TYPE) {
|
||||
return "((Float)args[" + index + "]).floatValue()";
|
||||
} else if (clazz == Double.TYPE) {
|
||||
return "((Double)args[" + index + "]).doubleValue()";
|
||||
} else if (listenerMode &&
|
||||
InvocationListener.class.isAssignableFrom(clazz)) {
|
||||
return "listener" + index;
|
||||
} else {
|
||||
return "(" + simpleName(clazz) + ")args[" + index + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to keep track of custom InvocationListener derivations. */
|
||||
public static class ServiceListener
|
||||
{
|
||||
@@ -261,107 +64,7 @@ public class GenServiceTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a nested <fileset> element which enumerates service
|
||||
* declaration source files.
|
||||
*/
|
||||
public void addFileset (FileSet set)
|
||||
{
|
||||
_filesets.add(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures us with a header file that we'll prepend to all
|
||||
* generated source files.
|
||||
*/
|
||||
public void setHeader (File header)
|
||||
{
|
||||
try {
|
||||
_header = IOUtils.toString(new FileReader(header));
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Unabled to load header '" + header + ": " +
|
||||
ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual work of the task.
|
||||
*/
|
||||
public void execute () throws BuildException
|
||||
{
|
||||
try {
|
||||
_velocity = VelocityUtil.createEngine();
|
||||
} catch (Exception e) {
|
||||
throw new BuildException("Failure initializing Velocity", e);
|
||||
}
|
||||
|
||||
ArrayList files = new ArrayList();
|
||||
for (Iterator iter = _filesets.iterator(); iter.hasNext(); ) {
|
||||
FileSet fs = (FileSet)iter.next();
|
||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
|
||||
File fromDir = fs.getDir(getProject());
|
||||
String[] srcFiles = ds.getIncludedFiles();
|
||||
for (int f = 0; f < srcFiles.length; f++) {
|
||||
processService(new File(fromDir, srcFiles[f]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an invocation service source file.
|
||||
*/
|
||||
protected void processService (File source)
|
||||
{
|
||||
// System.err.println("Processing " + source + "...");
|
||||
// load up the file and determine it's package and classname
|
||||
String pkgname = null, name = null;
|
||||
try {
|
||||
BufferedReader bin = new BufferedReader(new FileReader(source));
|
||||
String line;
|
||||
while ((line = bin.readLine()) != null) {
|
||||
Matcher pm = PACKAGE_PATTERN.matcher(line);
|
||||
if (pm.find()) {
|
||||
pkgname = pm.group(1);
|
||||
}
|
||||
Matcher nm = NAME_PATTERN.matcher(line);
|
||||
if (nm.find()) {
|
||||
name = nm.group(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bin.close();
|
||||
|
||||
// make sure we found something
|
||||
if (name == null) {
|
||||
System.err.println(
|
||||
"Unable to locate interface name in " + source + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// prepend the package name to get a name we can Class.forName()
|
||||
if (pkgname != null) {
|
||||
name = pkgname + "." + name;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println(
|
||||
"Failed to parse " + source + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
processService(source, Class.forName(name));
|
||||
} catch (Exception e) {
|
||||
System.err.println(
|
||||
"Failed to load " + name + ": " + e.getMessage());
|
||||
System.err.println("Make sure the classes for which you will " +
|
||||
"be generating interfaces are");
|
||||
System.err.println("in ant's classpath.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a resolved invocation service class instance.
|
||||
*/
|
||||
// documentation inherited
|
||||
protected void processService (File source, Class service)
|
||||
{
|
||||
System.out.println("Processing " + service.getName() + "...");
|
||||
@@ -410,11 +113,6 @@ public class GenServiceTask extends Task
|
||||
methods.add(new ServiceMethod(service, m, imports));
|
||||
}
|
||||
|
||||
// String dname = StringUtil.replace(sname, "Service", "Dispatcher");
|
||||
// String dpackage = StringUtil.replace(spackage, ".client", ".server");
|
||||
// String pname = StringUtil.replace(sname, "Service", "Provider");
|
||||
// String ppackage = StringUtil.replace(spackage, ".client", ".server");
|
||||
|
||||
generateMarshaller(source, sname, spackage, methods, listeners,
|
||||
imports.keySet().iterator());
|
||||
generateDispatcher(source, sname, spackage, methods,
|
||||
@@ -453,7 +151,6 @@ public class GenServiceTask extends Task
|
||||
mpath = StringUtil.replace(mpath, "Service", "Marshaller");
|
||||
mpath = StringUtil.replace(mpath, "/client/", "/data/");
|
||||
|
||||
System.out.println("Generating " + mname + "...");
|
||||
writeFile(mpath, sw.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -497,7 +194,6 @@ public class GenServiceTask extends Task
|
||||
mpath = StringUtil.replace(mpath, "Service", "Dispatcher");
|
||||
mpath = StringUtil.replace(mpath, "/client/", "/server/");
|
||||
|
||||
System.out.println("Generating " + dname + "...");
|
||||
writeFile(mpath, sw.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -506,57 +202,6 @@ public class GenServiceTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeFile (String path, String data)
|
||||
throws IOException
|
||||
{
|
||||
if (_header != null) {
|
||||
data = _header + data;
|
||||
}
|
||||
FileUtils.writeStringToFile(new File(path), data, "UTF-8");
|
||||
}
|
||||
|
||||
protected static void checkedAdd (SortableArrayList list, String value)
|
||||
{
|
||||
if (!list.contains(value)) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected static String simpleName (Class clazz)
|
||||
{
|
||||
if (clazz.isArray()) {
|
||||
return simpleName(clazz.getComponentType()) + "[]";
|
||||
} else {
|
||||
Package pkg = clazz.getPackage();
|
||||
int offset = (pkg == null) ? 0 : pkg.getName().length()+1;
|
||||
String name = clazz.getName().substring(offset);
|
||||
return StringUtil.replace(name, "$", ".");
|
||||
}
|
||||
}
|
||||
|
||||
protected static String importify (String name)
|
||||
{
|
||||
int didx = name.indexOf("$");
|
||||
return (didx == -1) ? name : name.substring(0, didx);
|
||||
}
|
||||
|
||||
/** A list of filesets that contain tile images. */
|
||||
protected ArrayList _filesets = new ArrayList();
|
||||
|
||||
/** A header to put on all generated source files. */
|
||||
protected String _header;
|
||||
|
||||
/** Used to generate source files from templates. */
|
||||
protected VelocityEngine _velocity;
|
||||
|
||||
/** A regular expression for matching the package declaration. */
|
||||
protected static final Pattern PACKAGE_PATTERN =
|
||||
Pattern.compile("^\\s*package\\s+(\\S+)\\W");
|
||||
|
||||
/** A regular expression for matching the interface declaration. */
|
||||
protected static final Pattern NAME_PATTERN =
|
||||
Pattern.compile("^\\s*public\\s+interface\\s+(\\S+)\\W");
|
||||
|
||||
/** Specifies the path to the marshaller template. */
|
||||
protected static final String MARSHALLER_TMPL =
|
||||
"com/threerings/presents/tools/marshaller.tmpl";
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
package com.threerings.presents.tools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
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.samskivert.util.ObjectUtil;
|
||||
import com.samskivert.util.SortableArrayList;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.velocity.VelocityUtil;
|
||||
|
||||
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
|
||||
{
|
||||
/** Used to keep track of invocation service method listener arguments. */
|
||||
public static class ListenerArgument
|
||||
{
|
||||
public int index;
|
||||
|
||||
public Class listener;
|
||||
|
||||
public ListenerArgument (int index, Class listener)
|
||||
{
|
||||
this.index = index+1;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public String getMarshaller ()
|
||||
{
|
||||
String name = simpleName(listener);
|
||||
// handle ye olde special case
|
||||
if (name.equals("InvocationService.InvocationListener")) {
|
||||
return "ListenerMarshaller";
|
||||
}
|
||||
name = StringUtil.replace(name, "Service", "Marshaller");
|
||||
return StringUtil.replace(name, "Listener", "Marshaller");
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to keep track of invocation service methods. */
|
||||
public static class ServiceMethod
|
||||
{
|
||||
public Method method;
|
||||
|
||||
public ArrayList listenerArgs = new ArrayList();
|
||||
|
||||
public ServiceMethod (Class service, Method method, HashMap imports)
|
||||
{
|
||||
this.method = method;
|
||||
|
||||
// we need to look through our arguments and note any needed
|
||||
// imports in the supplied table
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = 0; ii < args.length; ii++) {
|
||||
Class arg = args[ii];
|
||||
while (arg.isArray()) {
|
||||
arg = arg.getComponentType();
|
||||
}
|
||||
|
||||
// if this is a listener, we need to add a listener
|
||||
// argument info for it
|
||||
if (InvocationListener.class.isAssignableFrom(arg)) {
|
||||
listenerArgs.add(new ListenerArgument(ii, arg));
|
||||
}
|
||||
|
||||
// if it's not primitive, global or in our package, we
|
||||
// should add an import statement for it
|
||||
if (arg.isPrimitive() ||
|
||||
arg.getName().startsWith("java.lang") ||
|
||||
ObjectUtil.equals(
|
||||
arg.getPackage(), service.getPackage())) {
|
||||
continue;
|
||||
}
|
||||
imports.put(importify(arg.getName()), Boolean.TRUE);
|
||||
|
||||
// if it's a listener and not one of the special
|
||||
// InvocationService listeners, we need to import its
|
||||
// marshaller as well
|
||||
if (InvocationListener.class.isAssignableFrom(arg) &&
|
||||
!simpleName(arg).startsWith("InvocationService")) {
|
||||
String mname = arg.getName();
|
||||
mname = StringUtil.replace(mname, "Service", "Marshaller");
|
||||
mname = StringUtil.replace(mname, "Listener", "Marshaller");
|
||||
mname = StringUtil.replace(mname, ".client.", ".data.");
|
||||
imports.put(importify(mname), Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getCode ()
|
||||
{
|
||||
return StringUtil.unStudlyName(method.getName()).toUpperCase();
|
||||
}
|
||||
|
||||
public String getArgList ()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = 0; ii < args.length; ii++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(simpleName(args[ii])).append(" arg").append(ii+1);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getWrappedArgList (boolean skipFirst)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = (skipFirst ? 1 : 0); ii < args.length; ii++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(wrapArgument(args[ii], ii+1));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public boolean hasArgs ()
|
||||
{
|
||||
return (method.getParameterTypes().length > 1);
|
||||
}
|
||||
|
||||
public String getUnwrappedArgList (boolean listenerMode)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Class[] args = method.getParameterTypes();
|
||||
for (int ii = (listenerMode ? 0 : 1); ii < args.length; ii++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(unwrapArgument(args[ii], listenerMode ? ii : ii-1,
|
||||
listenerMode));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected String wrapArgument (Class clazz, int index)
|
||||
{
|
||||
if (clazz == Boolean.TYPE) {
|
||||
return "new Boolean(arg" + index + ")";
|
||||
} else if (clazz == Byte.TYPE) {
|
||||
return "new Byte(arg" + index + ")";
|
||||
} else if (clazz == Character.TYPE) {
|
||||
return "new Character(arg" + index + ")";
|
||||
} else if (clazz == Short.TYPE) {
|
||||
return "new Short(arg" + index + ")";
|
||||
} else if (clazz == Integer.TYPE) {
|
||||
return "new Integer(arg" + index + ")";
|
||||
} else if (clazz == Long.TYPE) {
|
||||
return "new Long(arg" + index + ")";
|
||||
} else if (clazz == Float.TYPE) {
|
||||
return "new Float(arg" + index + ")";
|
||||
} else if (clazz == Double.TYPE) {
|
||||
return "new Double(arg" + index + ")";
|
||||
} else if (InvocationListener.class.isAssignableFrom(clazz)) {
|
||||
return "listener" + index;
|
||||
} else {
|
||||
return "arg" + index;
|
||||
}
|
||||
}
|
||||
|
||||
protected String unwrapArgument (
|
||||
Class clazz, int index, boolean listenerMode)
|
||||
{
|
||||
if (clazz == Boolean.TYPE) {
|
||||
return "((Boolean)args[" + index + "]).booleanValue()";
|
||||
} else if (clazz == Byte.TYPE) {
|
||||
return "((Byte)args[" + index + "]).byteValue()";
|
||||
} else if (clazz == Character.TYPE) {
|
||||
return "((Character)args[" + index + "]).charValue()";
|
||||
} else if (clazz == Short.TYPE) {
|
||||
return "((Short)args[" + index + "]).shortValue()";
|
||||
} else if (clazz == Integer.TYPE) {
|
||||
return "((Integer)args[" + index + "]).intValue()";
|
||||
} else if (clazz == Long.TYPE) {
|
||||
return "((Long)args[" + index + "]).longValue()";
|
||||
} else if (clazz == Float.TYPE) {
|
||||
return "((Float)args[" + index + "]).floatValue()";
|
||||
} else if (clazz == Double.TYPE) {
|
||||
return "((Double)args[" + index + "]).doubleValue()";
|
||||
} else if (listenerMode &&
|
||||
InvocationListener.class.isAssignableFrom(clazz)) {
|
||||
return "listener" + index;
|
||||
} else {
|
||||
return "(" + simpleName(clazz) + ")args[" + index + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a nested <fileset> element which enumerates service
|
||||
* declaration source files.
|
||||
*/
|
||||
public void addFileset (FileSet set)
|
||||
{
|
||||
_filesets.add(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures us with a header file that we'll prepend to all
|
||||
* generated source files.
|
||||
*/
|
||||
public void setHeader (File header)
|
||||
{
|
||||
try {
|
||||
_header = IOUtils.toString(new FileReader(header));
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Unabled to load header '" + header + ": " +
|
||||
ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** Configures our classpath which we'll use to load service classes. */
|
||||
public void setClasspathref (Reference pathref)
|
||||
{
|
||||
_cloader = ClasspathUtils.getClassLoaderForPath(
|
||||
getProject(), pathref);
|
||||
}
|
||||
|
||||
/** Performs the actual work of the task. */
|
||||
public void execute () throws BuildException
|
||||
{
|
||||
try {
|
||||
_velocity = VelocityUtil.createEngine();
|
||||
} catch (Exception e) {
|
||||
throw new BuildException("Failure initializing Velocity", e);
|
||||
}
|
||||
|
||||
ArrayList files = new ArrayList();
|
||||
for (Iterator iter = _filesets.iterator(); iter.hasNext(); ) {
|
||||
FileSet fs = (FileSet)iter.next();
|
||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
|
||||
File fromDir = fs.getDir(getProject());
|
||||
String[] srcFiles = ds.getIncludedFiles();
|
||||
for (int f = 0; f < srcFiles.length; f++) {
|
||||
processService(new File(fromDir, srcFiles[f]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Processes an invocation service source file. */
|
||||
protected void processService (File source)
|
||||
{
|
||||
// System.err.println("Processing " + source + "...");
|
||||
// load up the file and determine it's package and classname
|
||||
String pkgname = null, name = null;
|
||||
try {
|
||||
BufferedReader bin = new BufferedReader(new FileReader(source));
|
||||
String line;
|
||||
while ((line = bin.readLine()) != null) {
|
||||
Matcher pm = PACKAGE_PATTERN.matcher(line);
|
||||
if (pm.find()) {
|
||||
pkgname = pm.group(1);
|
||||
}
|
||||
Matcher nm = NAME_PATTERN.matcher(line);
|
||||
if (nm.find()) {
|
||||
name = nm.group(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bin.close();
|
||||
|
||||
// make sure we found something
|
||||
if (name == null) {
|
||||
System.err.println(
|
||||
"Unable to locate interface name in " + source + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// prepend the package name to get a name we can Class.forName()
|
||||
if (pkgname != null) {
|
||||
name = pkgname + "." + name;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println(
|
||||
"Failed to parse " + source + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
processService(source, _cloader.loadClass(name));
|
||||
} catch (Exception e) {
|
||||
System.err.println(
|
||||
"Failed to load " + name + ": " + e.getMessage());
|
||||
System.err.println("Make sure the classes for which you will " +
|
||||
"be generating interfaces are");
|
||||
System.err.println("in ant's classpath.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Processes a resolved invocation service class instance. */
|
||||
protected abstract void processService (File source, Class service);
|
||||
|
||||
protected void writeFile (String path, String data)
|
||||
throws IOException
|
||||
{
|
||||
if (_header != null) {
|
||||
data = _header + data;
|
||||
}
|
||||
FileUtils.writeStringToFile(new File(path), data, "UTF-8");
|
||||
}
|
||||
|
||||
protected static void checkedAdd (SortableArrayList list, String value)
|
||||
{
|
||||
if (!list.contains(value)) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected static String simpleName (Class clazz)
|
||||
{
|
||||
if (clazz.isArray()) {
|
||||
return simpleName(clazz.getComponentType()) + "[]";
|
||||
} else {
|
||||
Package pkg = clazz.getPackage();
|
||||
int offset = (pkg == null) ? 0 : pkg.getName().length()+1;
|
||||
String name = clazz.getName().substring(offset);
|
||||
return StringUtil.replace(name, "$", ".");
|
||||
}
|
||||
}
|
||||
|
||||
protected static String importify (String name)
|
||||
{
|
||||
int didx = name.indexOf("$");
|
||||
return (didx == -1) ? name : name.substring(0, didx);
|
||||
}
|
||||
|
||||
/** A list of filesets that contain tile images. */
|
||||
protected ArrayList _filesets = new ArrayList();
|
||||
|
||||
/** A header to put on all generated source files. */
|
||||
protected String _header;
|
||||
|
||||
/** Used to do our own classpath business. */
|
||||
protected ClassLoader _cloader;
|
||||
|
||||
/** Used to generate source files from templates. */
|
||||
protected VelocityEngine _velocity;
|
||||
|
||||
/** A regular expression for matching the package declaration. */
|
||||
protected static final Pattern PACKAGE_PATTERN =
|
||||
Pattern.compile("^\\s*package\\s+(\\S+)\\W");
|
||||
|
||||
/** A regular expression for matching the interface declaration. */
|
||||
protected static final Pattern NAME_PATTERN =
|
||||
Pattern.compile("^\\s*public\\s+interface\\s+(\\S+)\\W");
|
||||
}
|
||||
Reference in New Issue
Block a user