Browse Source

once again for Jose Alberto - think I got it right this time

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271710 13f79535-47bb-0310-9956-ffa450edef68
master
Erik Hatcher 23 years ago
parent
commit
6252354506
10 changed files with 1971 additions and 1201 deletions
  1. +40
    -6
      proposal/sandbox/antlib/build.xml
  2. +993
    -546
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java
  3. +96
    -60
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java
  4. +5
    -0
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java
  5. +358
    -288
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java
  6. +22
    -14
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java
  7. +1
    -23
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Ant.java
  8. +9
    -5
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antjar.java
  9. +426
    -256
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antlib.java
  10. +21
    -3
      proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java

+ 40
- 6
proposal/sandbox/antlib/build.xml View File

@@ -6,21 +6,24 @@
<property name='build' location='build' /> <property name='build' location='build' />
<property name='dist' location='dist' /> <property name='dist' location='dist' />
<property name='classes' location='${build}/classes' /> <property name='classes' location='${build}/classes' />
<property name='testcases' location='src/testcases' />


<property name="debug" value="true" /> <property name="debug" value="true" />
<property name="deprecation" value="false" /> <property name="deprecation" value="false" />
<property name="optimize" value="true" /> <property name="optimize" value="true" />
<target name='init'> <target name='init'>
<ant target='build' dir='${orig}' inheritAll='false' /> <ant target='build' dir='${orig}' inheritAll='false' />
<mkdir dir='${classes}' /> <mkdir dir='${classes}' />
<copy toDir='${classes}' preservelastmodified='true' > <copy toDir='${classes}' preservelastmodified='true' >
<fileset dir='${orig-classes}'> <fileset dir='${orig-classes}'>
<include name='**' /> <include name='**' />
<exclude name='org/apache/tools/ant/Project.class' />
<exclude name='org/apache/tools/ant/TaskAdapter.class' />
<exclude name='org/apache/tools/ant/taskdefs/Ant.class' />
<exclude name='org/apache/tools/ant/Project.class' />
<exclude name='org/apache/tools/ant/ProjectHelper.class' />
<exclude name='org/apache/tools/ant/IntrospectionHelper.class' />
<exclude name='org/apache/tools/ant/TaskAdapter.class' />
<exclude name='org/apache/tools/ant/taskdefs/Ant.class' />
</fileset> </fileset>
</copy> </copy>
</target> </target>
@@ -39,6 +42,32 @@
<property name="build.dir" value="${build}"/> <property name="build.dir" value="${build}"/>
<property name="dist.dir" value="${dist}"/> <property name="dist.dir" value="${dist}"/>
</ant> </ant>
<!--
Rejar things to use lib descriptors
It needs to work with the original ANT processor
-->
<path id="newtasks">
<pathelement location="${classes}" />
</path>
<taskdef name="antjar" classname="org.apache.tools.ant.taskdefs.Antjar"
classpathref="newtasks" />
<taskdef name="antlib" classname="org.apache.tools.ant.taskdefs.Antlib"
classpathref="newtasks" />
<mkdir dir='${dist}/autolib' />
<antjar antxml="src/main/org/apache/tools/ant/opt-antlib.xml"
destfile="${dist}/autolib/optional.jar" >
<zipfileset src="${dist}/lib/optional.jar" >
<include name="**/*" />
</zipfileset>
</antjar>
<antjar antxml="src/main/org/apache/tools/ant/antlib.xml"
destfile="${dist}/lib/newant.jar" >
<zipfileset src="${dist}/lib/ant.jar" >
<include name="**/*" />
</zipfileset>
</antjar>
<delete file="${dist}/lib/optional.jar" />
<move file="${dist}/lib/newant.jar" tofile="${dist}/lib/ant.jar"/>
</target> </target>


<target name='compile'> <target name='compile'>
@@ -48,6 +77,11 @@
optimize="${optimize}"> optimize="${optimize}">
<include name='**/*.java'/> <include name='**/*.java'/>
</javac> </javac>
<copy toDir='${classes}' preservelastmodified='true' >
<fileset dir='src/main'>
<include name='**/*.xml' />
</fileset>
</copy>
</target> </target>


<target name='clean'> <target name='clean'>
@@ -56,7 +90,7 @@


<target name='test'> <target name='test'>
<ant dir='${testcases}' inheritAll='false'/> <ant dir='${testcases}' inheritAll='false'/>
<ant dir='${testcases}'
<ant dir='${testcases}'
antfile='${testcases}/case.xml' inheritAll='false'/> antfile='${testcases}/case.xml' inheritAll='false'/>
</target> </target>




+ 993
- 546
proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java
File diff suppressed because it is too large
View File


+ 96
- 60
proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java View File

@@ -114,7 +114,7 @@ public class ProjectHelper {
private void parse() throws BuildException { private void parse() throws BuildException {
FileInputStream inputStream = null; FileInputStream inputStream = null;
InputSource inputSource = null; InputSource inputSource = null;
try { try {
SAXParser saxParser = getParserFactory().newSAXParser(); SAXParser saxParser = getParserFactory().newSAXParser();
parser = saxParser.getParser(); parser = saxParser.getParser();
@@ -123,7 +123,7 @@ public class ProjectHelper {
for (int index = uri.indexOf('#'); index != -1; index = uri.indexOf('#')) { for (int index = uri.indexOf('#'); index != -1; index = uri.indexOf('#')) {
uri = uri.substring(0, index) + "%23" + uri.substring(index+1); uri = uri.substring(0, index) + "%23" + uri.substring(index+1);
} }
inputStream = new FileInputStream(buildFile); inputStream = new FileInputStream(buildFile);
inputSource = new InputSource(inputStream); inputSource = new InputSource(inputStream);
inputSource.setSystemId(uri); inputSource.setSystemId(uri);
@@ -145,7 +145,7 @@ public class ProjectHelper {
} }
throw be; throw be;
} }
throw new BuildException(exc.getMessage(), t, location); throw new BuildException(exc.getMessage(), t, location);
} }
catch(SAXException exc) { catch(SAXException exc) {
@@ -231,20 +231,20 @@ public class ProjectHelper {
*/ */
public InputSource resolveEntity(String publicId, public InputSource resolveEntity(String publicId,
String systemId) { String systemId) {
project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE); project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
if (systemId.startsWith("file:")) { if (systemId.startsWith("file:")) {
String path = systemId.substring(5); String path = systemId.substring(5);
int index = path.indexOf("file:"); int index = path.indexOf("file:");
// we only have to handle these for backward compatibility // we only have to handle these for backward compatibility
// since they are in the FAQ. // since they are in the FAQ.
while (index != -1) { while (index != -1) {
path = path.substring(0, index) + path.substring(index + 5); path = path.substring(0, index) + path.substring(index + 5);
index = path.indexOf("file:"); index = path.indexOf("file:");
} }
String entitySystemId = path; String entitySystemId = path;
index = path.indexOf("%23"); index = path.indexOf("%23");
// convert these to # // convert these to #
@@ -257,13 +257,13 @@ public class ProjectHelper {
if (!file.isAbsolute()) { if (!file.isAbsolute()) {
file = new File(buildFileParent, path); file = new File(buildFileParent, path);
} }
try { try {
InputSource inputSource = new InputSource(new FileInputStream(file)); InputSource inputSource = new InputSource(new FileInputStream(file));
inputSource.setSystemId("file:" + entitySystemId); inputSource.setSystemId("file:" + entitySystemId);
return inputSource; return inputSource;
} catch (FileNotFoundException fne) { } catch (FileNotFoundException fne) {
project.log(file.getAbsolutePath()+" could not be found",
project.log(file.getAbsolutePath()+" could not be found",
Project.MSG_WARN); Project.MSG_WARN);
} }
} }
@@ -316,10 +316,10 @@ public class ProjectHelper {
} }


if (def == null) { if (def == null) {
throw new SAXParseException("The default attribute of project is required",
throw new SAXParseException("The default attribute of project is required",
locator); locator);
} }


project.setDefaultTarget(def); project.setDefaultTarget(def);


@@ -360,6 +360,8 @@ public class ProjectHelper {
handleTopTask(name, attrs); handleTopTask(name, attrs);
} else if (name.equals("target")) { } else if (name.equals("target")) {
handleTarget(name, attrs); handleTarget(name, attrs);
} else if (name.equals("description")) {
handleDescription(name, attrs);
} else if (project.isDefinedOnRole(Project.DATATYPE_ROLE, name)) { } else if (project.isDefinedOnRole(Project.DATATYPE_ROLE, name)) {
handleTopTask(name, attrs); handleTopTask(name, attrs);
} else { } else {
@@ -367,9 +369,9 @@ public class ProjectHelper {
} }
} }


private void handleTopTask(String name, AttributeList attrs)
throws SAXParseException {
InmediateTarget target = new InmediateTarget(name);
private void handleTopTask(String name, AttributeList attrs)
throws SAXParseException {
InmediateTarget target = new InmediateTarget(name);
(new TaskHandler(this, target, null, target)).init(name, attrs); (new TaskHandler(this, target, null, target)).init(name, attrs);
} }


@@ -377,6 +379,10 @@ public class ProjectHelper {
new TargetHandler(this).init(tag, attrs); new TargetHandler(this).init(tag, attrs);
} }


private void handleDescription(String tag, AttributeList attrs) throws SAXParseException {
new DescriptionHandler(this).init(tag, attrs);
}

} }


