| // ------------------------------------------------------------------------------- |
| // 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) |
| */ |
| public class TaskManager { |
| |
| // ----------------------------------------------------------------- |
| // PRIVATE DATA MEMBERS |
| // ----------------------------------------------------------------- |
| |
| /** |
| * FrontEnd that this TaskManager can communicate through. |
| */ |
| private AntFrontEnd frontEnd; |
| |
| /** |
| * 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(AntFrontEnd frontEnd) { |
| this.frontEnd = frontEnd; |
| } |
| |
| // ----------------------------------------------------------------- |
| // PUBLIC METHODS |
| // ----------------------------------------------------------------- |
| |
| /** |
| * Adds a node to the task path |
| */ |
| public void addTaskPathNode(File file) throws AntException { |
| taskPathNodes.addElement(file); |
| processTaskPathNode(file); |
| } |
| |
| // ----------------------------------------------------------------- |
| // PACKAGE METHODS |
| // ----------------------------------------------------------------- |
| |
| /** |
| * |
| */ |
| AbstractTask getTaskInstance(String taskName) throws AntException { |
| Class clazz = (Class)taskClasses.get(taskName); |
| try { |
| return (AbstractTask)clazz.newInstance(); |
| } catch (Exception e) { |
| String msg = "Can't instantiate task: " + taskName; |
| AntException ae = new AntException(msg, e); |
| throw ae; |
| } |
| } |
| |
| // ----------------------------------------------------------------- |
| // 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) { |
| frontEnd.writeMessage("Scanning " + dir + " for tasks", |
| AntFrontEnd.MSG_LEVEL_LOW); |
| 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); |
| frontEnd.writeMessage("Got Task: " + taskName + |
| clazz, AntFrontEnd.MSG_LEVEL_LOW); |
| 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) throws AntException { |
| frontEnd.writeMessage("Scanning " + file + " for tasks", |
| AntFrontEnd.MSG_LEVEL_LOW); |
| 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"); |
| if (taskClass == null) { |
| String msg = "No class definition for task " + taskName + |
| "in jar file " + file; |
| throw new AntException(msg); |
| } |
| URLClassLoader loader = new URLClassLoader(new URL[] {file.toURL()}); |
| try { |
| Class clazz = loader.loadClass(taskClass); |
| frontEnd.writeMessage("Got Task: " + taskName + |
| clazz, AntFrontEnd.MSG_LEVEL_LOW); |
| 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) throws AntException { |
| |
| // 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); |
| } |
| } |
| |
| /** |
| * 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() throws AntException { |
| |
| // 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()) { |
| addTaskPathNode(f); |
| } |
| |
| // macos x |
| f = new File(userHome + "/Library/Ant", "Tasks"); |
| if (f.exists() && f.isDirectory()) { |
| addTaskPathNode(f); |
| } |
| |
| // windows -- todo |
| |
| // 2nd, add system local dir. |
| |
| // generic unix |
| f = new File("/usr/local/ant/tasks"); |
| if (f.exists() && f.isDirectory()) { |
| addTaskPathNode(f); |
| } |
| |
| // macos x |
| f = new File("/Library/Ant/Tasks"); |
| if (f.exists() && f.isDirectory()) { |
| addTaskPathNode(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. |
| } |
| |
| } |