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