diff --git a/proposal/anteater/README b/proposal/anteater/README new file mode 100644 index 000000000..4fc1737ea --- /dev/null +++ b/proposal/anteater/README @@ -0,0 +1,14 @@ +README for Ant(Eater) +--------------------------------------------------------------------------------- + +Execution: + + ant [args] target + +Args: + + -help + -quiet + -verbose + -taskpath [path] + -antfile [file] \ No newline at end of file diff --git a/proposal/anteater/bootstrap/Bootstrap.java b/proposal/anteater/bootstrap/Bootstrap.java new file mode 100644 index 000000000..e15062fa2 --- /dev/null +++ b/proposal/anteater/bootstrap/Bootstrap.java @@ -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.
+ *
+ * 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);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/proposal/anteater/bootstrap/README b/proposal/anteater/bootstrap/README
new file mode 100644
index 000000000..1d551d508
--- /dev/null
+++ b/proposal/anteater/bootstrap/README
@@ -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.
\ No newline at end of file
diff --git a/proposal/anteater/source/coretasks/echo/org/apache/ant/echo/EchoTask.java b/proposal/anteater/source/coretasks/echo/org/apache/ant/echo/EchoTask.java
new file mode 100644
index 000000000..39bc2920e
--- /dev/null
+++ b/proposal/anteater/source/coretasks/echo/org/apache/ant/echo/EchoTask.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/proposal/anteater/source/coretasks/echo/taskdef.properties b/proposal/anteater/source/coretasks/echo/taskdef.properties
new file mode 100644
index 000000000..e8627c8c0
--- /dev/null
+++ b/proposal/anteater/source/coretasks/echo/taskdef.properties
@@ -0,0 +1,4 @@
+# taskdef.properties for Echo task
+
+tasks=echo
+echo.class=org.apache.ant.echo.EchoTask
\ No newline at end of file
diff --git a/proposal/anteater/source/main.ant b/proposal/anteater/source/main.ant
new file mode 100644
index 000000000..a313562a7
--- /dev/null
+++ b/proposal/anteater/source/main.ant
@@ -0,0 +1,13 @@
+
+
+
+ * 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; + } +} \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/Task.java b/proposal/anteater/source/main/org/apache/ant/Task.java new file mode 100644 index 000000000..363c80106 --- /dev/null +++ b/proposal/anteater/source/main/org/apache/ant/Task.java @@ -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; + } + +} \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java b/proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java new file mode 100644 index 000000000..46c8e55a7 --- /dev/null +++ b/proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java @@ -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); + } + } +} \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/cli/Main.java b/proposal/anteater/source/main/org/apache/ant/cli/Main.java new file mode 100644 index 000000000..85dfb3972 --- /dev/null +++ b/proposal/anteater/source/main/org/apache/ant/cli/Main.java @@ -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]"); + } +} \ No newline at end of file