/** /**
@@ -441,8 +447,13 @@ public class ProjectHelper {
} }


public void startElement(String name, AttributeList attrs) throws SAXParseException { public void startElement(String name, AttributeList attrs) throws SAXParseException {
new TaskHandler(this, target, null, target).init(name, attrs);
}
if (name.equals("description")) {
new DescriptionHandler(this).init(name, attrs);
}
else {
new TaskHandler(this, target, null, target).init(name, attrs);
}
}
} }


/** /**
@@ -466,7 +477,7 @@ public class ProjectHelper {
try { try {
task = (Task)project.createInRole(container, tag); task = (Task)project.createInRole(container, tag);
} catch (BuildException e) { } catch (BuildException e) {
// swallow here, will be thrown again in
// swallow here, will be thrown again in
// UnknownElement.maybeConfigure if the problem persists. // UnknownElement.maybeConfigure if the problem persists.
} }


@@ -475,21 +486,21 @@ public class ProjectHelper {
task.setProject(project); task.setProject(project);
task.setTaskType(tag); task.setTaskType(tag);
task.setTaskName(tag); task.setTaskName(tag);
container.addTask(task);
container.addTask(task);
} }


task.setLocation(new Location(buildFile.toString(),
locator.getLineNumber(),
locator.getColumnNumber()));
task.setLocation(new Location(buildFile.toString(),
locator.getLineNumber(),
locator.getColumnNumber()));
configureId(task, attrs); configureId(task, attrs);


task.setOwningTarget(target);
task.init();
wrapper = task.getRuntimeConfigurableWrapper();
wrapper.setAttributes(attrs);
if (parentWrapper != null) {
parentWrapper.addChild(wrapper);
}
task.setOwningTarget(target);
task.init();
wrapper = task.getRuntimeConfigurableWrapper();
wrapper.setAttributes(attrs);
if (parentWrapper != null) {
parentWrapper.addChild(wrapper);
}
} }


protected void finished() { protected void finished() {
@@ -531,7 +542,7 @@ public class ProjectHelper {
private RuntimeConfigurable childWrapper = null; private RuntimeConfigurable childWrapper = null;
private Target target; private Target target;


public NestedElementHandler(DocumentHandler parentHandler,
public NestedElementHandler(DocumentHandler parentHandler,
Object parent, Object parent,
RuntimeConfigurable parentWrapper, RuntimeConfigurable parentWrapper,
Target target) { Target target) {
@@ -548,7 +559,7 @@ public class ProjectHelper {


public void init(String propType, AttributeList attrs) throws SAXParseException { public void init(String propType, AttributeList attrs) throws SAXParseException {
Class parentClass = parent.getClass(); Class parentClass = parent.getClass();
IntrospectionHelper ih =
IntrospectionHelper ih =
IntrospectionHelper.getHelper(parentClass); IntrospectionHelper.getHelper(parentClass);


try { try {
@@ -557,9 +568,9 @@ public class ProjectHelper {
UnknownElement uc = new UnknownElement(elementName); UnknownElement uc = new UnknownElement(elementName);
uc.setProject(project); uc.setProject(project);
((UnknownElement) parent).addChild(uc); ((UnknownElement) parent).addChild(uc);
// Set this parameters just in case is a Task
uc.setTaskType(elementName);
uc.setTaskName(elementName);
// Set this parameters just in case is a Task
uc.setTaskType(elementName);
uc.setTaskName(elementName);
child = uc; child = uc;
} else { } else {
child = ih.createElement(project, parent, elementName); child = ih.createElement(project, parent, elementName);
@@ -594,7 +605,7 @@ public class ProjectHelper {


public void startElement(String name, AttributeList attrs) throws SAXParseException { public void startElement(String name, AttributeList attrs) throws SAXParseException {
if (child instanceof TaskContainer) { if (child instanceof TaskContainer) {
// taskcontainer nested element can contain other tasks - no other
// taskcontainer nested element can contain other tasks - no other
// nested elements possible // nested elements possible
new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs); new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs);
} }
@@ -604,39 +615,64 @@ public class ProjectHelper {
} }
} }


/**
* Handler to perform appropriate semantics for the special
* <description> element on tasks.
*/
private class DescriptionHandler extends AbstractHandler {

public DescriptionHandler(DocumentHandler parent) {
super(parent);
}

public void init(String tag, AttributeList attrs) throws SAXParseException {
if (attrs.getLength() > 0) {
throw new SAXParseException("No attributes allowed on " + tag, locator);
}
}

public void characters(char[] buf, int start, int end) throws SAXParseException {
String desc = project.getDescription();
if (desc == null) {
desc = "";
}
project.setDescription(desc + new String(buf, start, end));
}
}

/** /**
* Special target type for top level Tasks and Datatypes. * Special target type for top level Tasks and Datatypes.
* This will allow eliminating special cases. * This will allow eliminating special cases.
*/ */
private class InmediateTarget extends Target { private class InmediateTarget extends Target {
/**
* Create a target for a top level task or datatype.
* @param name the name of the task to be run on this target.
*/
InmediateTarget(String name) {
super();
setProject(project);
setName("Top level " + name);
}
/**
* Create a target for a top level task or datatype.
* @param name the name of the task to be run on this target.
*/
InmediateTarget(String name) {
super();
setProject(project);
setName("Top level " + name);
}
} }


public static void configure(Object target, AttributeList attrs,
public static void configure(Object target, AttributeList attrs,
Project project) throws BuildException { Project project) throws BuildException {
if( target instanceof RoleAdapter ) { if( target instanceof RoleAdapter ) {
target=((RoleAdapter)target).getProxy(); target=((RoleAdapter)target).getProxy();
} }


IntrospectionHelper ih =
IntrospectionHelper ih =
IntrospectionHelper.getHelper(target.getClass()); IntrospectionHelper.getHelper(target.getClass());


project.addBuildListener(ih); project.addBuildListener(ih);


for (int i = 0; i < attrs.getLength(); i++) { for (int i = 0; i < attrs.getLength(); i++) {
// reflect these into the target // reflect these into the target
String value=replaceProperties(project, attrs.getValue(i),
String value=replaceProperties(project, attrs.getValue(i),
project.getProperties() ); project.getProperties() );
try { try {
ih.setAttribute(project, target,
ih.setAttribute(project, target,
attrs.getName(i).toLowerCase(Locale.US), value); attrs.getName(i).toLowerCase(Locale.US), value);


} catch (BuildException be) { } catch (BuildException be) {
@@ -674,7 +710,7 @@ public class ProjectHelper {
} }


/** /**
* Stores a configured child element into its parent object
* Stores a configured child element into its parent object
*/ */
public static void storeChild(Project project, Object parent, Object child, String tag) { public static void storeChild(Project project, Object parent, Object child, String tag) {
IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass()); IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass());
@@ -719,23 +755,23 @@ public class ProjectHelper {
if (!keys.containsKey(propertyName)) { if (!keys.containsKey(propertyName)) {
project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE); project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE);
} }
fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName)
: "${" + propertyName + "}";
fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName)
: "${" + propertyName + "}";
} }
sb.append(fragment); sb.append(fragment);
}
}
return sb.toString(); return sb.toString();
} }


