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]"); | |||||
} | |||||
} |