all classes. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268332 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -4,6 +4,7 @@ | |||||
| import java.io.*; | import java.io.*; | ||||
| import java.util.*; | import java.util.*; | ||||
| import java.util.jar.*; | |||||
| import java.util.zip.*; | import java.util.zip.*; | ||||
| /** | /** | ||||
| @@ -161,31 +162,46 @@ public class Bootstrap2 { | |||||
| private static void jarDir(File dir, File jarfile) throws IOException { | private static void jarDir(File dir, File jarfile) throws IOException { | ||||
| String[] files = dir.list(); | String[] files = dir.list(); | ||||
| if (files.length > 0) { | if (files.length > 0) { | ||||
| System.out.println("Jaring: " + jarfile); | |||||
| System.out.println("Jaring: " + jarfile); | |||||
| FileOutputStream fos = new FileOutputStream(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 | IOException | ||||
| { | { | ||||
| String[] files = dir.list(); | String[] files = dir.list(); | ||||
| for (int i = 0; i < files.length; i++) { | for (int i = 0; i < files.length; i++) { | ||||
| File f = new File(dir, files[i]); | File f = new File(dir, files[i]); | ||||
| if (f.isDirectory()) { | 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 { | } 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); | FileInputStream fis = new FileInputStream(f); | ||||
| int count = 0; | int count = 0; | ||||
| byte[] buf = new byte[8 * 1024]; | byte[] buf = new byte[8 * 1024]; | ||||
| count = fis.read(buf, 0, buf.length); | count = fis.read(buf, 0, buf.length); | ||||
| while (count != -1) { | while (count != -1) { | ||||
| zos.write(buf, 0, count); | |||||
| jos.write(buf, 0, count); | |||||
| count = fis.read(buf, 0, buf.length); | count = fis.read(buf, 0, buf.length); | ||||
| } | } | ||||
| fis.close(); | fis.close(); | ||||
| @@ -1,4 +1,4 @@ | |||||
| # taskdef.properties for Echo task | # taskdef.properties for Echo task | ||||
| tasks=echo | tasks=echo | ||||
| echo.class=org.apache.ant.echo.EchoTask | |||||
| task.echo.class=org.apache.ant.echo.EchoTask | |||||
| @@ -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) { | public void addTaskPathNode(File node) { | ||||
| taskPathNodes.insertElementAt(node, 0); | taskPathNodes.insertElementAt(node, 0); | ||||
| taskManager.addTaskPathNode(node); | |||||
| } | } | ||||
| /** | /** | ||||
| * | * | ||||
| */ | */ | ||||
| public void buildTarget(String targetName) throws AntException { | public void buildTarget(String targetName) throws AntException { | ||||
| try { | |||||
| loadTasks(); | |||||
| } catch (IOException ioe) { | |||||
| throw new AntException(ioe.getMessage()); | |||||
| } | |||||
| Target target = project.getTarget(targetName); | Target target = project.getTarget(targetName); | ||||
| @@ -81,24 +81,18 @@ public class Ant { | |||||
| Enumeration enum = target.getTasks().elements(); | Enumeration enum = target.getTasks().elements(); | ||||
| while (enum.hasMoreElements()) { | while (enum.hasMoreElements()) { | ||||
| Task task = (Task)enum.nextElement(); | 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 | // 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 | * Sets up the taskpath based on the currently running operating | ||||
| * system. In general, the ordering of the taskpath is: user directory, | * system. In general, the ordering of the taskpath is: user directory, | ||||
| @@ -211,13 +158,13 @@ public class Ant { | |||||
| // generic unix | // generic unix | ||||
| f = new File(userHome + ".ant", "tasks"); | f = new File(userHome + ".ant", "tasks"); | ||||
| if (f.exists() && f.isDirectory()) { | if (f.exists() && f.isDirectory()) { | ||||
| taskPathNodes.addElement(f); | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | } | ||||
| // macos x | // macos x | ||||
| f = new File(userHome + "/Library/Ant", "Tasks"); | f = new File(userHome + "/Library/Ant", "Tasks"); | ||||
| if (f.exists() && f.isDirectory()) { | if (f.exists() && f.isDirectory()) { | ||||
| taskPathNodes.addElement(f); | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | } | ||||
| // windows -- todo | // windows -- todo | ||||
| @@ -227,13 +174,13 @@ public class Ant { | |||||
| // generic unix | // generic unix | ||||
| f = new File("/usr/local/ant/tasks"); | f = new File("/usr/local/ant/tasks"); | ||||
| if (f.exists() && f.isDirectory()) { | if (f.exists() && f.isDirectory()) { | ||||
| taskPathNodes.addElement(f); | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | } | ||||
| // macos x | // macos x | ||||
| f = new File("/Library/Ant/Tasks"); | f = new File("/Library/Ant/Tasks"); | ||||
| if (f.exists() && f.isDirectory()) { | if (f.exists() && f.isDirectory()) { | ||||
| taskPathNodes.addElement(f); | |||||
| taskManager.addTaskPathNode(f); | |||||
| } | } | ||||
| // windows -- todo | // windows -- todo | ||||
| @@ -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); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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); | |||||
| } | |||||
| } | |||||
| } | |||||