/** /**
* This method will parse a string containing ${value} style
* This method will parse a string containing ${value} style
* property values into two lists. The first list is a collection * property values into two lists. The first list is a collection
* of text fragments, while the other is a set of string property names * of text fragments, while the other is a set of string property names
* null entries in the first list indicate a property reference from the * null entries in the first list indicate a property reference from the
* second list. * second list.
*/ */
public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs)
public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs)
throws BuildException { throws BuildException {
int prev = 0; int prev = 0;
int pos; int pos;
@@ -754,7 +790,7 @@ public class ProjectHelper {
} else { } else {
int endName = value.indexOf('}', pos); int endName = value.indexOf('}', pos);
if (endName < 0) { if (endName < 0) {
throw new BuildException("Syntax error in property: "
throw new BuildException("Syntax error in property: "
+ value ); + value );
} }
String propertyName = value.substring(pos + 2, endName); String propertyName = value.substring(pos + 2, endName);
@@ -779,17 +815,17 @@ public class ProjectHelper {


/** /**
* Scan AttributeList for the id attribute and maybe add a * Scan AttributeList for the id attribute and maybe add a
* reference to project.
* reference to project.
* *
* <p>Moved out of {@link #configure configure} to make it happen * <p>Moved out of {@link #configure configure} to make it happen
* at parser time.</p>
* at parser time.</p>
*/ */
private void configureId(Object target, AttributeList attr) { private void configureId(Object target, AttributeList attr) {
String id = attr.getValue("id"); String id = attr.getValue("id");
if (id != null) { if (id != null) {
if( target instanceof RoleAdapter ) {
((RoleAdapter)target).setId(id);
}
if( target instanceof RoleAdapter ) {
((RoleAdapter)target).setId(id);
}
project.addReference(id, target); project.addReference(id, target);
} }
} }


+ 5
- 0
proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java View File

@@ -55,6 +55,11 @@ package org.apache.tools.ant;


public interface RoleAdapter { public interface RoleAdapter {


/**
* Obtain the id in case it is needed.
*/
public void setId(String id);

/** /**
* Set the object being adapted. * Set the object being adapted.
* @param o the object being adapted * @param o the object being adapted


+ 358
- 288
proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java View File

@@ -54,6 +54,7 @@
package org.apache.tools.ant; package org.apache.tools.ant;


import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
@@ -64,7 +65,7 @@ public class SymbolTable {


/** Parent symbol table */ /** Parent symbol table */
private SymbolTable parentTable; private SymbolTable parentTable;
/** Project associated with this symbol table */ /** Project associated with this symbol table */
private Project project; private Project project;


@@ -82,8 +83,8 @@ public class SymbolTable {
/** /**
* Parameters for checking adapters. * Parameters for checking adapters.
*/ */
private static final Class[] CHECK_ADAPTER_PARAMS =
new Class[]{Class.class, Project.class};
private static final Class[] CHECK_ADAPTER_PARAMS =
new Class[]{Class.class, Project.class};


/** /**
* Create a top level Symbol table. * Create a top level Symbol table.
@@ -96,8 +97,8 @@ public class SymbolTable {
* from that defined in the calling Project. * from that defined in the calling Project.
* @param p the calling project * @param p the calling project
*/ */
public SymbolTable(Project p) {
parentTable = p.getSymbols();
public SymbolTable(SymbolTable st) {
parentTable = st;
} }


/** /**
@@ -105,7 +106,55 @@ public class SymbolTable {
* @param p the project for this symbol table * @param p the project for this symbol table
*/ */
public void setProject(Project p) { public void setProject(Project p) {
this.project = p;
this.project = p;
}

/**
* Get the specified loader for the project.
* @param name the name of the loader
* @return the corresponding ANT classloader
*/
private AntClassLoader getLoader(String name) {
AntClassLoader cl = (AntClassLoader) loaders.get(name);
if (cl == null && parentTable != null) {
return parentTable.getLoader(name);
}
return cl;
}

/**
* Add the specified class-path to a loader.
* If the loader is defined in an ancestor project then a new
* classloader inheritin from the one already existing
* will be created, otherwise the path willbe added to the existing
* ClassLoader.
* @param name the name of the loader to use.
* @param clspath the path to be added to the classloader
*/
public ClassLoader addToLoader(String name, Path clspath) {
// Find if the loader is already defined in the current project
AntClassLoader cl = (AntClassLoader) loaders.get(name);
if (cl == null) {
// Is it inherited from the calling project
if (parentTable != null) {
cl = parentTable.getLoader(name);
}
cl = new AntClassLoader(cl, project, clspath, true);
loaders.put(name, cl);
}
else {
// Add additional path to the existing definition
String[] pathElements = clspath.list();
for (int i = 0; i < pathElements.length; ++i) {
try {
cl.addPathElement(pathElements[i]);
}
catch (BuildException e) {
// ignore path elements invalid relative to the project
}
}
}
return cl;
} }


/** /**
@@ -115,9 +164,9 @@ public class SymbolTable {
* @return an array of roles supported by the class * @return an array of roles supported by the class
*/ */
public String[] findRoles(final Class clz) { public String[] findRoles(final Class clz) {
Vector list = new Vector();
findRoles(clz, list);
return (String[])list.toArray(new String[list.size()]);
Vector list = new Vector();
findRoles(clz, list);
return (String[])list.toArray(new String[list.size()]);
} }


/** /**
@@ -126,27 +175,27 @@ public class SymbolTable {
* @param list the roles collected up to this point * @param list the roles collected up to this point
*/ */
private void findRoles(final Class clz, Vector list) { private void findRoles(final Class clz, Vector list) {
for (Enumeration e = roles.keys(); e.hasMoreElements();) {
String role = (String) e.nextElement();
if (((Role) roles.get(role)).isImplementedBy(clz)) {
list.addElement(role);
}
}
if (parentTable != null) findRoles(clz, list);
for (Enumeration e = roles.keys(); e.hasMoreElements();) {
String role = (String) e.nextElement();
if (((Role) roles.get(role)).isImplementedBy(clz)) {
list.addElement(role);
}
}
if (parentTable != null) parentTable.findRoles(clz, list);
} }
/** /**
* Get the Role definition * Get the Role definition
* @param role the name of the role * @param role the name of the role
* @return the method used to support objects on this role
* @return the Role description
*/ */
public Role getRole(String role) { public Role getRole(String role) {
Role r = (Role) roles.get(role);
if (r == null && parentTable != null) {
return parentTable.getRole(role);
}
return r;
Role r = (Role) roles.get(role);
if (r == null && parentTable != null) {
return parentTable.getRole(role);
}
return r;
} }


/** /**
@@ -157,126 +206,19 @@ public class SymbolTable {
* @return whether the role replaced a different definition * @return whether the role replaced a different definition
*/ */
public boolean addRole(String role, Class rclz, Class aclz) { public boolean addRole(String role, Class rclz, Class aclz) {
// Check if role already declared
Role old = getRole(role);
if (old != null && old.isSameAsFor(rclz, aclz)
) {
project.log("Ignoring override for role " + role
+ ", it is already defined by the same definition.",
project.MSG_VERBOSE);
return false;
}
// Role interfaces should only contain one method
roles.put(role, new Role(rclz, aclz));
return (old != null);
}

/**
* Verify if the interface is valid.
* @param clz the interface to validate
* @return the method defined by the interface
*/
private Method validInterface(Class clz) {
Method m[] = clz.getDeclaredMethods();
if (m.length == 1
&& java.lang.Void.TYPE.equals(m[0].getReturnType())) {
Class args[] = m[0].getParameterTypes();
if (args.length == 1
&& !java.lang.String.class.equals(args[0])
&& !args[0].isArray()
&& !args[0].isPrimitive()) {
return m[0];
}
else {
throw new BuildException("Invalid role interface method in: "
+ clz.getName());
}
}
else {
throw new BuildException("More than one method on role interface");
}
}

/**
* Verify if the adapter is valid with respect to the interface.
* @param clz the class adapter to validate
* @param mtd the method whose only argument must match
* @return the static method to use for validating adaptees
*/
private Method validAdapter(Class clz, Method mtd) {
if (clz == null) return null;
checkClass(clz);
if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) {
String msg = "Adapter " + clz.getName() +
" is incompatible with role interface " +
mtd.getDeclaringClass().getName();
throw new BuildException(msg);
}
String msg = "Class " + clz.getName() + " is not an adapter: ";
if (!RoleAdapter.class.isAssignableFrom(clz)) {
throw new BuildException(msg + "does not implement RoleAdapter");
}
try {
Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS);
if (!Modifier.isStatic(chk.getModifiers())) {
throw new BuildException(msg + "checkClass() is not static");
}
return chk;
}
catch(NoSuchMethodException nme){
throw new BuildException(msg + "checkClass() not found", nme);
}
}

/**
* Get the specified loader for the project.
* @param name the name of the loader
* @return the corresponding ANT classloader
*/
private AntClassLoader getLoader(String name) {
AntClassLoader cl = (AntClassLoader) loaders.get(name);
if (cl == null && parentTable != null) {
return parentTable.getLoader(name);
}
return cl;
// Check if role already declared
Role old = getRole(role);
if (old != null && old.isSameAsFor(rclz, aclz)) {
project.log("Ignoring override for role " + role
+ ", it is already defined by the same definition.",
project.MSG_VERBOSE);
return false;
}
// Role interfaces should only contain one method
roles.put(role, new Role(rclz, aclz));
return (old != null);
} }


/**
* Add the specified class-path to a loader.
* If the loader is defined in an ancestor project then a new
* classloader inheritin from the one already existing
* will be created, otherwise the path willbe added to the existing
* ClassLoader.
* @param name the name of the loader to use.
* @param clspath the path to be added to the classloader
*/
public ClassLoader addToLoader(String name, Path clspath) {
// Find if the loader is already defined in the current project
AntClassLoader cl = (AntClassLoader) loaders.get(name);
if (cl == null) {
// Is it inherited from the calling project
if (parentTable != null) {
cl = parentTable.getLoader(name);
}
cl = new AntClassLoader(cl, project, clspath, true);
loaders.put(name, cl);
}
else {
// Add additional path to the existing definition
String[] pathElements = clspath.list();
for (int i = 0; i < pathElements.length; ++i) {
try {
cl.addPathElement(pathElements[i]);
}
catch (BuildException e) {
// ignore path elements invalid relative to the project
}
}
}
return cl;
}
/** /**
* Add a new type of element to a role. * Add a new type of element to a role.
* @param role the role for this Class. * @param role the role for this Class.
@@ -285,46 +227,53 @@ public class SymbolTable {
* @return the old definition * @return the old definition
*/ */
public Class add(String role, String name, Class clz) { public Class add(String role, String name, Class clz) {
// Find the role definition
Role r = getRole(role);
if (r == null) {
throw new BuildException("Unknown role: " + role);
}
// Check if it is already defined
Class old = get(role, name);
if (old != null) {
if (old.equals(clz)) {
project.log("Ignoring override for "+ role + " " + name
+ ", it is already defined by the same class.",
project.MSG_VERBOSE);
return old;
}
else {
// Find the role definition
Role r = getRole(role);
if (r == null) {
throw new BuildException("Unknown role: " + role);
}
// Check if it is already defined
Factory old = get(role, name);
if (old != null) {
if (old.getOriginalClass().equals(clz)) {
project.log("Ignoring override for "+ role + " " + name
+ ", it is already defined by the same class.",
project.MSG_VERBOSE);
return old.getOriginalClass();
}
else {
project.log("Trying to override old definition of " + project.log("Trying to override old definition of " +
role + " " + name,
project.MSG_WARN);
}
}
checkClass(clz);
// Check that the Class is compatible with the role definition
r.verifyAdaptability(role, clz);
// Record the new type
Hashtable defTable = (Hashtable)defs.get(role);
if (defTable == null) {
defTable = new Hashtable();
defs.put(role, defTable);
}
defTable.put(name, clz);
return old;
role + " " + name,
project.MSG_WARN);
}
}
Factory f = checkClass(clz);
// Check that the Class is compatible with the role definition
f = r.verifyAdaptability(role, f);
// Record the new type
Hashtable defTable = (Hashtable)defs.get(role);
if (defTable == null) {
defTable = new Hashtable();
defs.put(role, defTable);
}
defTable.put(name, f);

String msg =
" +User " + role + ": " + name + " " + clz.getName();
project.log(msg, project.MSG_DEBUG);
return (old != null ? old.getOriginalClass() : null);
} }


/** /**
* Checks a class, whether it is suitable for serving in ANT. * Checks a class, whether it is suitable for serving in ANT.
* @return the factory to use when instantiating the class
* @throws BuildException and logs as Project.MSG_ERR for * @throws BuildException and logs as Project.MSG_ERR for
* conditions, that will cause execution to fail. * conditions, that will cause execution to fail.
*/ */
void checkClass(final Class clz)
throws BuildException {
Factory checkClass(final Class clz) // Package on purpose
throws BuildException {
if (clz == null) return null;

if(!Modifier.isPublic(clz.getModifiers())) { if(!Modifier.isPublic(clz.getModifiers())) {
final String message = clz + " is not public"; final String message = clz + " is not public";
project.log(message, Project.MSG_ERR); project.log(message, Project.MSG_ERR);
@@ -336,21 +285,53 @@ public class SymbolTable {
throw new BuildException(message); throw new BuildException(message);
} }
try { try {
// Class can have a "no arg" constructor or take a single
// Class can have a "no arg" constructor or take a single
// Project argument. // Project argument.
// don't have to check for public, since // don't have to check for public, since
// getConstructor finds public constructors only. // getConstructor finds public constructors only.
try { try {
clz.getConstructor(new Class[0]); clz.getConstructor(new Class[0]);
return new Factory(){
public Object create(Project p) {
try {
return clz.newInstance();
}
catch(Exception e) {
throw new BuildException(e);
}
}

public Class getOriginalClass() {
return clz;
}
};
} catch (NoSuchMethodException nse) { } catch (NoSuchMethodException nse) {
clz.getConstructor(new Class[] {Project.class});
final Constructor c =
clz.getConstructor(new Class[] {Project.class});
return new Factory(){
public Object create(Project p) {
try {
return c.newInstance(new Object[]{p});
}
catch(Exception e) {
throw new BuildException(e);
}
}

public Class getOriginalClass() {
return clz;
}
};
} }
} catch(NoSuchMethodException e) { } catch(NoSuchMethodException e) {
final String message =
"No valid public constructor in " + clz;
final String message = "No valid public constructor in " + clz;
project.log(message, Project.MSG_ERR); project.log(message, Project.MSG_ERR);
throw new BuildException(message); throw new BuildException(message);
} }
catch (NoClassDefFoundError ncdfe) {
final String msg = "Class cannot be loaded: " + ncdfe.getMessage();
throw new BuildException(msg, ncdfe);
}
} }


/** /**
@@ -359,32 +340,25 @@ public class SymbolTable {
* @param name the name of the element to sea * @param name the name of the element to sea
* @return the Class implementation * @return the Class implementation
*/ */
public Class get(String role, String name) {
Hashtable defTable = (Hashtable)defs.get(role);
if (defTable != null) {
Class clz = (Class)defTable.get(name);
if (clz != null) return clz;
}
if (parentTable != null) {
return parentTable.get(role, name);
}
return null;
}

/**
* Get a Hashtable that is usable for manipulating Tasks,
* @return a Hashtable that delegates to the Symbol table.
*/
public Hashtable getTaskDefinitions() {
return new SymbolHashtable("task");
public Factory get(String role, String name) {
Hashtable defTable = (Hashtable)defs.get(role);
if (defTable != null) {
Factory f = (Factory)defTable.get(name);
if (f != null) return f;
}
if (parentTable != null) {
return parentTable.get(role, name);
}
return null;
} }


/** /**
* Get a Hashtable that is usable for manipulating Datatypes,
* Get a Hashtable that is usable for manipulating elements on Role.
* @param role the role of the elements in the table
* @return a Hashtable that delegates to the Symbol table. * @return a Hashtable that delegates to the Symbol table.
*/ */
public Hashtable getDataTypeDefinitions() {
return new SymbolHashtable("datatype");
Hashtable getDefinitions(String role) { // package scope on purpose
return new SymbolHashtable(role);
} }


/** /**
@@ -392,100 +366,196 @@ public class SymbolTable {
* the search operations to the Symbol table * the search operations to the Symbol table
*/ */
private class SymbolHashtable extends Hashtable { private class SymbolHashtable extends Hashtable {
final String role;
SymbolHashtable(String role) {
this.role = role;
}

public synchronized Object put(Object key, Object value) {
return SymbolTable.this.add(role, (String) key, (Class) value);
}

public synchronized Object get(Object key) {
return SymbolTable.this.get(role, (String)key);
}
final String role;
SymbolHashtable(String role) {
this.role = role;
}

public synchronized Object put(Object key, Object value) {
return SymbolTable.this.add(role, (String) key, (Class) value);
}

public synchronized Object get(Object key) {
Factory f = SymbolTable.this.get(role, (String)key);
return (f == null? null : f.getOriginalClass());
}
}

/**
* Factory for creating ANT objects.
* Class objects are not instanciated directly but through a Factory
* which is able to resolve issues such as proxys and such.
*/
public static interface Factory {
/**
* Creates an object for the Role
* @param the project in which it is created
* @return the instantiated object with a proxy if necessary
*/
public Object create(Project p);

/**
* Creates an object for the Role, adapted if necessary
* for a particular interface.
*/
// public Object adaptFor(Class clz, Project p, Object o);

/**
* The original class of the object without proxy.
*/
public Class getOriginalClass();
} }


/** /**
* The definition of a role * The definition of a role
*/ */
public class Role { public class Role {
private Method interfaceMethod;
private Method adapterVerifier;
/**
* Creates a new Role object
* @param roleClz the class that defines the role
* @param adapterClz the class for the adapter, or null if none
*/
Role(Class roleClz, Class adapterClz) {
interfaceMethod = validInterface(roleClz);
adapterVerifier = validAdapter(adapterClz, interfaceMethod);
}

/**
* Get the method used to set on interface
*/
public Method getInterfaceMethod() {
return interfaceMethod;
}

/**
* Instantiate a new adapter for this role.
*/
public RoleAdapter createAdapter() {
if (adapterVerifier == null) return null;
try {
return (RoleAdapter)
adapterVerifier.getDeclaringClass().newInstance();
}
catch(BuildException be) {
throw be;
}
catch(Exception e) {
throw new BuildException(e);
}
}
/**
* Verify if the class can be adapted to use by the role
* @param role the name of the role to verify
* @param clz the class to verify
*/
public void verifyAdaptability(String role, Class clz) {
if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) {
return;
}
if (adapterVerifier == null) {
String msg = "Class " + clz.getName() +
" incompatible with role: " + role;
throw new BuildException(msg);
}
try {
try {
adapterVerifier.invoke(null,
new Object[]{clz, project});
}
catch (InvocationTargetException ite) {
throw ite.getTargetException();
}
}
catch(BuildException be) { throw be; }
catch(Error err) {throw err; }
catch(Throwable t) {
throw new BuildException(t);
}
}
public boolean isSameAsFor(Class clz, Class pclz) {
return interfaceMethod.getDeclaringClass().equals(clz) &&
((adapterVerifier == null && pclz == null) ||
adapterVerifier.getDeclaringClass().equals(pclz));
}

public boolean isImplementedBy(Class clz) {
return interfaceMethod.getDeclaringClass().isAssignableFrom(clz);
}
private Method interfaceMethod;
private Method adapterVerifier;
private Factory adapterFactory;

/**
* Creates a new Role object
* @param roleClz the class that defines the role
* @param adapterClz the class for the adapter, or null if none
*/
Role(Class roleClz, Class adapterClz) {
interfaceMethod = validInterface(roleClz);
adapterFactory = checkClass(adapterClz);
adapterVerifier = validAdapter(adapterClz, interfaceMethod);
}

/**
* Get the method used to set on interface
*/
public Method getInterfaceMethod() {
return interfaceMethod;
}

/**
* Instantiate a new adapter for this role.
*/
public RoleAdapter createAdapter(Project p) {
if (adapterFactory == null) return null;

try {
return (RoleAdapter) adapterFactory.create(p);
}
catch(BuildException be) {
throw be;
}
catch(Exception e) {
throw new BuildException(e);
}
}

/**
* Verify if the class can be adapted to use by the role
* @param role the name of the role to verify
* @param f the factory for the class to verify
*/
public Factory verifyAdaptability(String role, final Factory f) {
final Class clz = f.getOriginalClass();
if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) {
return f;
}
if (adapterVerifier == null) {
String msg = "Class " + clz.getName() +
" incompatible with role: " + role;
throw new BuildException(msg);
}
try {
try {
adapterVerifier.invoke(null, new Object[]{clz, project});
return new Factory(){
public Object create(Project p) {
RoleAdapter ra = createAdapter(p);
ra.setProxy(f.create(p));
return ra;
}

public Class getOriginalClass() {
return clz;
}
};
}
catch (InvocationTargetException ite) {
throw ite.getTargetException();
}
}
catch(BuildException be) { throw be; }
catch(Error err) {throw err; }
catch(Throwable t) {
throw new BuildException(t);
}
}

public boolean isSameAsFor(Class clz, Class pclz) {
return interfaceMethod.getDeclaringClass().equals(clz) &&
((adapterVerifier == null && pclz == null) ||
adapterVerifier.getDeclaringClass().equals(pclz));
}

public boolean isImplementedBy(Class clz) {
return interfaceMethod.getDeclaringClass().isAssignableFrom(clz);
}

/**
* Verify if the interface is valid.
* @param clz the interface to validate
* @return the method defined by the interface
*/
private Method validInterface(Class clz) {
Method m[] = clz.getDeclaredMethods();
if (m.length == 1
&& java.lang.Void.TYPE.equals(m[0].getReturnType())) {
Class args[] = m[0].getParameterTypes();
if (args.length == 1
&& !java.lang.String.class.equals(args[0])
&& !args[0].isArray()
&& !args[0].isPrimitive()) {
return m[0];
}
else {
throw new BuildException("Invalid role interface method in: "
+ clz.getName());
}
}
else {
throw new BuildException("More than one method on role interface");
}
}

/**
* Verify if the adapter is valid with respect to the interface.
* @param clz the class adapter to validate
* @param mtd the method whose only argument must match
* @return the static method to use for validating adaptees
*/
private Method validAdapter(Class clz, Method mtd) {
if (clz == null) return null;

if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) {
String msg = "Adapter " + clz.getName() +
" is incompatible with role interface " +
mtd.getDeclaringClass().getName();
throw new BuildException(msg);
}
String msg = "Class " + clz.getName() + " is not an adapter: ";
if (!RoleAdapter.class.isAssignableFrom(clz)) {
throw new BuildException(msg + "does not implement RoleAdapter");
}
try {
Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS);
if (!Modifier.isStatic(chk.getModifiers())) {
throw new BuildException(msg + "checkClass() is not static");
}
return chk;
}
catch(NoSuchMethodException nme){
throw new BuildException(msg + "checkClass() not found", nme);
}
}

} }
} }

