Browse Source

Changed task loading to use a centralized TaskManager that keeps tabs on

all classes.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268332 13f79535-47bb-0310-9956-ffa450edef68
master
James Duncan Davidson 24 years ago
parent
commit
e9211a1fb8
5 changed files with 246 additions and 190 deletions
  1. +25
    -9
      proposal/anteater/bootstrap/Bootstrap2.java
  2. +1
    -1
      proposal/anteater/source/coretasks/echo/taskdef.properties
  3. +24
    -77
      proposal/anteater/source/main/org/apache/ant/Ant.java
  4. +0
    -103
      proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java
  5. +196
    -0
      proposal/anteater/source/main/org/apache/ant/TaskManager.java

+ 25
- 9
proposal/anteater/bootstrap/Bootstrap2.java View File

@@ -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
- 1
proposal/anteater/source/coretasks/echo/taskdef.properties View File

@@ -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

+ 24
- 77
proposal/anteater/source/main/org/apache/ant/Ant.java View File

@@ -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


+ 0
- 103
proposal/anteater/source/main/org/apache/ant/TaskClassLoader.java View File

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

+ 196
- 0
proposal/anteater/source/main/org/apache/ant/TaskManager.java View File

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

Loading…
Cancel
Save