git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268317 13f79535-47bb-0310-9956-ffa450edef68master
@@ -0,0 +1,14 @@ | |||
README for Ant(Eater) | |||
--------------------------------------------------------------------------------- | |||
Execution: | |||
ant [args] target | |||
Args: | |||
-help | |||
-quiet | |||
-verbose | |||
-taskpath [path] | |||
-antfile [file] |
@@ -0,0 +1,299 @@ | |||
// ------------------------------------------------------------------------------- | |||
// Copyright (c)2000 Apache Software Foundation | |||
// ------------------------------------------------------------------------------- | |||
import java.io.*; | |||
import java.util.*; | |||
import java.util.zip.*; | |||
/** | |||
* Quick and dirty single class bootstrap utility for getting Ant off | |||
* the ground when in need. To use, compile this file in the directory | |||
* where the source code is in the repository, then execute it. That's | |||
* it.<p> | |||
* | |||
* No pretense is made that this is an elegant peice of code. This code | |||
* only exists to do a ground zero build of Ant. Any other building of | |||
* Ant should be done with itself whenever possible. | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public class Bootstrap { | |||
private static String base = "../"; | |||
private static String[] modules = new String[]{"copy", "echo", "jar", "javac"}; | |||
/** | |||
* Command line entry point. | |||
*/ | |||
public static void main(String[] args) { | |||
// check for secret sugar left by MRJ startup script... | |||
if (args.length > 0) { | |||
if (args[0].equals("osx")) { | |||
base = ""; | |||
} | |||
} | |||
long startTime = System.currentTimeMillis(); | |||
System.out.println("Starting Bootstrap...."); | |||
// ------------------------------------------------------------ | |||
// first create dirs that we need for strapping | |||
// ------------------------------------------------------------ | |||
mkdir(base + "bootstrap/temp"); | |||
mkdir(base + "bootstrap/temp/main"); | |||
mkdir(base + "bootstrap/temp/tasks"); | |||
mkdir(base + "bootstrap/temp/taskjars"); | |||
for (int i = 0; i < modules.length; i++) { | |||
mkdir(base + "bootstrap/temp/tasks/" + modules[i]); | |||
} | |||
// ------------------------------------------------------------ | |||
// build the main thing | |||
// ------------------------------------------------------------ | |||
Vector v = getSources(base + "source/main"); | |||
doCompile(base + "bootstrap/temp/main", v); | |||
// ------------------------------------------------------------ | |||
// now build each of the needed peices into their | |||
// areas within the strapping area | |||
// ------------------------------------------------------------ | |||
for (int i = 0; i < modules.length; i++) { | |||
buildModule(modules[i]); | |||
} | |||
// ------------------------------------------------------------ | |||
// now, set classpaths and launch an Ant build to | |||
// have Ant build itself nicely | |||
// ------------------------------------------------------------ | |||
System.out.println(); | |||
System.out.println("-------------------------------------------"); | |||
System.out.println("STARTING REAL BUILD"); | |||
System.out.println("-------------------------------------------"); | |||
System.out.println(); | |||
String[] cmdarray = new String[9]; | |||
cmdarray[0] = "java"; | |||
cmdarray[1] = "-cp"; | |||
cmdarray[2] = base + "bootstrap/temp/main:" + base + "lib/jaxp.jar:" + | |||
base + "lib/crimson.jar"; | |||
cmdarray[3] = "org.apache.ant.cli.Main"; | |||
cmdarray[4] = "-taskpath"; | |||
cmdarray[5] = base + "bootstrap/temp/taskjars"; | |||
cmdarray[6] = "-buildfile"; | |||
cmdarray[7] = base + "source/main.ant"; | |||
cmdarray[8] = "default"; | |||
try { | |||
Runtime runtime = Runtime.getRuntime(); | |||
Process process = runtime.exec(cmdarray); | |||
// echo output from process | |||
InputStream in = process.getInputStream(); | |||
byte[] buf = new byte[80]; | |||
int count = 0; | |||
count = in.read(buf, 0, buf.length); | |||
while (count != -1) { | |||
System.out.write(buf, 0, count); | |||
count = in.read(buf, 0, buf.length); | |||
} | |||
in = process.getErrorStream(); | |||
count = in.read(buf, 0, buf.length); | |||
if (count > 0) { | |||
System.out.println(); | |||
System.out.println("Error Stream Output:"); | |||
while (count != -1) { | |||
System.out.write(buf, 0, count); | |||
count = in.read(buf, 0, buf.length); | |||
} | |||
} | |||
} catch (Exception e) { | |||
System.out.println("OUCHY: " + e); | |||
return; | |||
} | |||
System.out.println(); | |||
System.out.println("-------------------------------------------"); | |||
System.out.println("FINISHED WITH REAL BUILD"); | |||
System.out.println("-------------------------------------------"); | |||
System.out.println(); | |||
// ------------------------------------------------------------ | |||
// Remove Temporary classes | |||
// ------------------------------------------------------------ | |||
// delete(tempDirName); | |||
// ------------------------------------------------------------ | |||
// Print Closer | |||
// ------------------------------------------------------------ | |||
long endTime = System.currentTimeMillis(); | |||
long elapsd = endTime - startTime; | |||
System.out.println("Bootstrap Time: " + (elapsd/1000) + "." + (elapsd%1000) + | |||
" seconds"); | |||
} | |||
private static void mkdir(String arg) { | |||
File dir = new File(arg); | |||
if (dir.exists() && !dir.isDirectory()) { | |||
System.out.println("Oh, horrors! Dir " + arg + " " + | |||
"doesn't seem to be a dir... Stop!"); | |||
System.exit(1); | |||
} | |||
if (!dir.exists()) { | |||
System.out.println("Making dir: " + arg); | |||
dir.mkdir(); | |||
} | |||
} | |||
private static void buildModule(String arg) { | |||
System.out.println("Building " + arg); | |||
// get all sources and hand them off to the compiler to | |||
// build over into destination | |||
Vector v = getSources(base + "source/coretasks/" + arg); | |||
if (v.size() > 0) { | |||
doCompile(base + "bootstrap/temp/tasks/" + arg, v); | |||
} | |||
// move taskdef.properties for the module | |||
copyfile(base + "source/coretasks/" + arg + "/taskdef.properties", | |||
base + "bootstrap/temp/tasks/" + arg + "/taskdef.properties"); | |||
// jar up tasks | |||
try { | |||
jarDir(new File(base + "bootstrap/temp/tasks/" + arg), | |||
new File(base + "bootstrap/temp/taskjars/" + arg + ".jar")); | |||
} catch(IOException ioe) { | |||
System.out.println("problem jar'ing: " + arg); | |||
} | |||
} | |||
private static Vector getSources(String arg) { | |||
File sourceDir = new File(arg); | |||
Vector v = new Vector(); | |||
scanDir(sourceDir, v, ".java"); | |||
return v; | |||
} | |||
private static void jarDir(File dir, File jarfile) throws IOException { | |||
String[] files = dir.list(); | |||
if (files.length > 0) { | |||
System.out.println("Jaring: " + jarfile); | |||
FileOutputStream fos = new FileOutputStream(jarfile); | |||
ZipOutputStream zos = new ZipOutputStream(fos); | |||
jarDir(dir, "", zos); | |||
zos.close(); | |||
} | |||
} | |||
private static void jarDir(File dir, String prefix, ZipOutputStream zos) throws | |||
IOException | |||
{ | |||
String[] files = dir.list(); | |||
for (int i = 0; i < files.length; i++) { | |||
File f = new File(dir, files[i]); | |||
if (f.isDirectory()) { | |||
jarDir(f, prefix + "/" + files[i], zos); | |||
} else { | |||
ZipEntry ze = new ZipEntry(prefix + "/" + files[i]); | |||
zos.putNextEntry(ze); | |||
FileInputStream fis = new FileInputStream(f); | |||
int count = 0; | |||
byte[] buf = new byte[8 * 1024]; | |||
count = fis.read(buf, 0, buf.length); | |||
while (count != -1) { | |||
zos.write(buf, 0, count); | |||
count = fis.read(buf, 0, buf.length); | |||
} | |||
fis.close(); | |||
} | |||
} | |||
} | |||
private static void scanDir(File dir, Vector v, String endsWith) { | |||
// System.out.println("user.dir=" + System.getProperty("user.dir")); | |||
// System.out.println("Scanning: " + dir); | |||
String[] files = dir.list(); | |||
// System.out.println("Files: " + files); | |||
for (int i = 0; i < files.length; i++) { | |||
File f = new File(dir, files[i]); | |||
if (f.isDirectory()) { | |||
scanDir(f, v, endsWith); | |||
} else { | |||
if (files[i].endsWith(endsWith)) { | |||
v.addElement(f); | |||
} | |||
} | |||
} | |||
} | |||
private static void doCompile(String dest, Vector sources) { | |||
System.out.println(" Compiling " + sources.size() + " files to " + dest); | |||
// XXX This should be more forgiving about compiling wherever | |||
// under whatever compiler, but this works so... | |||
sun.tools.javac.Main compiler = new sun.tools.javac.Main(System.out, | |||
"javac"); | |||
String[] args = new String[sources.size() + 4]; | |||
args[0] = "-classpath"; | |||
args[1] = base + "bootstrap/temp/main:" + base + "lib/jaxp.jar:" + | |||
base + "lib/crimson.jar"; | |||
args[2] = "-d"; | |||
args[3] = dest; | |||
for (int i = 0; i < sources.size(); i++) { | |||
args[4+i] = ((File)sources.elementAt(i)).toString(); | |||
} | |||
// System.out.print("javac "); | |||
// for (int i = 0; i < args.length; i++) { | |||
// System.out.print(args[i] + " "); | |||
// } | |||
// System.out.println(); | |||
compiler.compile(args); | |||
} | |||
private static void copyfile(String from, String dest) { | |||
File fromF = new File(from); | |||
File destF = new File(dest); | |||
if (fromF.exists()) { | |||
System.out.println(" Copying " + from); | |||
try { | |||
FileInputStream in = new FileInputStream(fromF); | |||
FileOutputStream out = new FileOutputStream(destF); | |||
byte[] buf = new byte[1024 * 16]; | |||
int count = 0; | |||
count = in.read(buf, 0, buf.length); | |||
if (count != -1) { | |||
out.write(buf, 0, count); | |||
count = in.read(buf, 0, buf.length); | |||
} | |||
in.close(); | |||
out.close(); | |||
} catch (IOException ioe) { | |||
System.out.println("OUCH: " + from); | |||
System.out.println(ioe); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
BOOTSTRAP FOLDER README | |||
--------------------------------------------------------------------- | |||
The utilities provided here are used by the developers of Ant to | |||
bootstrap builds of Ant and will be used by the nightly build process | |||
to build Ant from a zero state. | |||
That said, there is no reason for most folks -- even hard core Ant | |||
developers -- to use the files here on a regular basis. You should | |||
really have the latest stable version of Ant installed somewhere so | |||
that you can easily build Ant using itself. Check out the | |||
installation guidelines in the documentation for suggestions on how | |||
Ant can be installed as a full time program of your system. | |||
HOW TO USE | |||
So, you really want to use the bootstrap facilities instead of just | |||
downloading a build from somewhere? Ok. Here's how it works: | |||
* Make sure that sun.tools.javac.Main is on your classpath. | |||
Sometimes it is, sometimes it isn't -- it depends on the JDK | |||
installed on your machine. You can do a quick check using | |||
the 'javap sun.tools.javac.Main' command to see if it is. | |||
* Make sure that you have a JAXP 1.1 compliant parser in your | |||
classpath. The Bootstrap itself doesn't need XML parsing | |||
classes, but Ant itself does. A good test for this is | |||
'javap javax.xml.parsers.DocumentBuilder' | |||
* Compile Bootstrap.java. You should end up with Bootstrap.class | |||
and maybe a few other classes (depending). | |||
* Execute the Bootstrap class. | |||
How this will work in practice is: | |||
% javac Bootstrap.java | |||
% java Bootstrap | |||
The Bootstrap class will grind out a preliminary build in the directory | |||
'temp/' which will be placed in this directory, then use that build to | |||
build a real copy of Ant into '../Build' using Ant's own makefile. After | |||
doing this, the Boostrap class will remove the intermediate build in | |||
the 'temp/' directory. | |||
HISTORICAL NOTE | |||
The Bootstrap class is somewhat the same rough hack as the first sketch | |||
of Ant itself -- a proof of concept that a Java based build system | |||
could work out halfway decently. Of course, Ant has expanded much past | |||
the capabilities of this, but this little start serves as a useful | |||
tool to bootstrap builds. |
@@ -0,0 +1,44 @@ | |||
package org.apache.ant.echo; | |||
import java.io.*; | |||
import java.util.*; | |||
import org.apache.ant.*; | |||
/** | |||
* Basic echo task that just spits out whatever it is supposed to... | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public class EchoTask extends AbstractTask { | |||
// ----------------------------------------------------------------- | |||
// PRIVATE DATA MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Data to echo | |||
*/ | |||
private String data; | |||
// ----------------------------------------------------------------- | |||
// PUBLIC METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
public boolean execute() throws AntException { | |||
PrintStream out = project.getOutput(); | |||
out.println("ECHOING: " + data); | |||
return true; | |||
} | |||
/** | |||
* | |||
*/ | |||
public void setData(String data) { | |||
this.data = data; | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
# taskdef.properties for Echo task | |||
tasks=echo | |||
echo.class=org.apache.ant.echo.EchoTask |
@@ -0,0 +1,13 @@ | |||
<?xml version="1.0"?> | |||
<project name="Ant"> | |||
<target name="default"> | |||
<echo data="Echo In Default"/> | |||
</target> | |||
<target name="main"> | |||
<echo data="Echo In Main"/> | |||
</target> | |||
</project> |
@@ -0,0 +1,85 @@ | |||
package org.apache.ant; | |||
import java.io.*; | |||
import java.util.*; | |||
import java.lang.reflect.*; | |||
import java.beans.*; | |||
/** | |||
* Superclass of all Tasks. All tasks extend from this. | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public abstract class AbstractTask { | |||
// ----------------------------------------------------------------- | |||
// PROTECTED DATA MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
protected Project project; | |||
// ----------------------------------------------------------------- | |||
// ABSTRACT PUBLIC METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
public abstract boolean execute() throws AntException; | |||
// ----------------------------------------------------------------- | |||
// PUBLIC METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Used by the system to set the attributes which then get reflected | |||
* into the particular implementation class | |||
*/ | |||
public void setAttributes(Hashtable attributes) { | |||
Class clazz = this.getClass(); | |||
BeanInfo bi; | |||
try { | |||
bi = Introspector.getBeanInfo(clazz); | |||
} catch (IntrospectionException ie) { | |||
System.out.println("Can't reflect on: " + clazz); | |||
// XXX exception out | |||
return; | |||
} | |||
PropertyDescriptor[] pda = bi.getPropertyDescriptors(); | |||
for (int i = 0; i < pda.length; i++) { | |||
PropertyDescriptor pd = pda[i]; | |||
String property = pd.getName(); | |||
Object o = attributes.get(property); | |||
if (o != null) { | |||
String value = (String)o; | |||
Method setMethod = pd.getWriteMethod(); | |||
if (setMethod != null) { | |||
Class[] ma = setMethod.getParameterTypes(); | |||
if (ma.length == 1) { | |||
Class c = ma[0]; | |||
if (c.getName().equals("java.lang.String")) { | |||
try { | |||
setMethod.invoke(this, new String[] {value}); | |||
} catch (Exception e) { | |||
// XXX bad bad bad -- narrow to exact exceptions | |||
System.out.println("OUCH: " + e); | |||
// XXX exception out. | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Used by system to set the project. | |||
*/ | |||
public void setProject(Project project) { | |||
this.project = project; | |||
} | |||
} |
@@ -0,0 +1,249 @@ | |||
// ------------------------------------------------------------------------------- | |||
// Copyright (c)2000 Apache Software Foundation | |||
// ------------------------------------------------------------------------------- | |||
package org.apache.ant; | |||
import java.io.*; | |||
import java.util.*; | |||
import java.util.zip.*; | |||
/** | |||
* Central class of Ant. This is the core 'kernel' of ant. Interfaces into | |||
* ant talk to Ant through this class. | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public class Ant { | |||
// ----------------------------------------------------------------- | |||
// PRIVATE DATA MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
private Hashtable abstractTaskClasses = new Hashtable(); | |||
/** | |||
* | |||
*/ | |||
private Vector taskPathNodes = new Vector(); | |||
/** | |||
* | |||
*/ | |||
private File buildfile; | |||
/** | |||
* | |||
*/ | |||
private Project project; | |||
// ----------------------------------------------------------------- | |||
// CONSTRUCTORS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Constructs a new Ant instance. | |||
*/ | |||
public Ant() { | |||
setUpTaskPath(); | |||
} | |||
// ----------------------------------------------------------------- | |||
// PUBLIC METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Sets additional path nodes onto the task lookup path. These nodes | |||
* take precendence over all previously set path nodes. | |||
*/ | |||
public void addTaskPathNode(File node) { | |||
taskPathNodes.insertElementAt(node, 0); | |||
} | |||
/** | |||
* | |||
*/ | |||
public void buildTarget(String targetName) throws AntException { | |||
try { | |||
loadTasks(); | |||
} catch (IOException ioe) { | |||
throw new AntException(ioe.getMessage()); | |||
} | |||
Target target = project.getTarget(targetName); | |||
// XXX don't forget to execute dependancies first! | |||
Enumeration enum = target.getTasks().elements(); | |||
while (enum.hasMoreElements()) { | |||
Task task = (Task)enum.nextElement(); | |||
Object o = abstractTaskClasses.get(task.getType()); | |||
if (o != null) { | |||
Class c = (Class)o; | |||
try { | |||
AbstractTask aTask = (AbstractTask)c.newInstance(); | |||
aTask.setAttributes(task.getAttributes()); | |||
aTask.setProject(project); | |||
boolean b = aTask.execute(); | |||
if (!b) { | |||
throw new AntException("STOP: Task " + task + | |||
" did not succeed"); | |||
} | |||
} catch (Exception e) { | |||
// XXX yes yes yes, this shouldn't be a catch all... | |||
throw new AntException("ERR: " + e); | |||
} | |||
} else { | |||
throw new AntException("Don't have a class for task type: " + task); | |||
} | |||
} | |||
} | |||
/** | |||
* | |||
*/ | |||
public Project getProject() { | |||
return project; | |||
} | |||
/** | |||
* Sets the buildfile to be used. This action triggers a parse of | |||
* the build file and assembles a Project object from it. | |||
*/ | |||
public void setBuildfile(File file) throws AntException { | |||
buildfile = file; | |||
ProjectBuilder builder = new ProjectBuilder(); | |||
project = builder.buildFromFile(file); | |||
project.setAnt(this); | |||
System.out.println("Loaded Project: " + project.getName()); | |||
// XXX remove the dump after comfort level is reached | |||
System.out.println("Dump of Project:"); | |||
Enumeration enum = project.getTargets(); | |||
while (enum.hasMoreElements()) { | |||
Target target = (Target)enum.nextElement(); | |||
System.out.println(" Target: " + target.getName()); | |||
Enumeration enum2 = target.getTasks().elements(); | |||
while (enum2.hasMoreElements()) { | |||
Task task = (Task)enum2.nextElement(); | |||
System.out.println(" Task: " + task.getType()); | |||
Enumeration enum3 = task.getAttributeNames(); | |||
while (enum3.hasMoreElements()) { | |||
String atName = (String)enum3.nextElement(); | |||
String atValue = task.getAttribute(atName); | |||
System.out.println(" Att: " + atName + " = " + | |||
atValue); | |||
} | |||
} | |||
} | |||
} | |||
// ----------------------------------------------------------------- | |||
// PRIVATE METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Searches through the taskpath and loads up the taskImpl hashtable | |||
* | |||
* XXX we also need to lookup a taskdef.properties file out of a few | |||
* strategic locations on disk to allow generic classes to be pulled | |||
* from the classpath | |||
*/ | |||
private void loadTasks() throws IOException { | |||
Enumeration enum = taskPathNodes.elements(); | |||
while (enum.hasMoreElements()) { | |||
File dir = (File)enum.nextElement(); | |||
String[] files = dir.list(); | |||
for (int i = 0; i < files.length; i++) { | |||
if (files[i].endsWith(".jar")) { | |||
File f = new File(dir, files[i]); | |||
ZipFile zf = new ZipFile(f); | |||
ZipEntry ze = zf.getEntry("/taskdef.properties"); | |||
if (ze != null) { | |||
InputStream is = zf.getInputStream(ze); | |||
Properties props = new Properties(); | |||
props.load(is); | |||
is.close(); | |||
//System.out.println("Props: " + props); | |||
String s = props.getProperty("tasks"); | |||
StringTokenizer tok = new StringTokenizer(s, ",", false); | |||
while (tok.hasMoreTokens()) { | |||
String taskType = tok.nextToken(); | |||
String taskClassName = props.getProperty(taskType + | |||
".class"); | |||
//System.out.println("TASK: " + taskType + " class: " + | |||
// taskClassName); | |||
ClassLoader pcl = this.getClass().getClassLoader(); | |||
TaskClassLoader tcl = new TaskClassLoader(pcl, zf); | |||
try { | |||
Class clazz = tcl.findClass(taskClassName); | |||
abstractTaskClasses.put(taskType, clazz); | |||
} catch (ClassNotFoundException cnfe) { | |||
System.out.println(cnfe); | |||
System.out.println(cnfe.getMessage()); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Sets up the taskpath based on the currently running operating | |||
* system. In general, the ordering of the taskpath is: user directory, | |||
* system directory, and then installation. This allows users or | |||
* system admins to override or add tasks. | |||
*/ | |||
private void setUpTaskPath() { | |||
// 1st, add user's home dir. | |||
File f; | |||
String userHome = System.getProperty("user.home"); | |||
// generic unix | |||
f = new File(userHome + ".ant", "tasks"); | |||
if (f.exists() && f.isDirectory()) { | |||
taskPathNodes.addElement(f); | |||
} | |||
// macos x | |||
f = new File(userHome + "/Library/Ant", "Tasks"); | |||
if (f.exists() && f.isDirectory()) { | |||
taskPathNodes.addElement(f); | |||
} | |||
// windows -- todo | |||
// 2nd, add system local dir. | |||
// generic unix | |||
f = new File("/usr/local/ant/tasks"); | |||
if (f.exists() && f.isDirectory()) { | |||
taskPathNodes.addElement(f); | |||
} | |||
// macos x | |||
f = new File("/Library/Ant/Tasks"); | |||
if (f.exists() && f.isDirectory()) { | |||
taskPathNodes.addElement(f); | |||
} | |||
// windows -- todo | |||
// 3rd, add installation local dir. | |||
//System.out.println("BASE: " + this.getClass().getResource("/")); | |||
// XXX ---- not really sure how the best way of getting this info is... | |||
// hafta think about it. | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
// ------------------------------------------------------------------------------- | |||
// Copyright (c)2000 Apache Software Foundation | |||
// ------------------------------------------------------------------------------- | |||
package org.apache.ant; | |||
/** | |||
* Signals a problem. | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public class AntException extends Exception { | |||
public AntException() { | |||
super(); | |||
} | |||
public AntException(String msg) { | |||
super(msg); | |||
} | |||
} |
@@ -0,0 +1,128 @@ | |||
// --------------------------------------------------------------------- | |||
// (c)2000 Apache Software Foundation | |||
// | |||
// --------------------------------------------------------------------- | |||
package org.apache.ant; | |||
import java.io.*; | |||
import java.util.*; | |||
/** | |||
* In memory container for an Ant project. | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public class Project { | |||
// ----------------------------------------------------------------- | |||
// PRIVATE DATA MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
private Ant ant; | |||
/** | |||
* | |||
*/ | |||
private PrintStream out; | |||
/** | |||
* Parent project to this project, if one exists. | |||
*/ | |||
private Project parentProject = null; | |||
/** | |||
* | |||
*/ | |||
private String name; | |||
/** | |||
* Hashtable containing all of the targets that are part of this | |||
* project. Targets are stored in this hashtable using the name | |||
* of the target as the key and the Target object for the target | |||
* as the value. | |||
*/ | |||
private Hashtable targets = new Hashtable(); | |||
// ----------------------------------------------------------------- | |||
// PUBLIC ACCESSOR METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
public void addTarget(Target target) { | |||
// XXX check out for name, if null, reject! | |||
targets.put(target.getName(), target); | |||
} | |||
/** | |||
* | |||
*/ | |||
public PrintStream getOutput() { | |||
// XXX check if null!!!!???? | |||
return out; | |||
} | |||
/** | |||
* Returns the parent Project object to this Project if a parent | |||
* project exists. If there is not a parent Project object, null | |||
* is returned. | |||
*/ | |||
public Project getParent() { | |||
return parentProject; | |||
} | |||
/** | |||
* Returns the target identified with the given name. If no target | |||
* is known by the given name, then null is returned. | |||
*/ | |||
public Target getTarget(String name) { | |||
return (Target)targets.get(name); | |||
} | |||
/** | |||
* | |||
*/ | |||
public Enumeration getTargets() { | |||
return targets.elements(); | |||
} | |||
/** | |||
* | |||
*/ | |||
public String getName() { | |||
return name; | |||
} | |||
/** | |||
* | |||
*/ | |||
public void setAnt(Ant ant) { | |||
this.ant = ant; | |||
} | |||
/** | |||
* | |||
*/ | |||
public void setOutput(PrintStream out) { | |||
this.out = out; | |||
} | |||
/** | |||
* | |||
*/ | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
/** | |||
* | |||
*/ | |||
public String toString() { | |||
return "Project name=" + name; | |||
} | |||
} |
@@ -0,0 +1,154 @@ | |||
// ------------------------------------------------------------------------------- | |||
// Copyright (c)2000 Apache Software Foundation | |||
// ------------------------------------------------------------------------------- | |||
package org.apache.ant; | |||
import java.io.*; | |||
import javax.xml.parsers.*; | |||
import org.xml.sax.*; | |||
/** | |||
* Helper class to build Project object trees. | |||
* | |||
* XXX right now this class only deals with the primary levels (project/target/task) | |||
* and nothing else. Also, it only supports attributes.... | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
class ProjectBuilder { | |||
private SAXParserFactory parserFactory; | |||
// ----------------------------------------------------------------- | |||
// CONSTRUCTORS | |||
// ----------------------------------------------------------------- | |||
ProjectBuilder() { | |||
parserFactory = SAXParserFactory.newInstance(); | |||
parserFactory.setValidating(false); | |||
} | |||
Project buildFromFile(File file) throws AntException { | |||
try { | |||
SAXParser parser = parserFactory.newSAXParser(); | |||
BuilderHandlerBase bhb = new BuilderHandlerBase(); | |||
parser.parse(file, bhb); | |||
return bhb.getProject(); | |||
} catch (ParserConfigurationException pce) { | |||
throw new AntException(pce.getMessage()); | |||
} catch (SAXException se) { | |||
System.out.println(se); | |||
System.out.println(se.getMessage()); | |||
throw new AntException(se.getMessage()); | |||
} catch (IOException ioe) { | |||
throw new AntException(ioe.getMessage()); | |||
} | |||
} | |||
class BuilderHandlerBase extends HandlerBase { | |||
private static final int STATE_START = 0; | |||
private static final int STATE_PROJECT = 1; | |||
private static final int STATE_TARGET = 2; | |||
private static final int STATE_TASK = 3; | |||
private static final int STATE_FINISHED = 99; | |||
private int state = STATE_START; | |||
private Target currentTarget; | |||
private Task currentTask; | |||
Project project = new Project(); | |||
Project getProject() { | |||
return project; | |||
} | |||
public void startElement(String name, AttributeList atts) throws SAXException { | |||
//System.out.println("element: " + name); | |||
switch (state) { | |||
case STATE_START: | |||
if (name.equals("project")) { | |||
state = STATE_PROJECT; | |||
String projectName = atts.getValue("name"); | |||
if (projectName == null) { | |||
System.out.println("Projects *must* have names"); | |||
// XXX exception out | |||
} | |||
project.setName(projectName); | |||
} else { | |||
System.out.println("Expecting project, got: " + name); | |||
// XXX exception out | |||
} | |||
break; | |||
case STATE_PROJECT: | |||
if (name.equals("target")) { | |||
state = STATE_TARGET; | |||
String targetName = atts.getValue("name"); | |||
if (targetName == null) { | |||
System.out.println("Targets *must* have names"); | |||
// XXX exception out | |||
} | |||
currentTarget = new Target(targetName); | |||
project.addTarget(currentTarget); | |||
// XXX add dependency checks | |||
} else { | |||
System.out.println("Expecting target, got: " + name); | |||
// XXX exception out | |||
} | |||
break; | |||
case STATE_TARGET: | |||
state = STATE_TASK; | |||
//System.out.println("Getting task: " + name + " for target " + | |||
// currentTarget); | |||
// XXX need to validate that task type (name) exists in system | |||
// else exception out. | |||
currentTask = new Task(name); | |||
currentTarget.addTask(currentTask); | |||
for (int i = 0; i < atts.getLength(); i++) { | |||
String atName = atts.getName(i); | |||
String atValue = atts.getValue(i); | |||
currentTask.addAttribute(atName, atValue); | |||
} | |||
break; | |||
default: | |||
System.out.println("I'm not sure, but we're off base here: " + name); | |||
// XXX exception out | |||
} | |||
} | |||
public void characters(char ch[], int start, int length) throws SAXException { | |||
} | |||
public void endElement(String name) throws SAXException { | |||
// System.out.println("end: " + name); | |||
switch (state) { | |||
case STATE_TASK: | |||
state = STATE_TARGET; | |||
break; | |||
case STATE_TARGET: | |||
if (name.equals("target")) { | |||
state = STATE_PROJECT; | |||
} else { | |||
System.out.println("Expecting to get an end of target, got: " + name); | |||
// XXX exception out. | |||
} | |||
break; | |||
case STATE_PROJECT: | |||
if (name.equals("project")) { | |||
state = STATE_FINISHED; | |||
} else { | |||
System.out.println("Expecting to get end of project, got: " + name); | |||
// XXX exception out; | |||
} | |||
break; | |||
default: | |||
System.out.println("I'm not sure what we are ending here: " + name); | |||
// XXX exception out; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
// --------------------------------------------------------------------- | |||
// (c)2000 Apache Software Foundation | |||
// | |||
// --------------------------------------------------------------------- | |||
package org.apache.ant; | |||
import java.util.*; | |||
/** | |||
* In memory container for an Ant target. | |||
*/ | |||
public class Target { | |||
// ----------------------------------------------------------------- | |||
// PRIVATE DATA MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* String containing the name of the target. This name must be | |||
* unique withing a project. | |||
*/ | |||
private String name; | |||
/** | |||
* Vector containing the tasks that are part of this target. | |||
*/ | |||
private Vector tasks = new Vector(); | |||
// ----------------------------------------------------------------- | |||
// CONSTRUCTORS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Constructs a new Target object with the given name. | |||
*/ | |||
public Target(String name) { | |||
this.name = name; | |||
} | |||
// ----------------------------------------------------------------- | |||
// PUBLIC ACCESSOR METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
public void addTask(Task task) { | |||
tasks.addElement(task); | |||
} | |||
/** | |||
* Returns a String containing the name of this Target. | |||
*/ | |||
public String getName() { | |||
return name; | |||
} | |||
/** | |||
* | |||
*/ | |||
public String toString() { | |||
return "TARGET: " + name; | |||
} | |||
/** | |||
* Returns a Vector of Tasks contained in this Target. | |||
* <p> | |||
* Please use caution when using this method. I am not happy | |||
* about exposing this data as something other than a | |||
* Collection, but don't want to use 1.1 collections. So, | |||
* this method may change in the future. You have been warned. | |||
*/ | |||
public Vector getTasks() { | |||
return tasks; | |||
} | |||
} |
@@ -0,0 +1,86 @@ | |||
// --------------------------------------------------------------------- | |||
// (c)2000 Apache Software Foundation | |||
// | |||
// --------------------------------------------------------------------- | |||
package org.apache.ant; | |||
import java.util.*; | |||
/** | |||
* In memory container for an Ant target. | |||
* | |||
* XXX need a way to query which attributes are valid for this particular | |||
* task type... Like into Ant object to do this? | |||
*/ | |||
public class Task { | |||
// ----------------------------------------------------------------- | |||
// PRIVATE DATA MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
private Hashtable attributes = new Hashtable(); | |||
/** | |||
* String containing the type of the task. | |||
*/ | |||
private String type; | |||
// ----------------------------------------------------------------- | |||
// CONSTRUCTORS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Constructs a new Target object with the given name. | |||
*/ | |||
public Task(String type) { | |||
this.type = type; | |||
} | |||
// ----------------------------------------------------------------- | |||
// PUBLIC ACCESSOR METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
public void addAttribute(String name, String value) { | |||
attributes.put(name, value); | |||
} | |||
public String getAttribute(String name) { | |||
return (String)attributes.get(name); | |||
} | |||
/** | |||
* | |||
*/ | |||
public Hashtable getAttributes() { | |||
return attributes; | |||
} | |||
/** | |||
* | |||
*/ | |||
public Enumeration getAttributeNames() { | |||
return attributes.keys(); | |||
} | |||
/** | |||
* Returns a String containing the name of this Target. | |||
*/ | |||
public String getType() { | |||
return type; | |||
} | |||
/** | |||
* | |||
*/ | |||
public String toString() { | |||
return "TASK: " + type; | |||
} | |||
} |
@@ -0,0 +1,103 @@ | |||
package org.apache.ant; | |||
import java.io.*; | |||
import java.util.*; | |||
import java.util.zip.*; | |||
/** | |||
* | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
class TaskClassLoader extends ClassLoader { | |||
// ----------------------------------------------------------------- | |||
// PRIVATE MEMBERS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
private Hashtable cache = new Hashtable(); | |||
/** | |||
* | |||
*/ | |||
private ZipFile zf; | |||
// ----------------------------------------------------------------- | |||
// CONSTRUCTORS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Constructs a classloader that loads classes from the specified | |||
* zip file. | |||
*/ | |||
TaskClassLoader(ClassLoader parent, ZipFile zf) { | |||
super(parent); | |||
this.zf = zf; | |||
} | |||
// ----------------------------------------------------------------- | |||
// PUBLIC METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* | |||
*/ | |||
public Class findClass(String name) | |||
throws ClassNotFoundException | |||
{ | |||
Class c; | |||
try { | |||
return findSystemClass(name); | |||
} catch (ClassNotFoundException cnfe) { | |||
} | |||
try { | |||
return this.getClass().getClassLoader().loadClass(name); | |||
} catch (Exception e) { | |||
} | |||
Object o = cache.get(name); | |||
if (o != null) { | |||
c = (Class)o; | |||
} else { | |||
byte[] data = loadClassData(name); | |||
c = defineClass(data, 0, data.length); | |||
cache.put(name, c); | |||
} | |||
//if (resolve) { | |||
// resolveClass(c); | |||
//} | |||
return c; | |||
} | |||
/** | |||
* | |||
*/ | |||
private byte[] loadClassData(String name) throws ClassNotFoundException { | |||
String newName = name.replace('.', '/'); | |||
ZipEntry ze = zf.getEntry("/" + newName + ".class"); | |||
//System.out.println("/" + newName + ".class"); | |||
//System.out.println("ZE: " + ze); | |||
if (ze != null) { | |||
byte[] buf = new byte[((int)ze.getSize())]; | |||
// System.out.println("ZE SIZE " + ze.getSize()); | |||
try { | |||
InputStream in = zf.getInputStream(ze); | |||
int count = 0; | |||
int thisRead = 0; | |||
while (count < buf.length && thisRead != -1) { | |||
thisRead = in.read(buf, count, buf.length - count); | |||
count += thisRead; | |||
} | |||
in.close(); | |||
} catch (IOException ioe) { | |||
throw new ClassNotFoundException("Can't load class: " + name + " " + | |||
ioe.getMessage()); | |||
} | |||
return buf; | |||
} else { | |||
throw new ClassNotFoundException("Can't find class for: " + name); | |||
} | |||
} | |||
} |
@@ -0,0 +1,89 @@ | |||
// ------------------------------------------------------------------------------- | |||
// Copyright (c)2000 Apache Software Foundation | |||
// ------------------------------------------------------------------------------- | |||
package org.apache.ant.cli; | |||
import java.io.*; | |||
import java.util.*; | |||
import org.apache.ant.*; | |||
/** | |||
* Entry point for Ant on the Command Line Interface. | |||
* | |||
* @author James Duncan Davidson (duncan@apache.org) | |||
*/ | |||
public class Main { | |||
/** | |||
* Command line entry point. | |||
*/ | |||
public static void main(String[] args) { | |||
Ant ant = new Ant(); | |||
String target = ""; | |||
System.out.println("Ant(Eater) -- Proposed Ant 2.0"); | |||
// flip through args and set things accordingly | |||
for (int i = 0; i < args.length; i++) { | |||
String arg = args[i]; | |||
// scan through -- all -aaa args come first. | |||
if (arg.startsWith("-")) { | |||
if (arg.equals("-help")) { | |||
printHelp(); | |||
return; | |||
} else if (arg.equals("-taskpath")) { | |||
// XXX | |||
// need to seperate on pathsep, but not today | |||
ant.addTaskPathNode(new File(args[++i])); | |||
} else if (arg.equals("-buildfile")) { | |||
// XXX | |||
// need to check file to make sure it exists! | |||
try { | |||
ant.setBuildfile(new File(args[++i])); | |||
} catch (AntException ae) { | |||
System.out.println("ICK: " + ae); | |||
System.out.println(ae.getMessage()); | |||
return; | |||
} | |||
} | |||
} else { | |||
target = arg; | |||
} | |||
} | |||
// XXX do something if we dont' have a buildfile set! | |||
// XXX really should check to make sure that the target is set to something | |||
// set our listeners on the project | |||
Project project = ant.getProject(); | |||
project.setOutput(System.out); | |||
System.out.println(); | |||
System.out.println("Executing Target: " + target); | |||
try { | |||
ant.buildTarget(target); | |||
} catch (AntException ae) { | |||
System.out.println("Problem while building: " + ae); | |||
System.out.println(ae.getMessage()); | |||
} | |||
} | |||
// ----------------------------------------------------------------- | |||
// PRIVATE METHODS | |||
// ----------------------------------------------------------------- | |||
/** | |||
* Prints help to System.out | |||
*/ | |||
private static void printHelp() { | |||
System.out.println("Usage: ant [args] [target]"); | |||
System.out.println(" Arguments:"); | |||
System.out.println(" -help"); | |||
System.out.println(" -taskpath [path]"); | |||
System.out.println(" -buildfile [file]"); | |||
} | |||
} |