+ 22
- 14
proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java View File

@@ -1,7 +1,7 @@
/* /*
* The Apache Software License, Version 1.1 * The Apache Software License, Version 1.1
* *
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved. * reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -9,7 +9,7 @@
* are met: * are met:
* *
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer.
* *
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in * notice, this list of conditions and the following disclaimer in
@@ -17,15 +17,15 @@
* distribution. * distribution.
* *
* 3. The end-user documentation included with the redistribution, if * 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)." * Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself, * Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear. * if and wherever such third-party acknowlegements normally appear.
* *
* 4. The names "The Jakarta Project", "Ant", and "Apache Software * 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived * Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* from this software without prior written permission. For written
* permission, please contact apache@apache.org. * permission, please contact apache@apache.org.
* *
* 5. Products derived from this software may not be called "Apache" * 5. Products derived from this software may not be called "Apache"
@@ -55,6 +55,7 @@
package org.apache.tools.ant; package org.apache.tools.ant;


import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;






@@ -68,7 +69,7 @@ import java.lang.reflect.Method;
public class TaskAdapter extends Task implements RoleAdapter { public class TaskAdapter extends Task implements RoleAdapter {


Object proxy; Object proxy;
/** /**
* Checks a class, whether it is suitable to be adapted by TaskAdapter. * Checks a class, whether it is suitable to be adapted by TaskAdapter.
* *
@@ -81,15 +82,15 @@ public class TaskAdapter extends Task implements RoleAdapter {
* Logs other suspicious conditions with Project.MSG_WARN. * Logs other suspicious conditions with Project.MSG_WARN.
*/ */
public static void checkTaskClass(final Class taskClass, final Project project) { public static void checkTaskClass(final Class taskClass, final Project project) {
// This code is for backward compatibility
checkClass(taskClass, project);
// This code is for backward compatibility
checkClass(taskClass, project);
} }


