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