diff --git a/proposal/anteater/bootstrap/Bootstrap2.java b/proposal/anteater/bootstrap/Bootstrap2.java index 73104afb9..dd6572c68 100644 --- a/proposal/anteater/bootstrap/Bootstrap2.java +++ b/proposal/anteater/bootstrap/Bootstrap2.java @@ -4,6 +4,7 @@ import java.io.*; import java.util.*; +import java.util.jar.*; import java.util.zip.*; /** @@ -161,31 +162,46 @@ public class Bootstrap2 { private static void jarDir(File dir, File jarfile) throws IOException { String[] files = dir.list(); if (files.length > 0) { - System.out.println("Jaring: " + jarfile); + System.out.println("Jaring: " + jarfile); + FileOutputStream fos = new FileOutputStream(jarfile); - ZipOutputStream zos = new ZipOutputStream(fos); - jarDir(dir, "", zos); - zos.close(); + JarOutputStream jos = new JarOutputStream(fos, new Manifest()); + jarDir(dir, "", jos); + jos.close(); } } - private static void jarDir(File dir, String prefix, ZipOutputStream zos) throws + private static void jarDir(File dir, String prefix, JarOutputStream jos) 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); + String zipEntryName; + if (!prefix.equals("")) { + zipEntryName = prefix + "/" + files[i]; + } else { + zipEntryName = files[i]; + } + ZipEntry ze = new ZipEntry(zipEntryName); + jos.putNextEntry(ze); + jarDir(f, zipEntryName, jos); } else { - ZipEntry ze = new ZipEntry(prefix + "/" + files[i]); - zos.putNextEntry(ze); + String zipEntryName; + if (!prefix.equals("")) { + zipEntryName = prefix + "/" + files[i]; + } else { + zipEntryName = files[i]; + } + ZipEntry ze = new ZipEntry(zipEntryName); + jos.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); + jos.write(buf, 0, count); count = fis.read(buf, 0, buf.length); } fis.close(); diff --git a/proposal/anteater/source/coretasks/echo/taskdef.properties b/proposal/anteater/source/coretasks/echo/taskdef.properties index e8627c8c0..8949070db 100644 --- a/proposal/anteater/source/coretasks/echo/taskdef.properties +++ b/proposal/anteater/source/coretasks/echo/taskdef.properties @@ -1,4 +1,4 @@ # taskdef.properties for Echo task tasks=echo -echo.class=org.apache.ant.echo.EchoTask \ No newline at end of file +task.echo.class=org.apache.ant.echo.EchoTask \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/Ant.java b/proposal/anteater/source/main/org/apache/ant/Ant.java index 333e15a55..5da538aed 100644 --- a/proposal/anteater/source/main/org/apache/ant/Ant.java +++ b/proposal/anteater/source/main/org/apache/ant/Ant.java @@ -28,13 +28,18 @@ public class Ant { /** * */ - private Vector taskPathNodes = new Vector(); + private File buildfile; /** - * + * Manager of tasks. */ - private File buildfile; + private TaskManager taskManager = new TaskManager(); + /** + * + */ + private Vector taskPathNodes = new Vector(); + /** * */ @@ -61,18 +66,13 @@ public class Ant { */ public void addTaskPathNode(File node) { taskPathNodes.insertElementAt(node, 0); + taskManager.addTaskPathNode(node); } /** * */ public void buildTarget(String targetName) throws AntException { - - try { - loadTasks(); - } catch (IOException ioe) { - throw new AntException(ioe.getMessage()); - } Target target = project.getTarget(targetName); @@ -81,24 +81,18 @@ public class Ant { 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); + AbstractTask aTask = taskManager.getTaskInstance(task.getType()); + try { + aTask.setProject(project); + aTask.setAttributes(task.getAttributes()); + boolean b = aTask.execute(); + if (!b) { + throw new AntException("STOP: Task " + task + + " did not succeed"); } - } else { - throw new AntException("Don't have a class for task type: " + task); + } catch (Exception e) { + // XXX yes yes yes, this shouldn't be a catch all... + throw new AntException("ERR: " + e); } } } @@ -147,53 +141,6 @@ public class Ant { // 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, @@ -211,13 +158,13 @@ public class Ant { // generic unix f = new File(userHome + ".ant", "tasks"); if (f.exists() && f.isDirectory()) { - taskPathNodes.addElement(f); + taskManager.addTaskPathNode(f); } // macos x f = new File(userHome + "/Library/Ant", "Tasks"); if (f.exists() && f.isDirectory()) { - taskPathNodes.addElement(f); + taskManager.addTaskPathNode(f); } // windows -- todo @@ -227,13 +174,13 @@ public class Ant { // generic unix f = new File("/usr/local/ant/tasks"); if (f.exists() && f.isDirectory()) { - taskPathNodes.addElement(f); + taskManager.addTaskPathNode(f); } // macos x f = new File("/Library/Ant/Tasks"); if (f.exists() && f.isDirectory()) { - taskPathNodes.addElement(f); + taskManager.addTaskPathNode(f); } // windows -- todo diff --git a/proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java b/proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java deleted file mode 100644 index 46c8e55a7..000000000 --- a/proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java +++ /dev/null @@ -1,103 +0,0 @@ -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/TaskManager.java b/proposal/anteater/source/main/org/apache/ant/TaskManager.java new file mode 100644 index 000000000..1c328677c --- /dev/null +++ b/proposal/anteater/source/main/org/apache/ant/TaskManager.java @@ -0,0 +1,196 @@ +// ------------------------------------------------------------------------------- +// Copyright (c)2000 Apache Software Foundation +// ------------------------------------------------------------------------------- + +package org.apache.ant; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.zip.*; + +/** + * Manager of tasks and all things related to tasks. Tasks can be found in a + * wide number of locations -- and most of these locations require class loading + * help. As well, new nodes on the task search path may be added at any time. + * When these are added, new tasks should be scanned for. + * + * @author James Duncan Davidson (duncan@apache.org) + */ +class TaskManager { + + // ----------------------------------------------------------------- + // PRIVATE DATA MEMBERS + // ----------------------------------------------------------------- + + /** + * Data structure where all the Class definition for all known tasks are + * held. + */ + private Hashtable taskClasses = new Hashtable(); + + /** + * Data structure that holds all the nodes where tasks are picked up from. + */ + private Vector taskPathNodes = new Vector(); + + // ----------------------------------------------------------------- + // CONSTRUCTORS + // ----------------------------------------------------------------- + + /** + * Creates a new TaskManager. + */ + TaskManager() { + } + + // ----------------------------------------------------------------- + // PACKAGE METHODS + // ----------------------------------------------------------------- + + /** + * Adds a node to the task path + */ + void addTaskPathNode(File file) { + taskPathNodes.addElement(file); + processTaskPathNode(file); + } + + /** + * + */ + AbstractTask getTaskInstance(String taskName) { + Class clazz = (Class)taskClasses.get(taskName); + try { + return (AbstractTask)clazz.newInstance(); + } catch (Exception e) { + System.out.println("Can't instantiate task: " + taskName); + System.out.println(e); + // XXX error out and stop + } + return null; + } + + // ----------------------------------------------------------------- + // PRIVATE METHODS + // ----------------------------------------------------------------- + + /** + * Returns an enum of the task names that are defined in a given + * properties file. + */ + private Enumeration getTaskNames(Properties props) { + Vector v = new Vector(); + String s = props.getProperty("tasks"); + StringTokenizer tok = new StringTokenizer(s, ",", false); + while (tok.hasMoreTokens()) { + String taskName = tok.nextToken().trim(); + v.addElement(taskName); + } + return v.elements(); + } + + /** + * Processes a directory to get class defintions from it + */ + private void processDir(File dir) { + System.out.println("Scanning " + dir + " for tasks"); + File file = new File(dir, "taskdef.properties"); + if (file.exists()) { + try { + InputStream in = new FileInputStream(file); + Properties props = new Properties(); + props.load(in); + in.close(); + + Enumeration enum = getTaskNames(props); + while (enum.hasMoreElements()) { + String taskName = (String)enum.nextElement(); + String taskClass = props.getProperty("task." + taskName + ".class"); + URLClassLoader loader = new URLClassLoader(new URL[] {dir.toURL()}); + try { + Class clazz = loader.loadClass(taskClass); + System.out.println("Got task: " + taskName + " " + clazz); + taskClasses.put(taskName, clazz); + } catch (ClassNotFoundException cnfe) { + System.out.println("Couldn't load task: " + taskName); + System.out.println(cnfe); + // XXX error out and stop.... + } + } + } catch (IOException ioe) { + System.out.println("Could not work with dir: " + dir); + System.out.println(ioe); + // XXX error out and stop the build + } + } + } + + /** + * Processes a jar file to get class definitions from it + */ + private void processJar(File file) { + System.out.println("Scanning " + file + " for tasks"); + try { + ZipFile zipFile = new ZipFile(file); + ZipEntry zipEntry = zipFile.getEntry("taskdef.properties"); + if (zipEntry != null) { + InputStream in = zipFile.getInputStream(zipEntry); + Properties props = new Properties(); + props.load(in); + in.close(); + + Enumeration enum = getTaskNames(props); + while (enum.hasMoreElements()) { + String taskName = (String)enum.nextElement(); + String taskClass = props.getProperty("task." + taskName + ".class"); + URLClassLoader loader = new URLClassLoader(new URL[] {file.toURL()}); + try { + Class clazz = loader.loadClass(taskClass); + System.out.println("Got Task: " + taskName + " " + clazz); + taskClasses.put(taskName, clazz); + } catch (ClassNotFoundException cnfe) { + System.out.println("Couldn't load task: " + taskName); + System.out.println(cnfe); + // XXX error out and stop.... + } + } + } + // make sure to not leave resources hanging + zipFile.close(); + } catch (IOException ioe) { + System.out.println("Couldn't work with file: " + file); + System.out.println(ioe); + // XXX need to exception out of here properly to stop things + } + } + + /** + * Processes a node of the task path searching for task definitions there + * and adding them to the list of known tasks + */ + private void processTaskPathNode(File file) { + + // task path nodes can be any of the following: + // * jar file + // * directory of jar files + // * directory holding class files + + if(file.isDirectory()) { + // first look for all jar files here + // second look for a taskdefs.properties here to see if we should + // treat the directory as a classpath + + String[] files = file.list(); + for (int i = 0; i < files.length; i++) { + if (files[i].endsWith(".jar")) { + processJar(new File(file, files[i])); + } else if (files[i].equals("taskdef.properties")) { + processDir(file); + } + } + } else if (file.getName().endsWith(".jar")) { + processJar(file); + } + } +} \ No newline at end of file