/** /**
* Checks a class, whether it is suitable to be adapted. * Checks a class, whether it is suitable to be adapted.
* *
* Checks conditions only, which are additionally required for a tasks * Checks conditions only, which are additionally required for a tasks
* adapted by TaskAdapter.
* adapted by TaskAdapter.
* *
* Throws a BuildException and logs as Project.MSG_ERR for * Throws a BuildException and logs as Project.MSG_ERR for
* conditions, that will cause the task execution to fail. * conditions, that will cause the task execution to fail.
@@ -114,7 +115,7 @@ public class TaskAdapter extends Task implements RoleAdapter {
throw new BuildException(message); throw new BuildException(message);
} }
} }
/** /**
* Do the execution. * Do the execution.
*/ */
@@ -122,7 +123,7 @@ public class TaskAdapter extends Task implements RoleAdapter {
Method setProjectM = null; Method setProjectM = null;
try { try {
Class c = proxy.getClass(); Class c = proxy.getClass();
setProjectM =
setProjectM =
c.getMethod( "setProject", new Class[] {Project.class}); c.getMethod( "setProject", new Class[] {Project.class});
if(setProjectM != null) { if(setProjectM != null) {
setProjectM.invoke(proxy, new Object[] {project}); setProjectM.invoke(proxy, new Object[] {project});
@@ -131,7 +132,7 @@ public class TaskAdapter extends Task implements RoleAdapter {
// ignore this if the class being used as a task does not have // ignore this if the class being used as a task does not have
// a set project method. // a set project method.
} catch( Exception ex ) { } catch( Exception ex ) {
log("Error setting project in " + proxy.getClass(),
log("Error setting project in " + proxy.getClass(),
Project.MSG_ERR); Project.MSG_ERR);
throw new BuildException( ex ); throw new BuildException( ex );
} }
@@ -146,14 +147,20 @@ public class TaskAdapter extends Task implements RoleAdapter {
throw new BuildException("No public execute() in " + proxy.getClass()); throw new BuildException("No public execute() in " + proxy.getClass());
} }
executeM.invoke(proxy, null); executeM.invoke(proxy, null);
return;
return;
} catch( InvocationTargetException ite ) {
Throwable t = ite.getTargetException();
if (t instanceof BuildException) {
throw (BuildException) t;
}
throw new BuildException(t);
} catch( Exception ex ) { } catch( Exception ex ) {
log("Error in " + proxy.getClass(), Project.MSG_ERR); log("Error in " + proxy.getClass(), Project.MSG_ERR);
throw new BuildException( ex ); throw new BuildException( ex );
} }


} }
/** /**
* Set the target object class * Set the target object class
*/ */
@@ -165,4 +172,5 @@ public class TaskAdapter extends Task implements RoleAdapter {
return this.proxy ; return this.proxy ;
} }


public void setId(String id) {}
} }

+ 1
- 23
proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Ant.java View File

@@ -138,10 +138,8 @@ public class Ant extends Task {
} }


public void init() { public void init() {
newProject = new Project(project);
newProject = project.createSubProject();
newProject.setJavaVersionProperty(); newProject.setJavaVersionProperty();
// newProject.addTaskDefinition("property",
// (Class)project.getTaskDefinitions().get("property"));
} }


private void reinit() { private void reinit() {
@@ -185,26 +183,6 @@ public class Ant extends Task {
} }
} }


// Hashtable taskdefs = project.getTaskDefinitions();
// Enumeration et = taskdefs.keys();
// while (et.hasMoreElements()) {
// String taskName = (String) et.nextElement();
// if (taskName.equals("property")) {
// // we have already added this taskdef in #init
// continue;
// }
// Class taskClass = (Class) taskdefs.get(taskName);
// newProject.addTaskDefinition(taskName, taskClass);
// }

// Hashtable typedefs = project.getDataTypeDefinitions();
// Enumeration e = typedefs.keys();
// while (e.hasMoreElements()) {
// String typeName = (String) e.nextElement();
// Class typeClass = (Class) typedefs.get(typeName);
// newProject.addDataTypeDefinition(typeName, typeClass);
// }

