|
|
@@ -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); |
|
|
|
} |
|
|
|
} |
|
|
|
} |