// set user-defined or all properties from calling project // set user-defined or all properties from calling project
Hashtable prop1; Hashtable prop1;
if (inheritAll) { if (inheritAll) {


+ 9
- 5
proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antjar.java View File

@@ -104,7 +104,8 @@ public class Antjar extends Jar {
public void setAntxml(File descriptor) { public void setAntxml(File descriptor) {
libraryDescriptor = descriptor; libraryDescriptor = descriptor;
if (!libraryDescriptor.exists()) { if (!libraryDescriptor.exists()) {
throw new BuildException("Deployment descriptor: " + libraryDescriptor + " does not exist.");
throw new BuildException("Deployment descriptor: " +
libraryDescriptor + " does not exist.");
} }


// Create a ZipFileSet for this file, and pass it up. // Create a ZipFileSet for this file, and pass it up.
@@ -127,7 +128,8 @@ public class Antjar extends Jar {
throws IOException, BuildException { throws IOException, BuildException {
// If no antxml file is specified, it's an error. // If no antxml file is specified, it's an error.
if (libraryDescriptor == null) { if (libraryDescriptor == null) {
throw new BuildException("antxml attribute is required", location);
throw new BuildException("antxml attribute is required",
location);
} }


super.initZipOutputStream(zOut); super.initZipOutputStream(zOut);
@@ -149,10 +151,12 @@ public class Antjar extends Jar {
// meaning the same file is specified by the "antxml" attribute and in // meaning the same file is specified by the "antxml" attribute and in
// a <fileset> element. // a <fileset> element.
if (vPath.equalsIgnoreCase(Antlib.ANT_DESCRIPTOR)) { if (vPath.equalsIgnoreCase(Antlib.ANT_DESCRIPTOR)) {
if (libraryDescriptor == null || !libraryDescriptor.equals(file) || descriptorAdded) {
if (libraryDescriptor == null ||
!libraryDescriptor.equals(file) || descriptorAdded) {
log("Warning: selected " + archiveType + " files include a " + log("Warning: selected " + archiveType + " files include a " +
Antlib.ANT_DESCRIPTOR + " which will be ignored " +
"(please use antxml attribute to " + archiveType + " task)", Project.MSG_WARN);
Antlib.ANT_DESCRIPTOR + " which will be ignored " +
"(please use antxml attribute to " + archiveType +
" task)", Project.MSG_WARN);
} }
else { else {
super.zipFile(file, zOut, vPath); super.zipFile(file, zOut, vPath);


+ 426
- 256
proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antlib.java View File

@@ -55,12 +55,14 @@ package org.apache.tools.ant.taskdefs;


import org.apache.tools.ant.*; import org.apache.tools.ant.*;
import org.apache.tools.ant.types.*; import org.apache.tools.ant.types.*;
import org.apache.tools.ant.taskdefs.*;
import org.xml.sax.*; import org.xml.sax.*;
import javax.xml.parsers.*; import javax.xml.parsers.*;


import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
import java.io.*; import java.io.*;
import java.net.*;


/** /**
* Make available the tasks and types from an Ant library. <pre> * Make available the tasks and types from an Ant library. <pre>
@@ -76,16 +78,18 @@ import java.io.*;
* @since ant1.5 * @since ant1.5
*/ */
public class Antlib extends Task { public class Antlib extends Task {

/**
* Location of descriptor in library
*/
public static final String ANT_DESCRIPTOR = "META-INF/antlib.xml";

/** /**
* The named classloader to use. * The named classloader to use.
* Defaults to the default classLoader. * Defaults to the default classLoader.
*/ */
private String loaderId = ""; private String loaderId = "";


/**
* library attribute
*/
private String library = null;
/** /**
* file attribute * file attribute
*/ */
@@ -95,62 +99,200 @@ public class Antlib extends Task {
*/ */
private boolean override = false; private boolean override = false;
/** /**
* attribute to control classloader use
* attribute to control failure when loading
*/ */
private boolean useCurrentClassloader = false;
private FailureAction onerror = new FailureAction();

/** /**
* classpath to build up * classpath to build up
*/ */
private Path classpath = null; private Path classpath = null;


/**
* the manufacture set of classes to load
*/
private Path loaderPath = null;

/** /**
* our little xml parse * our little xml parse
*/ */
private SAXParserFactory saxFactory; private SAXParserFactory saxFactory;
/** /**
* table of aliases * table of aliases
*/ */
private Vector aliases = new Vector(); private Vector aliases = new Vector();


/** /**
* Location of descriptor in library
* Some internal constants.
*/ */
public static String ANT_DESCRIPTOR = "META-INF/antlib.xml";
private static final int FAIL = 0, REPORT = 1, IGNORE = 2;


/** /**
* Prefix name for DTD of descriptor
*/
public static String ANTLIB_DTD_URL =
"http://jakarta.apache.org/ant/";
/**
* prefix of the antlib
*/
public static String ANTLIB_DTD_PREFIX = "Antlib-V";
/**
* version counter
* Posible actions when classes are not found
*/ */
public static String ANTLIB_DTD_VERSION = "1_0";
/**
* dtd file extension
*/
public static String ANTLIB_DTD_EXT = ".dtd";
public static class FailureAction extends EnumeratedAttribute {
public String[] getValues() {
return new String[]{"fail", "report", "ignore"};
}
}


private static class DescriptorEnumeration implements Enumeration {

/**
* The name of the resource being searched for.
*/
private String resourceName;

/**
* The index of the next file to search.
*/
private int index;

/**
* The list of files to search
*/
private File files[];

/**
* The URL of the next resource to return in the enumeration. If this
* field is <code>null</code> then the enumeration has been completed,
* i.e., there are no more elements to return.
*/
private URL nextDescriptor;

/**
* Construct a new enumeration of resources of the given name found
* within this class loader's classpath.
*
* @param name the name of the resource to search for.
*/
DescriptorEnumeration(String fileNames[], String name) {
this.resourceName = name;
this.index = 0;
this.files = new File[fileNames.length];
for (int i = 0; i < files.length; i++) {
files[i] = new File(fileNames[i]);
}
findNextDescriptor();
}

/**
* Indicates whether there are more elements in the enumeration to
* return.
*
* @return <code>true</code> if there are more elements in the
* enumeration; <code>false</code> otherwise.
*/
public boolean hasMoreElements() {
return (this.nextDescriptor != null);
}

/**
* Returns the next resource in the enumeration.
*
* @return the next resource in the enumeration.
*/
public Object nextElement() {
URL ret = this.nextDescriptor;
findNextDescriptor();
return ret;
}

/**
* Locates the next descriptor of the correct name in the files and
* sets <code>nextDescriptor</code> to the URL of that resource. If no
* more resources can be found, <code>nextDescriptor</code> is set to
* <code>null</code>.
*/
private void findNextDescriptor() {
URL url = null;
while (index < files.length && url == null) {
try {
url = getDescriptorURL(files[index], this.resourceName);
index++;
}
catch (BuildException e) {
// ignore path elements which are not valid relative to the
// project
}
}
this.nextDescriptor = url;
}

/**
* Get an URL to a given resource in the given file which may
* either be a directory or a zip file.
*
* @param file the file (directory or jar) in which to search for
* the resource. Must not be <code>null</code>.
* @param resourceName the name of the resource for which a URL
* is required. Must not be <code>null</code>.
*
* @return a URL to the required resource or <code>null</code> if the
* resource cannot be found in the given file object
* @todo This code is extracted from AntClassLoader.getResourceURL
* I hate when that happens but the code there is too tied to
* the ClassLoader internals. Maybe we can find a nice place
* to put it where both can use it.
*/
private URL getDescriptorURL(File file, String resourceName) {
try {
if (!file.exists()) {
return null;
}

if (file.isDirectory()) {
File resource = new File(file, resourceName);

if (resource.exists()) {
try {
return new URL("file:"+resource.toString());
} catch (MalformedURLException ex) {
return null;
}
}
}
else {
ZipFile zipFile = new ZipFile(file);
try {
ZipEntry entry = zipFile.getEntry(resourceName);
if (entry != null) {
try {
return new URL("jar:file:"+file.toString()+"!/"+entry);
} catch (MalformedURLException ex) {
return null;
}
}
}
finally {
zipFile.close();
}
}
}
catch (Exception e) {
e.printStackTrace();
}

return null;
}

}


/** /**
* constructor creates a validating sax parser * constructor creates a validating sax parser
*/ */
public Antlib() { public Antlib() {
super(); super();
// Default error action
onerror.setValue("report");
saxFactory = SAXParserFactory.newInstance(); saxFactory = SAXParserFactory.newInstance();
saxFactory.setValidating(true);
saxFactory.setValidating(false);
} }




/** /**
* constructor binds to a project as well as setting up internal state
* constructor binds to a project and sets ignore mode on errors
* *
* @param p Description of Parameter * @param p Description of Parameter
*/ */
@@ -161,12 +303,12 @@ public class Antlib extends Task {




/** /**
* Set name of library to load. The library is located in $ANT_HOME/lib.
* Set name of library to load. The library is located in $ANT_HOME/antlib.
* *
* @param lib the name of library relative to $ANT_HOME/lib.
* @param lib the name of library relative to $ANT_HOME/antlib.
*/ */
public void setLibrary(String lib) { public void setLibrary(String lib) {
this.library = lib;
setFile(libraryFile("antlib", lib));
} }




@@ -180,13 +322,13 @@ public class Antlib extends Task {
} }


/** /**
* Set the ClassLoader to use for this library.
* Set the ID of the ClassLoader to use for this library.
* *
* @param id the id for the ClassLoader to use,
* if other than the default.
* @param id the id for the ClassLoader to use,
* <code>null</code> means use ANT's core classloader.
*/ */
public void setLoaderid(String id) { public void setLoaderid(String id) {
this.loaderId = id;
this.loaderId = id;
} }


/** /**
@@ -200,15 +342,26 @@ public class Antlib extends Task {




/** /**
* Set whether to use a new classloader or not.
* Default is <code>false</code>.
* Get what to do if a definition cannot be loaded
* This method is mostly used by the core when loading core tasks.
*
* @return what to do if a definition cannot be loaded
*/
final protected FailureAction getOnerror() {
return this.onerror;
}


/**
* Set whether to fail if a definition cannot be loaded
* Default is <code>true</code>.
* This property is mostly used by the core when loading core tasks. * This property is mostly used by the core when loading core tasks.
* *
* @param useCurrentClassloader if true the current classloader will
* be used to load the definitions.
* @param failedonerror if true loading will stop if classes
* cannot be instantiated
*/ */
public void setUseCurrentClassloader(boolean useCurrentClassloader) {
this.useCurrentClassloader = useCurrentClassloader;
public void setOnerror(FailureAction onerror) {
this.onerror = onerror;
} }




@@ -262,78 +415,97 @@ public class Antlib extends Task {
} }




/**
* Obtain library file from ANT_HOME directory.
*
* @param lib the library name.
* @return the File instance of the library
*/
private File libraryFile(String homeSubDir, String lib) {
// For the time being libraries live in $ANT_HOME/antlib.
// The idea being that not to load all the jars there anymore
String home = project.getProperty("ant.home");

if (home == null) {
throw new BuildException("ANT_HOME not set as required.");
}

return new File(new File(home, homeSubDir), lib);
}

/** /**
* actually do the work of loading the library * actually do the work of loading the library
* *
* @exception BuildException Description of Exception * @exception BuildException Description of Exception
* @todo maybe have failonerror support for missing file?
*/ */
public void execute() public void execute()
throws BuildException { throws BuildException {
File realFile = file;
if (library != null) {
if (file != null) {
String msg = "You cannot specify both file and library.";
throw new BuildException(msg, location);
}
// For the time being libraries live in $ANT_HOME/antlib.
// The idea being that we would not load all the jars there anymore
String home = project.getProperty("ant.home");

if (home == null) {
throw new BuildException("ANT_HOME not set as required.");
}

realFile = new File(new File(home, "antlib"), library);
}
else if (file == null) {
String msg = "Must specify either library or file attribute.";
if (file == null && classpath == null) {
String msg =
"Must specify either library or file attribute or classpath.";
throw new BuildException(msg, location); throw new BuildException(msg, location);
} }
if (!realFile.exists()) {
String msg = "Cannot find library: " + realFile;
if (file != null && !file.exists()) {
String msg = "Cannot find library: " + file;
throw new BuildException(msg, location); throw new BuildException(msg, location);
} }


//open the descriptor
InputStream is = getDescriptor(realFile);

if (is == null) {
String msg = "Missing descriptor on library: " + realFile;
throw new BuildException(msg, location);
}
loadDefinitions();
}


ClassLoader classloader=null;
if (useCurrentClassloader && classpath != null) {
log("ignoring the useCurrentClassloader option as a classpath is defined",
Project.MSG_WARN);
useCurrentClassloader=false;
}
if (!useCurrentClassloader) {
classloader = makeClassLoader(realFile);
}


//parse it and evaluate it.
evaluateDescriptor(classloader, processAliases(), is);
/**
* Load definitions in library and classpath
*
* @exception BuildException failure to access the resource
*/
public boolean loadDefinitions() throws BuildException {
return loadDefinitions(ANT_DESCRIPTOR);
} }



/** /**
* Load definitions directly from an external XML file.
* Load definitions from resource name in library and classpath
* *
* @param xmlfile XML file in the Antlib format.
* @exception BuildException failure to open the file
* @param res the name of the resources to load
* @exception BuildException failure to access the resource
*/ */
public void loadDefinitions(File xmlfile)
final protected boolean loadDefinitions(String res)
throws BuildException { throws BuildException {
Path path = makeLoaderClasspath();
ClassLoader cl = makeClassLoader(path);
boolean found = false;
try { try {
InputStream is = new FileInputStream(xmlfile);
loadDefinitions(is);
for (Enumeration e = getDescriptors(path, res); e.hasMoreElements(); ) {
URL resURL = (URL)e.nextElement();
InputStream is = resURL.openStream();
loadDefinitions(cl, is);
found = true;
}
if (!found && onerror.getIndex() != IGNORE) {
String sPath = path.toString();
if ("".equals(sPath.trim())) {
sPath = System.getProperty("java.classpath");
}
String msg = "Cannot find any " + res +
" antlib descriptors in: " + sPath;
switch (onerror.getIndex()) {
case FAIL:
throw new BuildException(msg);
case REPORT:
log(msg, project.MSG_WARN);
}
}
} }
catch (IOException io) { catch (IOException io) {
throw new BuildException("Cannot read file: " + file, io);
String msg = "Cannot load definitions from: " + res;
switch (onerror.getIndex()) {
case FAIL:
throw new BuildException(msg, io);
case REPORT:
log(io.getMessage(), project.MSG_WARN);
}
} }
return found;
} }




@@ -343,46 +515,29 @@ public class Antlib extends Task {
* @param is InputStream for the Antlib descriptor. * @param is InputStream for the Antlib descriptor.
* @exception BuildException trouble * @exception BuildException trouble
*/ */
public void loadDefinitions(InputStream is)
private void loadDefinitions(ClassLoader cl, InputStream is)
throws BuildException { throws BuildException {
evaluateDescriptor(null, processAliases(), is);
evaluateDescriptor(cl, processAliases(), is);
} }




/** /**
* get a descriptor from the library file
* get an Enumeration of URLs for all resouces corresponding to the
* descriptor name.
* *
* @param file jarfile to open
* @return input stream to the Descriptor
* @param res the name of the resource to collect
* @return input stream to the Descriptor or null if none existent
* @exception BuildException io trouble, or it isnt a zipfile * @exception BuildException io trouble, or it isnt a zipfile
*/ */
private InputStream getDescriptor(File file)
throws BuildException {
try {
final ZipFile zipfile = new ZipFile(file);
ZipEntry entry = zipfile.getEntry(ANT_DESCRIPTOR);

if (entry == null) {
return null;
}

// Guarantee that when Entry is closed so does the zipfile instance.
return
new FilterInputStream(zipfile.getInputStream(entry)) {
public void close()
throws IOException {
super.close();
zipfile.close();
}
};
}
catch (ZipException ze) {
throw new BuildException("Not a library file.", ze, location);
}
catch (IOException ioe) {
throw new BuildException("Cannot read library content.",
ioe, location);
private Enumeration getDescriptors(Path path, final String res)
throws BuildException, IOException {
if (loaderId == null) {
// Path cannot be added to the CoreLoader so simply
// ask for all instances of the resource descriptors
return project.getCoreLoader().getResources(res);
} }

return new DescriptorEnumeration(path.list(), res);
} }




@@ -410,18 +565,34 @@ public class Antlib extends Task {
* @return classloader using te * @return classloader using te
* @exception BuildException trouble creating the classloader * @exception BuildException trouble creating the classloader
*/ */
protected ClassLoader makeClassLoader(File file)
protected ClassLoader makeClassLoader(Path clspath)
throws BuildException { throws BuildException {
if (loaderId == null) {
log("Loading definitions from CORE, <classpath> ignored",
project.MSG_VERBOSE);
return project.getCoreLoader();
}

log("Using ClassLoader '" + loaderId + "' to load path: " + clspath,
project.MSG_VERBOSE);
return project.addToLoader(loaderId, clspath);
}


/**
* Constructs the Path to add to the ClassLoader
*/
private Path makeLoaderClasspath()
{
Path clspath = new Path(project); Path clspath = new Path(project);
clspath.setLocation(file);
if (file != null) clspath.setLocation(file);
//append any build supplied classpath //append any build supplied classpath
if (classpath != null) { if (classpath != null) {
clspath.append(classpath); clspath.append(classpath);
} }
return project.getSymbols().addToLoader(loaderId, clspath);
return clspath;
} }



/** /**
* parse the antlib descriptor * parse the antlib descriptor
* *
@@ -431,8 +602,8 @@ public class Antlib extends Task {
* @exception BuildException trouble * @exception BuildException trouble
*/ */
protected void evaluateDescriptor(ClassLoader cl, protected void evaluateDescriptor(ClassLoader cl,
Properties als, InputStream is)
throws BuildException {
Properties als, InputStream is)
throws BuildException {
try { try {
SAXParser saxParser = saxFactory.newSAXParser(); SAXParser saxParser = saxFactory.newSAXParser();
Parser parser = saxParser.getParser(); Parser parser = saxParser.getParser();
@@ -440,7 +611,7 @@ public class Antlib extends Task {
InputSource inputSource = new InputSource(is); InputSource inputSource = new InputSource(is);
//inputSource.setSystemId(uri); //URI is nasty for jar entries //inputSource.setSystemId(uri); //URI is nasty for jar entries
project.log("parsing descriptor for library: " + file, project.log("parsing descriptor for library: " + file,
Project.MSG_VERBOSE);
Project.MSG_VERBOSE);
saxParser.parse(inputSource, new AntLibraryHandler(cl, als)); saxParser.parse(inputSource, new AntLibraryHandler(cl, als));
} }
catch (ParserConfigurationException exc) { catch (ParserConfigurationException exc) {
@@ -485,8 +656,8 @@ public class Antlib extends Task {




/** /**
* Parses the document describing the content of the
* library. An inner class for access to Project.log
* Parses the document describing the content of the
* library. An inner class for access to Project.log
*/ */
private class AntLibraryHandler extends HandlerBase { private class AntLibraryHandler extends HandlerBase {


@@ -503,13 +674,11 @@ public class Antlib extends Task {
*/ */
private Locator locator = null; private Locator locator = null;


private int level = 0;

private SymbolTable symbols = null;
private int level = 0;


private String name = null;
private String className = null;
private String adapter = null;
private String name = null;
private String className = null;
private String adapter = null;


/** /**
* Constructor for the AntLibraryHandler object * Constructor for the AntLibraryHandler object
@@ -520,7 +689,6 @@ public class Antlib extends Task {
AntLibraryHandler(ClassLoader classloader, Properties als) { AntLibraryHandler(ClassLoader classloader, Properties als) {
this.classloader = classloader; this.classloader = classloader;
this.aliasMap = als; this.aliasMap = als;
this.symbols = project.getSymbols();
} }


/** /**
@@ -533,35 +701,35 @@ public class Antlib extends Task {
this.locator = locator; this.locator = locator;
} }


private void parseAttributes(String tag, AttributeList attrs)
throws SAXParseException {
name = null;
className = null;
adapter = null;
for (int i = 0, last = attrs.getLength(); i < last; i++) {
String key = attrs.getName(i);
String value = attrs.getValue(i);
if (key.equals("name")) {
name = value;
}
else if (key.equals("class")) {
className = value;
}
else if ("role".equals(tag) && key.equals("adapter")) {
adapter = value;
}
else {
throw new SAXParseException("Unexpected attribute \""
+ key + "\"", locator);
}
}
if (name == null || className == null) {
String msg = "Underspecified " + tag + " declaration.";
throw new SAXParseException(msg, locator);
}
}
private void parseAttributes(String tag, AttributeList attrs)
throws SAXParseException {
name = null;
className = null;
adapter = null;
for (int i = 0, last = attrs.getLength(); i < last; i++) {
String key = attrs.getName(i);
String value = attrs.getValue(i);
if (key.equals("name")) {
name = value;
}
else if (key.equals("class")) {
className = value;
}
else if ("role".equals(tag) && key.equals("adapter")) {
adapter = value;
}
else {
throw new SAXParseException("Unexpected attribute \""
+ key + "\"", locator);
}
}
if (name == null || className == null) {
String msg = "Underspecified " + tag + " declaration.";
throw new SAXParseException(msg, locator);
}
}


/** /**
* SAX callback handler * SAX callback handler
@@ -572,103 +740,105 @@ public class Antlib extends Task {
*/ */
public void startElement(String tag, AttributeList attrs) public void startElement(String tag, AttributeList attrs)
throws SAXParseException { throws SAXParseException {
level ++;
level ++;
if ("antlib".equals(tag)) { if ("antlib".equals(tag)) {
if (level > 1) {
throw new SAXParseException("Unexpected element: " + tag,
locator);
}
if (level > 1) {
throw new SAXParseException("Unexpected element: " + tag,
locator);
}
// No attributes to worry about // No attributes to worry about
return; return;
} }
if (level == 1) {
throw new SAXParseException("Missing antlib root element",
locator);
}

// Must have the two attributes declared
parseAttributes(tag, attrs);

try {
if ("role".equals(tag)) {
if (isRoleInUse(name)) {
String msg = "Cannot override role: " + name;
log(msg, Project.MSG_WARN);
return;
}
// Defining a new role
symbols.addRole(name, loadClass(className),
(adapter == null?
null : loadClass(adapter)));
return;
}

// Defining a new element kind
//check for name alias
String alias = aliasMap.getProperty(name);
if (alias != null) {
name = alias;
}
//catch an attempted override of an existing name
if (!override && isInUse(tag, name)) {
String msg = "Cannot override " + tag + ": " + name;
log(msg, Project.MSG_WARN);
return;
}
symbols.add(tag, name, loadClass(className));
}
catch(BuildException be) {
throw new SAXParseException(be.getMessage(), locator, be);
}
}

public void endElement(String tag) {
level--;
}

private Class loadClass(String className)
throws SAXParseException {
try {
//load the named class
Class cls;
if(classloader==null) {
cls=Class.forName(className);
}
else {
cls=classloader.loadClass(className);
}
return cls;
}
catch (ClassNotFoundException cnfe) {
String msg = "Class " + className +
" cannot be found";
throw new SAXParseException(msg, locator, cnfe);
}
catch (NoClassDefFoundError ncdfe) {
String msg = "Class " + className +
" cannot be found";
throw new SAXParseException(msg, locator);
}
}
if (level == 1) {
throw new SAXParseException("Missing antlib root element",
locator);
}


/**
* test for a name being in use already on this role
*
* @param name the name to test
* @return true if it is a task or a datatype
*/
private boolean isInUse(String role, String name) {
return (symbols.get(role, name) != null);
// Must have the two attributes declared
parseAttributes(tag, attrs);

try {
if ("role".equals(tag)) {
if (project.isRoleDefined(name)) {
String msg = "Cannot override role: " + name;
log(msg, Project.MSG_WARN);
return;
}
// Defining a new role
Class clz = loadClass(className);
if (clz != null) {
project.addRoleDefinition(name, clz,
(adapter == null? null :
loadClass(adapter)));
}
return;
}

// Defining a new element kind
//check for name alias
String alias = aliasMap.getProperty(name);
if (alias != null) {
name = alias;
}
//catch an attempted override of an existing name
if (!override && project.isDefinedOnRole(tag, name)) {
String msg = "Cannot override " + tag + ": " + name;
log(msg, Project.MSG_WARN);
return;
}
Class clz = loadClass(className);
if (clz != null)
project.addDefinitionOnRole(tag, name, clz);
}
catch(BuildException be) {
switch (onerror.getIndex()) {
case FAIL:
throw new SAXParseException(be.getMessage(), locator, be);
case REPORT:
project.log(be.getMessage(), project.MSG_WARN);
break;
default:
project.log(be.getMessage(), project.MSG_DEBUG);
}
}
} }


/**
* test for a role name being in use already
*
* @param name the name to test
* @return true if it is a task or a datatype
*/
private boolean isRoleInUse(String name) {
return (symbols.getRole(name) != null);
public void endElement(String tag) {
level--;
}

private Class loadClass(String className)
throws SAXParseException {
String msg = null;
try {
//load the named class
Class cls;
if(classloader==null) {
cls=Class.forName(className);
}
else {
cls=classloader.loadClass(className);
}
return cls;
}
catch (ClassNotFoundException cnfe) {
msg = "Class " + className + " cannot be found";
if (onerror.getIndex() == FAIL)
throw new SAXParseException(msg, locator, cnfe);
}
catch (NoClassDefFoundError ncdfe) {
msg = "Class " + className + " cannot be loaded";
if (onerror.getIndex() == FAIL)
throw new SAXParseException(msg, locator);
}

if (onerror.getIndex() == REPORT) {
project.log(msg, project.MSG_WARN);
}
else {
project.log(msg, project.MSG_DEBUG);
}
return null;
} }


//end inner class AntLibraryHandler //end inner class AntLibraryHandler
@@ -712,7 +882,7 @@ public class Antlib extends Task {
} }
//end inner class alias //end inner class alias
} }
//end class Antlib //end class Antlib
} }




+ 21
- 3
proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java View File

@@ -66,6 +66,7 @@ import org.apache.tools.ant.*;
public class DataTypeAdapterTask extends Task implements RoleAdapter { public class DataTypeAdapterTask extends Task implements RoleAdapter {


Object proxy; Object proxy;
String id = null;
/** /**
* Checks a class, whether it is suitable to be adapted. * Checks a class, whether it is suitable to be adapted.
@@ -83,14 +84,27 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter {
* Do the execution. * Do the execution.
*/ */
public void execute() throws BuildException { public void execute() throws BuildException {
if (id != null) {
// Need to re-register this reference
// The container has register the Adapter instead
project.addReference(id, proxy);
}
}

/**
* Propagate configuration of Project
*/
public void setProject(Project p) {
super.setProject(p);

// Check to see if the DataType has a setProject method to set // Check to see if the DataType has a setProject method to set
if (proxy instanceof ProjectComponent) { if (proxy instanceof ProjectComponent) {
((ProjectComponent)proxy).setProject(project);
((ProjectComponent)proxy).setProject(p);
return; return;
} }


// This may not be needed // This may not be needed
// We are trying to set project even it is was not declared
// We are trying to set project even if is was not declared
// just like TaskAdapter does for beans, this is not done // just like TaskAdapter does for beans, this is not done
// by the original code // by the original code
Method setProjectM = null; Method setProjectM = null;
@@ -99,7 +113,7 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter {
setProjectM = setProjectM =
c.getMethod( "setProject", new Class[] {Project.class}); c.getMethod( "setProject", new Class[] {Project.class});
if(setProjectM != null) { if(setProjectM != null) {
setProjectM.invoke(proxy, new Object[] {project});
setProjectM.invoke(proxy, new Object[] {p});
} }
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
// ignore this if the class being used as a task does not have // ignore this if the class being used as a task does not have
@@ -122,4 +136,8 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter {
return this.proxy ; return this.proxy ;
} }


public void setId(String id) {
log("Setting adapter id to: " + id, Project.MSG_DEBUG);
this.id = id;
}
} }

Loading…
Cancel
Save