peterreilly 2003/06/26 01:54:29
Modified: docs/manual/CoreTasks taskdef.html typedef.html
src/main/org/apache/tools/ant ComponentHelper.java
Project.java ProjectHelper.java
RuntimeConfigurable.java TaskAdapter.java
UnknownElement.java
src/main/org/apache/tools/ant/helper ProjectHelperImpl.java
src/main/org/apache/tools/ant/taskdefs Ant.java Definer.java
Taskdef.java
src/testcases/org/apache/tools/ant ProjectTest.java
Added: src/etc/testcases/taskdefs typeadapter.xml
src/main/org/apache/tools/ant AntTypeDefinition.java
TypeAdapter.java
src/testcases/org/apache/tools/ant/taskdefs
TypeAdapterTest.java
Log:
Second patch from antlib update as described in
http://issues.apache.org/bugzilla/show_bug.cgi?id=19897
This patch
* unifies the type and task definitions into one table
* types and tasks are represented by a AntTypeDefinition object
* taskadapter has been generalized to a typeadapter
* <typedef/> has a number of new attributes:
- adapter
- adaptto
- onerror
* <taskdef/> html page updated to refer to <typedef/> page
PR: 19897
Submitted by: Peter Reilly
Revision Changes Path
1.9 +7 -71 ant/docs/manual/CoreTasks/taskdef.html
Index: taskdef.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/CoreTasks/taskdef.html,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- taskdef.html 22 Jun 2002 23:38:27 -0000 1.8
+++ taskdef.html 26 Jun 2003 08:54:27 -0000 1.9
@@ -9,82 +9,18 @@
<h2><a name="taskdef">Taskdef</a></h2>
<h3>Description</h3>
-<p>Adds a task definition to the current project, such that this new task
can be
-used in the current project. Two attributes are needed, the name that
identifies
-this task uniquely, and the full name of the class (including the packages)
that
-implements this task.</p>
-<p>You can also define a group of tasks at once using the file or
-resource attributes. These attributes point to files in the format of
-Java property files. Each line defines a single task in the
-format:</p>
-<pre>
-taskname=fully.qualified.java.classname
-</pre>
-<p>Taskdef should be used to add your own tasks to the system. See also
"<a
-href="../develop.html#writingowntask">Writing your own task</a>".</p>
-<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
- <tr>
- <td valign="top"><b>Attribute</b></td>
- <td valign="top"><b>Description</b></td>
- <td align="center" valign="top"><b>Required</b></td>
- </tr>
- <tr>
- <td valign="top">name</td>
- <td valign="top">the name of the task</td>
- <td valign="top" align="center">Yes, unless file or resource have
- been specified.</td>
- </tr>
- <tr>
- <td valign="top">classname</td>
- <td valign="top">the full class name implementing the task</td>
- <td valign="top" align="center">Yes, unless file or resource have
- been specified.</td>
- </tr>
- <tr>
- <td valign="top">file</td>
- <td valign="top">Name of the property file to load
- taskname/classname pairs from.</td>
- <td valign="top" align="center">No</td>
- </tr>
- <tr>
- <td valign="top">resource</td>
- <td valign="top">Name of the property resource to load
- taskname/classname pairs from.</td>
- <td valign="top" align="center">No</td>
- </tr>
- <tr>
- <td valign="top">classpath</td> <td valign="top">the classpath to
- use when looking up <code>classname</code> or
- <code>resource</code>.</td>
- <td align="center" valign="top">No</td>
- </tr>
- <tr>
- <td valign="top">classpathref</td>
- <td valign="top">Reference to a classpath to
- use when looking up <code>classname</code> or
- <code>resource</code>.</td>
- <td align="center" valign="top">No</td>
- </tr>
- <tr>
- <td valign="top">loaderRef</td> <td valign="top">the name of the loader
that is
- used to load the class, constructed from the specified classpath. Use
this to
- allow multiple tasks/types to be loaded with the same loader, so they
can call
- each other. ( introduced in ant1.5 )</td>
- <td align="center" valign="top">No</td>
- </tr>
-</table>
-<h3>Parameters specified as nested elements</h3>
-<h4>classpath</h4>
-<p><code>Taskdef</code>'s <i>classpath</i> attribute is a <a
-href="../using.html#path">PATH like structure</a> and can also be set via a
nested
-<i>classpath</i> element.</p>
+ <p>Adds a task definition to the current project, such that this new task
can be
+ used in the current project.</p>
+ <p>This task is a form of <a href="typedef.html">Typedef</a> with the
+ attributes "adapter" and "adaptto" set to the values
+ "org.apache.tools.ant.TaskAdapter" and "org.apache.tools.ant.Task"
+ respectively.
<h3>Examples</h3>
<pre> <taskdef name="myjavadoc"
classname="com.mydomain.JavadocTask"/></pre>
<p>makes a task called <code>myjavadoc</code> available to Ant. The class
<code>com.mydomain.JavadocTask</code>
implements the task.</p>
<hr>
-<p align="center">Copyright © 2000-2002 Apache Software Foundation. All
rights
+<p align="center">Copyright © 2000-2003 Apache Software Foundation. All
rights
Reserved.</p>
</body>
1.7 +43 -10 ant/docs/manual/CoreTasks/typedef.html
Index: typedef.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/CoreTasks/typedef.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- typedef.html 1 Jun 2002 12:26:33 -0000 1.6
+++ typedef.html 26 Jun 2003 08:54:27 -0000 1.7
@@ -21,7 +21,7 @@
<pre>
typename=fully.qualified.java.classname
</pre>
-<p>Typedef should be used to add your own types to the system. Data
+<p>Typedef should be used to add your own tasks and types to the system. Data
types are things like <a href="../using.html#path">paths</a> or <a
href="../CoreTypes/fileset.html">filesets</a> that can be defined at
the project level and referenced via their ID attribute.</p>
@@ -36,25 +36,23 @@
<tr>
<td valign="top">name</td>
<td valign="top">the name of the data type</td>
- <td valign="top" align="center">Yes, unless file or resource have
- been specified.</td>
+ <td valign="top" align="center">Yes, unless the file or resource type
+ attributes have been specified.</td>
</tr>
<tr>
<td valign="top">classname</td>
<td valign="top">the full class name implementing the data type</td>
- <td valign="top" align="center">Yes, unless file or resource have
- been specified.</td>
+ <td valign="top" align="center">Yes, unless file or resource
+ have been specified.</td>
</tr>
<tr>
<td valign="top">file</td>
- <td valign="top">Name of the property file to load
- typename/classname pairs from.</td>
+ <td valign="top">Name of the file to load definitions from.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">resource</td>
- <td valign="top">Name of the property resource to load
- typename/classname pairs from.</td>
+ <td valign="top">Name of the resouce to load definitions from.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
@@ -69,6 +67,40 @@
each other. ( introduced in ant1.5 )</td>
<td align="center" valign="top">No</td>
</tr>
+ <tr>
+ <td valign="top">onerror</td>
+ <td valign="top">The action to take if there was a failure in defining
the
+ type. The values are <i>fail</i> - cause a build exception, <i>warn</i>
+ output a warning, but continue, <i>ignore</i>, do nothing. The default
+ is <i>fail</i>.
+ (introduced in ant1.6)
+ </td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
+ <td valign="top">adapter</td>
+ <td valign="top">A class that is used to adapt the defined class to
+ another interface/class. The adapter class must implement the interface
+ "org.apache.tools.ant.TypeAdapter". The adapter class will be used
+ to wrap the defined class unless the defined class implements/extends
+ the class defined by the attribute "adaptto".
+ If "adaptto" is not set,
+ the defined class will always be wrapped.
+ (introduced in ant1.6)
+ </td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
+ <td valign="top">adaptto</td>
+ <td valign="top">This attribute is used in conjunction with the
+ adapter attribute.
+ If the defined class does not implement/extend the interface/class
+ specified by this attribute, the adaptor class will be used
+ to wrap the class.
+ (introduced in ant1.6)
+ </td>
+ <td valign="top" align="center">No</td>
+ </tr>
</table>
<h3>Parameters specified as nested elements</h3>
<h4>classpath</h4>
@@ -79,8 +111,9 @@
<pre> <typedef name="urlset"
classname="com.mydomain.URLSet"/></pre>
<p>makes a data type called <code>urlset</code> available to Ant. The
class <code>com.mydomain.URLSet</code> implements this type.</p>
+
<hr>
-<p align="center">Copyright © 2001-2002 Apache Software
+<p align="center">Copyright © 2001-2003 Apache Software
Foundation. All rights Reserved.</p>
</body>
1.1 ant/src/etc/testcases/taskdefs/typeadapter.xml
Index: typeadapter.xml
===================================================================
<?xml version="1.0"?>
<project name="test" basedir="." default="invalid">
<property name="testcases.dir" location="../../../../build/testcases"/>
<path id="testclasses">
<pathelement location="${testcases.dir}" />
<pathelement path="${java.class.path}" />
</path>
<target name="taskadapter">
<typedef name="myexec"
classname="org.apache.tools.ant.taskdefs.TypeAdapterTest$MyExec"
classpathref="testclasses"
adapter="org.apache.tools.ant.TaskAdapter"/>
<myexec/>
</target>
<target name="runadapter">
<typedef
name="myrunnable"
classname="org.apache.tools.ant.taskdefs.TypeAdapterTest$MyRunnable"
classpathref="testclasses"
adapter="org.apache.tools.ant.taskdefs.TypeAdapterTest$RunnableAdapter"/>
<myrunnable/>
</target>
<target name="runadaptererror">
<typedef
name="myrunnable"
classname="org.apache.tools.ant.taskdefs.TypeAdapterTest$MyExec"
classpathref="testclasses"
adapter="org.apache.tools.ant.taskdefs.TypeAdapterTest$RunnableAdapter"/>
<myrunnable/>
</target>
<target name="delay">
<typedef
name="mytask"
classname="org.apache.tools.ant.taskdefs.TypeAdapterTest$MyTask"
classpathref="testclasses"
onerror="ignore"/>
<mytask/>
</target>
<target name="onerror.report">
<typedef
name="mytask"
classname="org.apache.tools.ant.taskdefs.TypeAdapterTest$MyTaskNotPresent"
classpathref="testclasses"
onerror="report"/>
</target>
<target name="onerror.ignore">
<typedef
name="mytask"
classname="org.apache.tools.ant.taskdefs.TypeAdapterTest$MyTaskNotPresent"
classpathref="testclasses"
onerror="ignore"/>
</target>
</project>
1.12 +292 -312 ant/src/main/org/apache/tools/ant/ComponentHelper.java
Index: ComponentHelper.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/ComponentHelper.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- ComponentHelper.java 10 Jun 2003 14:05:58 -0000 1.11
+++ ComponentHelper.java 26 Jun 2003 08:54:28 -0000 1.12
@@ -59,7 +59,15 @@
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Properties;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+
import java.util.Vector;
import java.io.InputStream;
import java.io.IOException;
@@ -68,21 +76,28 @@
/**
* Component creation and configuration.
*
- * This is cut&paste from Project.java of everything related to
- * task/type management. Project will just delegate.
+ * The class is based around handing component
+ * definitions in an AntTypeTable.
+ *
+ * The old task/type methods have been kept
+ * for backward compatibly.
+ * Project will just delegate its calls to this class.
*
* A very simple hook mechnism is provided that allows users to plug
* in custom code. It is also possible to replace the default behavior
* ( for example in an app embeding ant )
*
* @author Costin Manolache
+ * @author Peter Reilly
* @since Ant1.6
*/
public class ComponentHelper {
- /** Map from data type names to implementing classes (String to Class).
*/
- private Hashtable dataClassDefinitions;
- /** Map from task names to implementing classes (String to Class). */
- private Hashtable taskClassDefinitions;
+ // Map from task names to implementing classes - not used anymore
+ private Hashtable taskClassDefinitions = new Hashtable();
+
+ /** Map from compoennt name to anttypedefinition */
+ private AntTypeTable antTypeTable;
+
/**
* Map from task names to vectors of created tasks
* (String to Vector of Task). This is used to invalidate tasks if
@@ -120,10 +135,24 @@
public void setProject(Project project) {
this.project = project;
- dataClassDefinitions= new AntTaskTable(project, false);
- taskClassDefinitions= new AntTaskTable(project, true);
+ antTypeTable = new AntTypeTable(project);
}
+ /**
+ * Used with creating child projects. Each child
+ * project inherites the component definitions
+ * from its parent.
+ */
+ public void initSubProject(ComponentHelper helper) {
+ // add the types of the parent project
+ AntTypeTable typeTable = helper.antTypeTable;
+ for (Iterator i = typeTable.values().iterator(); i.hasNext();) {
+ AntTypeDefinition def = (AntTypeDefinition) i.next();
+ def = def.copy(project);
+ antTypeTable.put(def.getName(), def);
+ }
+ }
+
/** Factory method to create the components.
*
* This should be called by UnknownElement.
@@ -139,63 +168,54 @@
String taskName )
throws BuildException
{
- Object component=null;
-
- // System.out.println("Fallback to project default " + taskName );
- // Can't create component. Default is to use the old methods in
project.
+ Object component = createComponent(taskName);
+ if (component == null) {
+ return null;
+ }
- // This policy is taken from 1.5 ProjectHelper. In future the
difference between
- // task and type should disapear.
- if( project.getDataTypeDefinitions().get(taskName) != null ) {
- // This is the original policy in ProjectHelper. The 1.5 version
of UnkwnonwElement
- // used to try first to create a task, and if it failed tried a
type. In 1.6 the diff
- // should disapear.
- component = this.createDataType(taskName);
- if( component!=null ) return component;
- }
-
- // from UnkwnonwElement.createTask. The 'top level' case is removed,
we're
- // allways lazy
- component = this.createTask(taskName);
+ if (component instanceof Task) {
+ Task task = (Task) component;
+ task.setTaskType(taskName);
+ task.setTaskName(taskName);
+ addCreatedTask(taskName, task);
+ }
return component;
}
+
+ /**
+ * Create an object for a component.
+ *
+ * @param componentName the name of the component, if
+ * the component is in a namespace, the
+ * name is prefixed withe the namespace uri and ":"
+ * @return the class if found or null if not.
+ */
+ public Object createComponent(String componentName)
+ throws BuildException
+ {
+ return antTypeTable.create(componentName);
+ }
/**
- * get the class of a particular component
+ * Return the class of the component name.
+ *
+ * @param componentName the name of the component, if
+ * the component is in a namespace, the
+ * name is prefixed withe the namespace uri and ":"
+ * @return the class if found or null if not.
*/
public Class getComponentClass(String componentName) {
- Class elementClass =
- (Class) getTaskDefinitions().get(componentName);
- if (elementClass != null) {
- if (! (Task.class.isAssignableFrom(elementClass))) {
- elementClass = TaskAdapter.class;
- }
- return elementClass;
- }
- return (Class) getDataTypeDefinitions().get(componentName);
+ return antTypeTable.getExposedClass(componentName);
}
-
+
/**
- * create a named component
+ * Return the antTypeDefinition for a componentName
*/
- public Object createComponent(String componentName)
- throws BuildException
- {
- Object obj = createTask(componentName);
- if (obj == null) {
- obj = createDataType(componentName);
- }
- if (obj == null) {
- return obj;
- }
- project.setProjectReference(obj);
- if (obj instanceof Task) {
- ((Task)obj).init(); // Needed here ??
- }
- return obj;
+ public AntTypeDefinition getDefinition(String componentName) {
+ return antTypeTable.getDefinition(componentName);
}
-
+
/** Initialization code - implementing the original ant component
* loading from /org/apache/tools/ant/taskdefs/default.properties
* and .../types/default.properties
@@ -203,40 +223,8 @@
* @throws BuildException
*/
public void initDefaultDefinitions() throws BuildException {
- String defs = "/org/apache/tools/ant/taskdefs/defaults.properties";
-
- try {
- Properties props = new Properties();
- InputStream in = this.getClass().getResourceAsStream(defs);
- if (in == null) {
- throw new BuildException("Can't load default task list");
- }
- props.load(in);
- in.close();
- ((AntTaskTable)taskClassDefinitions).addDefinitions( props );
-
-
- } catch (IOException ioe) {
- throw new BuildException("Can't load default task list");
- }
-
- String dataDefs = "/org/apache/tools/ant/types/defaults.properties";
-
- try {
- Properties props = new Properties();
- InputStream in = this.getClass().getResourceAsStream(dataDefs);
- if (in == null) {
- throw new BuildException("Can't load default datatype list");
- }
- props.load(in);
- in.close();
-
- ((AntTaskTable)dataClassDefinitions).addDefinitions(props);
-
-
- } catch (IOException ioe) {
- throw new BuildException("Can't load default datatype list");
- }
+ initTasks();
+ initTypes();
}
/**
@@ -259,44 +247,17 @@
*
* @see #checkTaskClass(Class)
*/
- public void addTaskDefinition(String taskName, Class taskClass)
- throws BuildException {
- Class old = (Class) taskClassDefinitions.get(taskName);
- if (null != old) {
- if (old.equals(taskClass)) {
-// project.log("Ignoring override for task " + taskName
-// + ", it is already defined by the same class.",
-// Project.MSG_VERBOSE);
- return;
- } else {
- int logLevel = Project.MSG_WARN;
- if (old.getName().equals(taskClass.getName())) {
- ClassLoader oldLoader = old.getClassLoader();
- ClassLoader newLoader = taskClass.getClassLoader();
- // system classloader on older JDKs can be null
- if (oldLoader != null
- && newLoader != null
- && oldLoader instanceof AntClassLoader
- && newLoader instanceof AntClassLoader
- && ((AntClassLoader) oldLoader).getClasspath()
- .equals(((AntClassLoader)
newLoader).getClasspath())
- ) {
- // same classname loaded from the same
- // classpath components
- logLevel = Project.MSG_VERBOSE;
- }
- }
-
- project.log("Trying to override old definition of task " +
taskName,
- logLevel);
- invalidateCreatedTasks(taskName);
- }
- }
-
- String msg = " +User task: " + taskName + " " +
taskClass.getName();
- project.log(msg, Project.MSG_DEBUG);
+ public void addTaskDefinition(String taskName, Class taskClass) {
checkTaskClass(taskClass);
- taskClassDefinitions.put(taskName, taskClass);
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setProject(project);
+ def.setName(taskName);
+ def.setClassLoader(taskClass.getClassLoader());
+ def.setClass(taskClass);
+ def.setAdapterClass(TaskAdapter.class);
+ def.setClassName(taskClass.getName());
+ def.setAdaptToClass(Task.class);
+ updateDataTypeDefinition(def);
}
/**
@@ -340,6 +301,7 @@
/**
* Returns the current task definition hashtable. The returned hashtable
is
* "live" and so should not be modified.
+ * This table does not contain any information
*
* @return a map of from task name to implementing class
* (String to Class).
@@ -347,7 +309,7 @@
public Hashtable getTaskDefinitions() {
return taskClassDefinitions;
}
-
+
/**
* Adds a new datatype definition.
* Attempting to override an existing definition with an
@@ -362,27 +324,26 @@
* Must not be <code>null</code>.
*/
public void addDataTypeDefinition(String typeName, Class typeClass) {
- synchronized(dataClassDefinitions) {
- Class old = (Class) dataClassDefinitions.get(typeName);
- if (null != old) {
- if (old.equals(typeClass)) {
-// project.log("Ignoring override for datatype " +
typeName
-// + ", it is already defined by the same class.",
-// Project.MSG_VERBOSE);
- return;
- } else {
- project.log("Trying to override old definition of
datatype "
- + typeName, Project.MSG_WARN);
- }
- }
- dataClassDefinitions.put(typeName, typeClass);
- }
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setProject(project);
+ def.setName(typeName);
+ def.setClass(typeClass);
+ updateDataTypeDefinition(def);
String msg = " +User datatype: " + typeName + " "
+ typeClass.getName();
project.log(msg, Project.MSG_DEBUG);
}
/**
+ * Describe <code>addDataTypeDefinition</code> method here.
+ *
+ * @param def an <code>AntTypeDefinition</code> value
+ */
+ public void addDataTypeDefinition(AntTypeDefinition def) {
+ updateDataTypeDefinition(def);
+ }
+
+ /**
* Returns the current datatype definition hashtable. The returned
* hashtable is "live" and so should not be modified.
*
@@ -390,7 +351,7 @@
* (String to Class).
*/
public Hashtable getDataTypeDefinitions() {
- return dataClassDefinitions;
+ return antTypeTable;
}
/**
@@ -432,49 +393,26 @@
* creation fails.
*/
private Task createNewTask(String taskType) throws BuildException {
- Class c = (Class) taskClassDefinitions.get(taskType);
-
+ Class c = antTypeTable.getExposedClass(taskType);
if (c == null) {
return null;
}
+
+ if (! Task.class.isAssignableFrom(c)) {
+ return null;
+ }
+ Task task = (Task) antTypeTable.create(taskType);
+ if (task == null) {
+ return null;
+ }
+ task.setTaskType(taskType);
- try {
- Object o = c.newInstance();
- if ( project != null ) {
- project.setProjectReference( o );
- }
- Task task = null;
- if (o instanceof Task) {
- task = (Task) o;
- } else {
- // "Generic" Bean - use the setter pattern
- // and an Adapter
- TaskAdapter taskA = new TaskAdapter();
- taskA.setProxy(o);
- if ( project != null ) {
- project.setProjectReference( taskA );
- }
- task = taskA;
- }
- task.setProject( project );
- task.setTaskType(taskType);
-
- // set default value, can be changed by the user
- task.setTaskName(taskType);
+ // set default value, can be changed by the user
+ task.setTaskName(taskType);
- String msg = " +Task: " + taskType;
- project.log (msg, Project.MSG_DEBUG);
- return task;
- } catch (NoClassDefFoundError ncdfe) {
- String msg = "Task " + taskType + ": A class needed by class "
- + c + " cannot be found: " + ncdfe.getMessage();
- throw new BuildException(msg, ncdfe);
- } catch (Throwable t) {
- System.out.println("task CL=" + c.getClassLoader());
- String msg = "Could not create task of type: "
- + taskType + " due to " + t;
- throw new BuildException(msg, t);
- }
+ String msg = " +Task: " + taskType;
+ project.log (msg, Project.MSG_DEBUG);
+ return task;
}
/**
@@ -538,52 +476,11 @@
* instance creation fails.
*/
public Object createDataType(String typeName) throws BuildException {
- Class c = (Class) dataClassDefinitions.get(typeName);
-
- if (c == null) {
- return null;
- }
-
- try {
- java.lang.reflect.Constructor ctor = null;
- boolean noArg = false;
- // DataType can have a "no arg" constructor or take a single
- // Project argument.
- try {
- ctor = c.getConstructor(new Class[0]);
- noArg = true;
- } catch (NoSuchMethodException nse) {
- ctor = c.getConstructor(new Class[] {Project.class});
- noArg = false;
- }
-
- Object o = null;
- if (noArg) {
- o = ctor.newInstance(new Object[0]);
- } else {
- o = ctor.newInstance(new Object[] {project});
- }
- if ( project != null ) {
- project.setProjectReference( o );
- }
- String msg = " +DataType: " + typeName;
- project.log(msg, Project.MSG_DEBUG);
- return o;
- } catch (java.lang.reflect.InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- String msg = "Could not create datatype of type: "
- + typeName + " due to " + t;
- throw new BuildException(msg, t);
- } catch (Throwable t) {
- String msg = "Could not create datatype of type: "
- + typeName + " due to " + t;
- throw new BuildException(msg, t);
- }
+ return antTypeTable.create(typeName);
}
/**
- * Returns a description of the type of the given element, with
- * special handling for instances of tasks and data types.
+ * Returns a description of the type of the given element.
* <p>
* This is useful for logging purposes.
*
@@ -595,127 +492,210 @@
* @since Ant 1.6
*/
public String getElementName(Object element) {
- Hashtable elements = taskClassDefinitions;
+ // PR: I do not know what to do if the object class
+ // has multiple defines
+ // but this is for logging only...
Class elementClass = element.getClass();
- String typeName = "task";
- if (!elements.contains(elementClass)) {
- elements = dataClassDefinitions;
- typeName = "data type";
- if (!elements.contains(elementClass)) {
- elements = null;
+ for (Iterator i = antTypeTable.values().iterator(); i.hasNext();) {
+ AntTypeDefinition def = (AntTypeDefinition) i.next();
+ if (elementClass == def.getExposedClass()) {
+ return "The <" + def.getName() + "> type";
}
}
+ return "Class " + elementClass.getName();
+ }
+
+
+ /** return true if the two definitions are the same */
+ private boolean sameDefinition(
+ AntTypeDefinition def, AntTypeDefinition old) {
+ if (! (old.getTypeClass().equals(def.getTypeClass()))) {
+ return false;
+ }
+ if (! (old.getExposedClass().equals(def.getExposedClass()))) {
+ return false;
+ }
+ return true;
+ }
- if (elements != null) {
- Enumeration e = elements.keys();
- while (e.hasMoreElements()) {
- String name = (String) e.nextElement();
- Class clazz = (Class) elements.get(name);
- if (elementClass.equals(clazz)) {
- return "The <" + name + "> " + typeName;
+ /**
+ * update the component definition table with a new or
+ * modified definition.
+ */
+ private void updateDataTypeDefinition(AntTypeDefinition def) {
+ String name = def.getName();
+ synchronized (antTypeTable) {
+ AntTypeDefinition old = antTypeTable.getDefinition(name);
+ if (old != null) {
+ if (sameDefinition(def, old)) {
+ return;
+ }
+ Class oldClass = antTypeTable.getExposedClass(name);
+ if (Task.class.isAssignableFrom(oldClass)) {
+ int logLevel = Project.MSG_WARN;
+ if (def.getClassName().equals(old.getClassName()) &&
+ def.getClassLoader() == old.getClassLoader()) {
+ logLevel = Project.MSG_VERBOSE;
+ }
+ project.log(
+ "Trying to override old definition of task " +
+ name, logLevel);
+ invalidateCreatedTasks(name);
+ } else {
+ project.log(
+ "Trying to override old definition of datatype " +
+ name, Project.MSG_WARN);
}
}
+ project.log(" +Datatype " + name + " " + def.getClassName(),
+ Project.MSG_DEBUG);
+ antTypeTable.put(name, def);
}
-
- return "Class " + elementClass.getName();
}
+ /**
+ * load ant's tasks
+ */
+ private void initTasks() {
+ ClassLoader classLoader = null;
+ if (project.getCoreLoader() != null &&
+ ! ("only".equals(project.getProperty("build.sysclasspath")))) {
+ classLoader = project.getCoreLoader();
+ }
+ String dataDefs =
"/org/apache/tools/ant/taskdefs/defaults.properties";
- private static class AntTaskTable extends LazyHashtable {
- Project project;
- Properties props;
- boolean tasks=false;
+ InputStream in = null;
+ try {
+ Properties props = new Properties();
+ in = this.getClass().getResourceAsStream(dataDefs);
+ if (in == null) {
+ throw new BuildException("Can't load default task list");
+ }
+ props.load(in);
- public AntTaskTable( Project p, boolean tasks ) {
- this.project=p;
- this.tasks=tasks;
+ Enumeration enum = props.propertyNames();
+ while (enum.hasMoreElements()) {
+ String name = (String) enum.nextElement();
+ String className = props.getProperty(name);
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setProject(project);
+ def.setName(name);
+ def.setClassName(className);
+ def.setClassLoader(classLoader);
+ def.setAdaptToClass(Task.class);
+ def.setAdapterClass(TaskAdapter.class);
+ antTypeTable.put(name, def);
+ }
+ } catch (IOException ex) {
+ throw new BuildException("Can't load default type list");
}
+ finally {
+ if (in != null) {
+ try {in.close();} catch (Exception ignore) {}
+ }
+ }
+ }
- public void addDefinitions( Properties props ) {
- this.props=props;
+ /**
+ * load ant's datatypes
+ */
+ private void initTypes() {
+ ClassLoader classLoader = null;
+ if (project.getCoreLoader() != null &&
+ ! ("only".equals(project.getProperty("build.sysclasspath")))) {
+ classLoader = project.getCoreLoader();
}
+ String dataDefs = "/org/apache/tools/ant/types/defaults.properties";
- protected void initAll( ) {
- if( initAllDone ) {
- return;
- }
- project.log("InitAll", Project.MSG_DEBUG);
- if( props==null ) {
- return;
+ InputStream in = null;
+ try {
+ Properties props = new Properties();
+ in = this.getClass().getResourceAsStream(dataDefs);
+ if (in == null) {
+ throw new BuildException("Can't load default datatype list");
}
+ props.load(in);
+
Enumeration enum = props.propertyNames();
while (enum.hasMoreElements()) {
- String key = (String) enum.nextElement();
- Class taskClass=getTask( key );
- if( taskClass!=null ) {
- // This will call a get() and a put()
- if( tasks ) {
- project.addTaskDefinition(key, taskClass);
- } else {
- project.addDataTypeDefinition(key, taskClass );
- }
- }
+ String name = (String) enum.nextElement();
+ String className = props.getProperty(name);
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setProject(project);
+ def.setName(name);
+ def.setClassName(className);
+ def.setClassLoader(classLoader);
+ antTypeTable.put(name, def);
}
- initAllDone=true;
+ } catch (IOException ex) {
+ throw new BuildException("Can't load default type list");
}
-
- protected Class getTask(String key) {
- if( props==null ) {
- return null; // for tasks loaded before init()
+ finally {
+ if (in != null) {
+ try {in.close();} catch (Exception ignore) {}
}
- String value=props.getProperty(key);
- if( value==null) {
- //project.log( "No class name for " + key,
Project.MSG_VERBOSE );
+ }
+ }
+
+ /**
+ * map that contains the component definitions
+ */
+ private static class AntTypeTable extends Hashtable {
+ Project project;
+
+ public AntTypeTable(Project project) {
+ this.project = project;
+ }
+
+ public AntTypeDefinition getDefinition(String key) {
+ AntTypeDefinition ret = (AntTypeDefinition) super.get(key);
+ return ret;
+ }
+
+ /** Equivalent to getTypeType */
+ public Object get(Object key) {
+ return getTypeClass((String) key);
+ }
+
+ public Object create(String name) {
+ AntTypeDefinition def = getDefinition(name);
+ if (def == null) {
return null;
}
- try {
- Class taskClass=null;
- if( project.getCoreLoader() != null &&
-
!("only".equals(project.getProperty("build.sysclasspath")))) {
- try {
- project.log("Loading with the core loader " + value,
- Project.MSG_DEBUG);
- taskClass=project.getCoreLoader().loadClass(value);
- if( taskClass != null ) {
- return taskClass;
- }
- } catch( Exception ex ) {
- //ignore
- }
- }
- taskClass = Class.forName(value);
- return taskClass;
- } catch (NoClassDefFoundError ncdfe) {
- project.log("Could not load a dependent class ("
- + ncdfe.getMessage() + ") for task "
- + key, Project.MSG_DEBUG);
- } catch (ClassNotFoundException cnfe) {
- project.log("Could not load class (" + value
- + ") for task " + key, Project.MSG_DEBUG);
+ return def.create();
+ }
+
+ public Class getTypeClass(String name) {
+ AntTypeDefinition def = getDefinition(name);
+ if (def == null) {
+ return null;
}
- return null;
+ return def.getTypeClass();
}
- // Hashtable implementation
- public Object get( Object key ) {
- Object orig=super.get( key );
- if( orig!= null ) {
- return orig;
- }
- if( ! (key instanceof String) ) {
+ public Class getExposedClass(String name) {
+ AntTypeDefinition def = getDefinition(name);
+ if (def == null) {
return null;
}
- project.log("Get task " + key, Project.MSG_DEBUG );
- Object taskClass=getTask( (String) key);
- if( taskClass != null) {
- super.put( key, taskClass );
- }
- return taskClass;
+ return def.getExposedClass();
}
- public boolean containsKey( Object key ) {
- return get( key ) != null;
+ public boolean contains(Object clazz) {
+ // only used in unit test ProjectTest
+ // needed ???
+ for (Iterator i = values().iterator(); i.hasNext();) {
+ AntTypeDefinition def = (AntTypeDefinition) i.next();
+ Class c = def.getExposedClass();
+ if (c == clazz)
+ return true;
+ }
+ return false;
}
+ public boolean containsValue(Object value) {
+ return contains(value);
+ }
}
+
}
1.141 +9 -1 ant/src/main/org/apache/tools/ant/Project.java
Index: Project.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/Project.java,v
retrieving revision 1.140
retrieving revision 1.141
diff -u -r1.140 -r1.141
--- Project.java 10 Jun 2003 13:29:55 -0000 1.140
+++ Project.java 26 Jun 2003 08:54:28 -0000 1.141
@@ -268,6 +268,14 @@
}
/**
+ * inits a sub project - used by taskdefs.Ant
+ */
+ public void initSubProject(Project subProject) {
+ ComponentHelper.getComponentHelper(subProject)
+ .initSubProject(ComponentHelper.getComponentHelper(this));
+ }
+
+ /**
* Initialises the project.
*
* This involves setting the default task definitions and loading the
1.96 +4 -4 ant/src/main/org/apache/tools/ant/ProjectHelper.java
Index: ProjectHelper.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/ProjectHelper.java,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -r1.95 -r1.96
--- ProjectHelper.java 14 Apr 2003 14:47:41 -0000 1.95
+++ ProjectHelper.java 26 Jun 2003 08:54:28 -0000 1.96
@@ -324,8 +324,8 @@
*/
public static void configure(Object target, AttributeList attrs,
Project project) throws BuildException {
- if (target instanceof TaskAdapter) {
- target = ((TaskAdapter) target).getProxy();
+ if (target instanceof TypeAdapter) {
+ target = ((TypeAdapter) target).getProxy();
}
IntrospectionHelper ih =
@@ -389,8 +389,8 @@
return;
}
- if (target instanceof TaskAdapter) {
- target = ((TaskAdapter) target).getProxy();
+ if (target instanceof TypeAdapter) {
+ target = ((TypeAdapter) target).getProxy();
}
IntrospectionHelper.getHelper(target.getClass()).addText(project,
1.35 +2 -2
ant/src/main/org/apache/tools/ant/RuntimeConfigurable.java
Index: RuntimeConfigurable.java
===================================================================
RCS file:
/home/cvs/ant/src/main/org/apache/tools/ant/RuntimeConfigurable.java,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- RuntimeConfigurable.java 9 Jun 2003 13:38:06 -0000 1.34
+++ RuntimeConfigurable.java 26 Jun 2003 08:54:28 -0000 1.35
@@ -310,8 +310,8 @@
}
// Configure the object
- Object target = (wrappedObject instanceof TaskAdapter) ?
- ((TaskAdapter) wrappedObject).getProxy() : wrappedObject;
+ Object target = (wrappedObject instanceof TypeAdapter) ?
+ ((TypeAdapter) wrappedObject).getProxy() : wrappedObject;
//PropertyHelper ph=PropertyHelper.getPropertyHelper(p);
IntrospectionHelper ih =
1.21 +9 -1 ant/src/main/org/apache/tools/ant/TaskAdapter.java
Index: TaskAdapter.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/TaskAdapter.java,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- TaskAdapter.java 5 Jun 2003 09:35:47 -0000 1.20
+++ TaskAdapter.java 26 Jun 2003 08:54:28 -0000 1.21
@@ -63,7 +63,7 @@
*
* @author [EMAIL PROTECTED]
*/
-public class TaskAdapter extends Task {
+public class TaskAdapter extends Task implements TypeAdapter {
/** Object to act as a proxy for. */
private Object proxy;
@@ -107,6 +107,14 @@
project.log(message, Project.MSG_ERR);
throw new BuildException(message);
}
+ }
+
+ /**
+ * check if the proxy class is a valid class to use
+ * with this adapter.
+ */
+ public void checkProxyClass(Class proxyClass) {
+ checkTaskClass(proxyClass, getProject());
}
/**
1.51 +2 -2 ant/src/main/org/apache/tools/ant/UnknownElement.java
Index: UnknownElement.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/UnknownElement.java,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -r1.50 -r1.51
--- UnknownElement.java 9 Jun 2003 13:38:06 -0000 1.50
+++ UnknownElement.java 26 Jun 2003 08:54:28 -0000 1.51
@@ -300,8 +300,8 @@
protected void handleChildren(Object parent,
RuntimeConfigurable parentWrapper)
throws BuildException {
- if (parent instanceof TaskAdapter) {
- parent = ((TaskAdapter) parent).getProxy();
+ if (parent instanceof TypeAdapter) {
+ parent = ((TypeAdapter) parent).getProxy();
}
Class parentClass = parent.getClass();
1.1 ant/src/main/org/apache/tools/ant/AntTypeDefinition.java
Index: AntTypeDefinition.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Ant" and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
/**
* This class contains all the information
* on a particular ant type,
* the classname, adaptor and the class
* it should be assignable from.
* This type replaces the task/datatype split
* of pre ant 1.6.
*
* @author Peter Reilly
*/
public class AntTypeDefinition {
private Project project;
private String name;
private Class clazz;
private Class adapterClass;
private Class adaptToClass;
private String className;
private ClassLoader classLoader;
/**
* Clone this definiton and changed the cloned definitions' project.
* @param p the project the cloned definition lives in
* @return the cloned definition
*/
public AntTypeDefinition copy(Project p) {
AntTypeDefinition copy = new AntTypeDefinition();
copy.project = p;
copy.name = name;
copy.clazz = clazz;
copy.adapterClass = adapterClass;
copy.className = className;
copy.classLoader = classLoader;
copy.adaptToClass = adaptToClass;
return copy;
}
/** set the project on the definition */
public void setProject(Project project) {
this.project = project;
}
/** set the definiton's name */
public void setName(String name) {
this.name = name;
}
/** return the definition's name */
public String getName() {
return name;
}
/**
* set the class of the definition.
* as a side-effect may set the classloader and classname
*/
public void setClass(Class clazz) {
this.clazz = clazz;
if (clazz == null) {
return;
}
if (classLoader == null) {
this.classLoader = clazz.getClassLoader();
}
if (className == null) {
this.className = clazz.getName();
}
}
/** set the classname of the definition */
public void setClassName(String className) {
this.className = className;
}
/** get the classname of the definition */
public String getClassName() {
return className;
}
/**
* set the adapter class for this definition.
* this class is used to adapt the definitions class if
* required.
*/
public void setAdapterClass(Class adapterClass) {
this.adapterClass = adapterClass;
}
/**
* set the assignable class for this definition.
*/
public void setAdaptToClass(Class adaptToClass) {
this.adaptToClass = adaptToClass;
}
/**
* set the classloader to use to create an instance
* of the definition
*/
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/** get the classloader for this definition */
public ClassLoader getClassLoader() {
return classLoader;
}
/**
* get the exposed class for this
* definition. This will be a proxy class
* (adapted class) if there is an adpater
* class and the definition class is not
* assignable from the assignable class.
*/
public Class getExposedClass() {
if (adaptToClass != null) {
Class z = getTypeClass();
if (z == null)
return null;
if (adaptToClass.isAssignableFrom(z)) {
return z;
}
}
if (adapterClass != null) {
return adapterClass;
}
return getTypeClass();
}
/**
* get the definition class
*/
public Class getTypeClass() {
if (clazz != null) {
return clazz;
}
try {
if (classLoader == null) {
clazz = Class.forName(className);
} else {
clazz = classLoader.loadClass(className);
}
} catch (NoClassDefFoundError ncdfe) {
project.log("Could not load a dependent class ("
+ ncdfe.getMessage() + ") for type "
+ name, Project.MSG_DEBUG);
} catch (ClassNotFoundException cnfe) {
project.log("Could not load class (" + className
+ ") for type " + name, Project.MSG_DEBUG);
}
return clazz;
}
/**
* create an instance of the definition.
* The instance may be wrapped in a proxy class.
*/
public Object create() {
Object o = icreate();
return o;
}
/**
* Create a component object based on
* its definition
*/
private Object icreate() {
Class c = getTypeClass();
if (c == null) {
return null;
}
Object o = createAndSet(c);
if (o == null || adapterClass == null) {
return o;
}
if (adaptToClass != null) {
if (adaptToClass.isAssignableFrom(o.getClass())) {
return o;
}
}
TypeAdapter adapterObject = (TypeAdapter) createAndSet(adapterClass);
if (adapterObject == null) {
return null;
}
adapterObject.setProxy(o);
return adapterObject;
}
/**
* check if the attributes are correct
* <dl>
* <li>if an adapter class can be created</li>
* <li>if the type is
*
*
* (Used during creation of the definition).
*/
public void checkClass() {
if (clazz == null) {
clazz = getTypeClass();
if (clazz == null) {
throw new BuildException(
"Unable to create class for " + getName());
}
}
// check adapter
if (adapterClass != null) {
boolean needToCheck = true;
if (adaptToClass != null &&
adaptToClass.isAssignableFrom(clazz)) {
needToCheck = false;
}
if (needToCheck) {
TypeAdapter adapter = (TypeAdapter)
createAndSet(adapterClass);
if (adapter == null) {
throw new BuildException("Unable to create adapter
object");
}
adapter.checkProxyClass(clazz);
}
}
}
/**
* get the constructor of the defintion
* and invoke it.
*/
private Object createAndSet(Class c) {
try {
java.lang.reflect.Constructor ctor = null;
boolean noArg = false;
// DataType can have a "no arg" constructor or take a single
// Project argument.
try {
ctor = c.getConstructor(new Class[0]);
noArg = true;
} catch (NoSuchMethodException nse) {
ctor = c.getConstructor(new Class[] {Project.class});
noArg = false;
}
Object o = null;
if (noArg) {
o = ctor.newInstance(new Object[0]);
} else {
o = ctor.newInstance(new Object[] {project});
}
project.setProjectReference(o);
return o;
} catch (java.lang.reflect.InvocationTargetException ex) {
Throwable t = ex.getTargetException();
throw new BuildException(
"Could not create type " + name + " due to " + t, t);
} catch (NoClassDefFoundError ncdfe) {
String msg = "Type " + name + ": A class needed by class "
+ c + " cannot be found: " + ncdfe.getMessage();
throw new BuildException(msg, ncdfe);
} catch (Throwable t) {
throw new BuildException(
"Could not create type " + name + " due to " + t, t);
}
}
}
1.1 ant/src/main/org/apache/tools/ant/TypeAdapter.java
Index: TypeAdapter.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Ant" and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant;
import java.lang.reflect.Method;
/**
* Used to wrap types.
*
* @author [EMAIL PROTECTED]
* @author peter reilly
*/
public interface TypeAdapter {
/**
* Sets the project
*/
public void setProject(Project p);
/**
* Gets the project
*/
public Project getProject();
/**
* Sets the proxy object, whose methods are going to be
* invoked by ant.
* A proxy object is normally the object defined by
* a <typedef/> task that is adapted by the "adapter"
* attribute.
*
* @param o The target object. Must not be <code>null</code>.
*/
public void setProxy(Object o);
/**
* Returns the proxy object.
*
* @return the target proxy object
*/
public Object getProxy();
/**
* Check if the proxy class matchs the criteria
*/
public void checkProxyClass(Class proxyClass);
}
1.19 +4 -4
ant/src/main/org/apache/tools/ant/helper/ProjectHelperImpl.java
Index: ProjectHelperImpl.java
===================================================================
RCS file:
/home/cvs/ant/src/main/org/apache/tools/ant/helper/ProjectHelperImpl.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- ProjectHelperImpl.java 14 Apr 2003 11:58:04 -0000 1.18
+++ ProjectHelperImpl.java 26 Jun 2003 08:54:28 -0000 1.19
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -68,7 +68,7 @@
import org.apache.tools.ant.RuntimeConfigurable;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.Task;
-import org.apache.tools.ant.TaskAdapter;
+import org.apache.tools.ant.TypeAdapter;
import org.apache.tools.ant.TaskContainer;
import org.apache.tools.ant.UnknownElement;
import org.apache.tools.ant.util.FileUtils;
@@ -865,8 +865,8 @@
Target target) {
super(helperImpl, parentHandler);
- if (parent instanceof TaskAdapter) {
- this.parent = ((TaskAdapter) parent).getProxy();
+ if (parent instanceof TypeAdapter) {
+ this.parent = ((TypeAdapter) parent).getProxy();
} else {
this.parent = parent;
}
1.78 +2 -22 ant/src/main/org/apache/tools/ant/taskdefs/Ant.java
Index: Ant.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Ant.java,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- Ant.java 12 May 2003 12:57:04 -0000 1.77
+++ Ant.java 26 Jun 2003 08:54:29 -0000 1.78
@@ -156,9 +156,6 @@
newProject = new Project();
newProject.setDefaultInputStream(getProject().getDefaultInputStream());
newProject.setJavaVersionProperty();
- newProject.addTaskDefinition("property",
- (Class)
getProject().getTaskDefinitions()
- .get("property"));
}
/**
@@ -238,25 +235,7 @@
}
}
- Hashtable taskdefs = getProject().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 = getProject().getDataTypeDefinitions();
- Enumeration e = typedefs.keys();
- while (e.hasMoreElements()) {
- String typeName = (String) e.nextElement();
- Class typeClass = (Class) typedefs.get(typeName);
- newProject.addDataTypeDefinition(typeName, typeClass);
- }
+ getProject().initSubProject(newProject);
// set user-defined properties
getProject().copyUserProperties(newProject);
@@ -271,6 +250,7 @@
addAlmostAll(getProject().getProperties());
}
+ Enumeration e;
e = propertySets.elements();
while (e.hasMoreElements()) {
PropertySet ps = (PropertySet) e.nextElement();
1.31 +241 -88 ant/src/main/org/apache/tools/ant/taskdefs/Definer.java
Index: Definer.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Definer.java,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- Definer.java 10 Jun 2003 14:05:58 -0000 1.30
+++ Definer.java 26 Jun 2003 08:54:29 -0000 1.31
@@ -58,15 +58,23 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URL;
import java.util.Enumeration;
+import java.util.Locale;
import java.util.Properties;
+
+import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.ClasspathUtils;
+import org.apache.tools.ant.types.EnumeratedAttribute;
/**
* Base class for Taskdef and Typedef - does all the classpath
@@ -79,10 +87,61 @@
*/
public abstract class Definer extends Task {
private String name;
- private String value;
+ private String classname;
private File file;
private String resource;
private ClasspathUtils.Delegate cpDelegate;
+
+ private int format = Format.PROPERTIES;
+ private boolean definerSet = false;
+ private ClassLoader internalClassLoader;
+ private int onError = OnError.FAIL;
+ private String adapter;
+ private String adaptTo;
+
+ private Class adapterClass;
+ private Class adaptToClass;
+
+ public static class OnError extends EnumeratedAttribute {
+ public static final int FAIL = 0, REPORT = 1, IGNORE = 2;
+ public OnError() {
+ super();
+ }
+ public OnError(String value) {
+ setValue(value);
+ }
+ public String[] getValues() {
+ return new String[] {"fail", "report", "ignore"};
+ }
+ }
+
+ public static class Format extends EnumeratedAttribute {
+ public static final int PROPERTIES=0, XML=1;
+ public String[] getValues() {
+ return new String[] {"properties", "xml"};
+ }
+ }
+
+ /**
+ * What to do if there is an error in loading the class.
+ * <dl>
+ * <li>error - throw build exception</li>
+ * <li>report - output at warning level</li>
+ * <li>ignore - output at debug level</li>
+ * </dl>
+ *
+ * @param onError an <code>OnError</code> value
+ */
+ public void setOnError(OnError onError) {
+ this.onError = onError.getIndex();
+ }
+
+ /**
+ * Sets the format of the file or resource
+ */
+ public void setFormat(Format format) {
+ this.format = format.getIndex();
+ }
/**
* @deprecated stop using this attribute
@@ -165,101 +224,107 @@
public void execute() throws BuildException {
ClassLoader al = createLoader();
- if (file == null && resource == null) {
-
- // simple case - one definition
- if (name == null || value == null) {
- String msg = "name or classname attributes of "
- + getTaskName() + " element "
- + "are undefined";
- throw new BuildException(msg);
+ if (!definerSet) {
+ throw new BuildException(
+ "name, file or resource attribute of "
+ + getTaskName() + " is undefined", getLocation());
+ }
+
+ if (name != null) {
+ if (classname == null) {
+ throw new BuildException(
+ "classname attribute of " + getTaskName() + " element "
+ + "is undefined", getLocation());
}
- addDefinition(al, name, value);
-
+ addDefinition(al, name, classname);
} else {
+ if (classname != null) {
+ String msg = "You must not specify classname "
+ + "together with file or resource.";
+ throw new BuildException(msg, getLocation());
+ }
+ URL url = null;
+ if (file != null) {
+ url = fileToURL();
+ }
+ if (resource != null) {
+ url = resourceToURL(al);
+ }
- InputStream is = null;
- try {
- if (name != null || value != null) {
- String msg = "You must not specify name or value "
- + "together with file or resource.";
- throw new BuildException(msg, getLocation());
- }
-
- if (file != null && resource != null) {
- String msg = "You must not specify both, file and "
- + "resource.";
- throw new BuildException(msg, getLocation());
- }
+ if (url == null) {
+ return;
+ }
+ loadProperties(al, url);
+ }
+ }
- Properties props = new Properties();
- if (file != null) {
- log("Loading definitions from file " + file,
- Project.MSG_VERBOSE);
- is = new FileInputStream(file);
- if (is == null) {
- log("Could not load definitions from file " + file
- + ". It doesn\'t exist.", Project.MSG_WARN);
- }
- }
- if (resource != null) {
- log("Loading definitions from resource " + resource,
- Project.MSG_VERBOSE);
- is = al.getResourceAsStream(resource);
- if (is == null) {
- log("Could not load definitions from resource "
- + resource + ". It could not be found.",
- Project.MSG_WARN);
- }
- }
+ private URL fileToURL() {
+ if (! file.exists()) {
+ log("File " + file + " does not exist", Project.MSG_WARN);
+ return null;
+ }
+ if (! file.isFile()) {
+ log("File " + file + " is not a file", Project.MSG_WARN);
+ return null;
+ }
+ try {
+ return file.toURL();
+ } catch (Exception ex) {
+ log("File " + file + " cannot use as URL: " +
+ ex.toString(), Project.MSG_WARN);
+ return null;
+ }
+ }
- if (is != null) {
- props.load(is);
- Enumeration keys = props.keys();
- while (keys.hasMoreElements()) {
- String n = (String) keys.nextElement();
- String v = props.getProperty(n);
- addDefinition(al, n, v);
- }
- }
- } catch (IOException ex) {
- throw new BuildException(ex, getLocation());
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {}
- }
+ private URL resourceToURL(ClassLoader classLoader) {
+ URL ret = classLoader.getResource(resource);
+ if (ret == null) {
+ if (onError != OnError.IGNORE) {
+ log("Could not load definitions from resource "
+ + resource + ". It could not be found.",
+ Project.MSG_WARN);
}
}
+ return ret;
}
-
- /**
- * create the classloader then hand the definition off to the subclass;
- * @throws BuildException when the class wont load for any reason
- */
- private void addDefinition(ClassLoader al, String name, String value)
- throws BuildException {
+
+ protected void loadProperties(ClassLoader al, URL url) {
+ InputStream is = null;
try {
- Class c = al.loadClass(value);
- AntClassLoader.initializeClass(c);
- addDefinition(name, c);
- } catch (ClassNotFoundException cnfe) {
- String msg = getTaskName() + " class " + value
- + " cannot be found";
- throw new BuildException(msg, cnfe, getLocation());
- } catch (NoClassDefFoundError ncdfe) {
- String msg = getTaskName() + ": A class needed by class "
- + value + " cannot be found: " + ncdfe.getMessage();
- throw new BuildException(msg, ncdfe, location);
+ is = url.openStream();
+ if (is == null) {
+ log("Could not load definitions from " + url,
+ Project.MSG_WARN);
+ return;
+ }
+ Properties props = new Properties();
+ props.load(is);
+ Enumeration keys = props.keys();
+ while (keys.hasMoreElements()) {
+ name = ((String) keys.nextElement());
+ classname = props.getProperty(name);
+ addDefinition(al, name, classname);
+ }
+ } catch (IOException ex) {
+ throw new BuildException(ex, getLocation());
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {}
+ }
}
}
+
/**
* create a classloader for this definition
*/
- private ClassLoader createLoader() {
+ protected ClassLoader createLoader() {
+ if (internalClassLoader != null) {
+ return internalClassLoader;
+ }
ClassLoader al = this.cpDelegate.getClassLoader();
// need to load Task via system classloader or the new
// task we want to define will never be a Task but always
@@ -274,6 +339,10 @@
* ant name/classname pairs from.
*/
public void setFile(File file) {
+ if (definerSet) {
+ tooManyDefinitions();
+ }
+ definerSet = true;
this.file = file;
}
@@ -282,6 +351,10 @@
* ant name/classname pairs from.
*/
public void setResource(String res) {
+ if (definerSet) {
+ tooManyDefinitions();
+ }
+ definerSet = true;
this.resource = res;
}
@@ -290,6 +363,10 @@
* ant name/classname pairs from.
*/
public void setName(String name) {
+ if (definerSet) {
+ tooManyDefinitions();
+ }
+ definerSet = true;
this.name = name;
}
@@ -298,7 +375,7 @@
* May be <code>null</code>.
*/
public String getClassname() {
- return value;
+ return classname;
}
/**
@@ -307,16 +384,29 @@
* been specified.
*/
public void setClassname(String v) {
- value = v;
+ classname = v;
}
- /**
- * This must be implemented by subclasses; it is the callback
- * they will get to add a new definition of their type.
- */
- protected abstract void addDefinition(String name, Class c);
-
+ public void setAdapter(String adapter) {
+ this.adapter = adapter;
+ }
+
+ protected void setAdapterClass(Class adapterClass) {
+ this.adapterClass = adapterClass;
+ }
+ public void setAdaptTo(String adaptTo) {
+ this.adaptTo = adaptTo;
+ }
+
+ protected void setAdaptToClass(Class adaptToClass) {
+ this.adaptToClass = adaptToClass;
+ }
+
+ protected void setInternalClassLoader(ClassLoader classLoader) {
+ this.internalClassLoader = classLoader;
+ }
+
/**
* @see org.apache.tools.ant.Task#init()
* @since Ant 1.6
@@ -326,4 +416,67 @@
super.init();
}
+ protected void addDefinition(ClassLoader al, String name, String
classname)
+ throws BuildException
+ {
+ Class cl = null;
+ try {
+ try {
+ if (onError != OnError.IGNORE) {
+ cl = al.loadClass(classname);
+ AntClassLoader.initializeClass(cl);
+ }
+
+ if (adapter != null) {
+ adapterClass = al.loadClass(adapter);
+ AntClassLoader.initializeClass(adapterClass);
+ }
+
+ if (adaptTo != null) {
+ adaptToClass = al.loadClass(adaptTo);
+ AntClassLoader.initializeClass(adaptToClass);
+ }
+
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setName(name);
+ def.setProject(getProject());
+ def.setClassName(classname);
+ def.setClass(cl);
+ def.setAdapterClass(adapterClass);
+ def.setAdaptToClass(adaptToClass);
+ def.setClassLoader(al);
+ if (cl != null) {
+ def.checkClass();
+ }
+ ComponentHelper.getComponentHelper(getProject())
+ .addDataTypeDefinition(def);
+ } catch (ClassNotFoundException cnfe) {
+ String msg = getTaskName() + " class " + classname
+ + " cannot be found";
+ throw new BuildException(msg, cnfe, getLocation());
+ } catch (NoClassDefFoundError ncdfe) {
+ String msg = getTaskName() + "A class needed by class "
+ + classname + " cannot be found: " + ncdfe.getMessage();
+ throw new BuildException(msg, ncdfe, location);
+ }
+ } catch (BuildException ex) {
+ switch (onError) {
+ case OnError.FAIL:
+ throw ex;
+ case OnError.REPORT:
+ log(ex.getLocation() + "Warning: " + ex.getMessage(),
+ Project.MSG_WARN);
+ break;
+ default:
+ log(ex.getLocation() + ex.getMessage(),
+ Project.MSG_DEBUG);
+ }
+ }
+ }
+
+ private void tooManyDefinitions() {
+ throw new BuildException(
+ "Only one of the attributes name,file,resource" +
+ " can be set", getLocation());
+ }
}
1.27 +8 -9 ant/src/main/org/apache/tools/ant/taskdefs/Taskdef.java
Index: Taskdef.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Taskdef.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- Taskdef.java 7 Mar 2003 11:23:02 -0000 1.26
+++ Taskdef.java 26 Jun 2003 08:54:29 -0000 1.27
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,8 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskAdapter;
/**
* Adds a task definition to the current project, such that this new task
can be
@@ -72,13 +74,10 @@
* @since Ant 1.1
* @ant.task category="internal"
*/
-public class Taskdef extends Definer {
-
- /**
- * subclassed handler for definitions; called by parent during
- * execution.
- */
- protected void addDefinition(String name, Class c) throws BuildException
{
- getProject().addTaskDefinition(name, c);
+public class Taskdef extends Typedef {
+
+ public Taskdef() {
+ setAdapterClass(TaskAdapter.class);
+ setAdaptToClass(Task.class);
}
}
1.17 +6 -5 ant/src/testcases/org/apache/tools/ant/ProjectTest.java
Index: ProjectTest.java
===================================================================
RCS file: /home/cvs/ant/src/testcases/org/apache/tools/ant/ProjectTest.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- ProjectTest.java 7 Mar 2003 11:23:10 -0000 1.16
+++ ProjectTest.java 26 Jun 2003 08:54:29 -0000 1.17
@@ -183,9 +183,9 @@
p.addBuildListener(mbl);
p.addTaskDefinition("Ok", DummyTaskOk.class);
- assertEquals(DummyTaskOk.class, p.getTaskDefinitions().get("Ok"));
+ assertEquals(DummyTaskOk.class,
p.getDataTypeDefinitions().get("Ok"));
p.addTaskDefinition("OkNonTask", DummyTaskOkNonTask.class);
- assertEquals(DummyTaskOkNonTask.class,
p.getTaskDefinitions().get("OkNonTask"));
+ assertEquals(DummyTaskOkNonTask.class,
p.getDataTypeDefinitions().get("OkNonTask"));
mbl.assertEmpty();
assertTaskDefFails(DummyTaskPrivate.class, DummyTaskPrivate.class
+ " is not public");
@@ -220,7 +220,7 @@
mbl.addBuildEvent("return type of execute() should be void but was
\"int\" in " + DummyTaskWithNonVoidExecute.class, Project.MSG_WARN);
p.addTaskDefinition("NonVoidExecute",
DummyTaskWithNonVoidExecute.class);
mbl.assertEmpty();
- assertEquals(DummyTaskWithNonVoidExecute.class,
p.getTaskDefinitions().get("NonVoidExecute"));
+ assertEquals(DummyTaskWithNonVoidExecute.class,
p.getDataTypeDefinitions().get("NonVoidExecute"));
}
public void testInputHandler() {
@@ -233,11 +233,12 @@
}
public void testTaskDefinitionContainsKey() {
- assertTrue(p.getTaskDefinitions().containsKey("echo"));
+ assertTrue(p.getDataTypeDefinitions().containsKey("echo"));
}
public void testTaskDefinitionContains() {
-
assertTrue(p.getTaskDefinitions().contains(org.apache.tools.ant.taskdefs.Echo.class));
+ assertTrue(p.getDataTypeDefinitions()
+ .contains(org.apache.tools.ant.taskdefs.Echo.class));
}
private class DummyTaskPrivate extends Task {
1.1
ant/src/testcases/org/apache/tools/ant/taskdefs/TypeAdapterTest.java
Index: TypeAdapterTest.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Ant" and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.taskdefs;
import java.lang.reflect.Method;
import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TypeAdapter;
/**
* @author Peter Reilly
*/
public class TypeAdapterTest extends BuildFileTest {
public TypeAdapterTest(String name) {
super(name);
}
public void setUp() {
configureProject("src/etc/testcases/taskdefs/typeadapter.xml");
}
public void testTaskAdapter() {
expectLogContaining("taskadapter", "MyExec called");
}
public void testRunAdapter() {
expectLogContaining("runadapter", "MyRunnable called");
}
public void testRunAdapterError() {
expectBuildExceptionContaining(
"runadaptererror", "xx", "No public run() method in");
}
public void testDelay() {
expectLogContaining("delay", "MyTask called");
}
public void testOnErrorReport() {
expectLogContaining("onerror.report",
"MyTaskNotPresent cannot be found");
}
public void testOnErrorIgnore() {
expectLog("onerror.ignore","");
}
public static class MyTask extends Task {
public void execute() {
log("MyTask called");
}
}
public static class MyExec {
private Project project;
public void setProject(Project project) {
this.project = project;
}
public void execute() {
project.log("MyExec called");
}
}
public static class MyRunnable {
private Project project;
public void setProject(Project project) {
this.project = project;
}
public void run() {
project.log("MyRunnable called");
}
}
public static class RunnableAdapter
extends Task implements TypeAdapter
{
private String execMethodName = "run";
private Object proxy;
public Method getExecuteMethod(Class proxyClass) {
try {
Method execMethod = proxyClass.getMethod(
execMethodName, null);
if (!Void.TYPE.equals(execMethod.getReturnType())) {
String message =
"return type of " + execMethodName + "() should be "
+ "void but was \"" + execMethod.getReturnType() +
"\" in "
+ proxyClass;
log(message, Project.MSG_WARN);
}
return execMethod;
} catch (NoSuchMethodException e) {
String message = "No public "+ execMethodName +
"() method in "
+ proxyClass;
log(message, Project.MSG_ERR);
throw new BuildException(message);
}
}
public void checkProxyClass(Class proxyClass) {
getExecuteMethod(proxyClass);
}
public void setProxy(Object o) {
getExecuteMethod(o.getClass());
this.proxy = o;
}
public Object getProxy() {
return proxy;
}
public void execute() {
getProject().setProjectReference(proxy);
Method executeMethod = getExecuteMethod(proxy.getClass());
try {
executeMethod.invoke(proxy, null);
} catch (java.lang.reflect.InvocationTargetException ie) {
log("Error in " + proxy.getClass(), Project.MSG_ERR);
Throwable t = ie.getTargetException();
if (t instanceof BuildException) {
throw ((BuildException) t);
} else {
throw new BuildException(t);
}
} catch (Exception ex) {
log("Error in " + proxy.getClass(), Project.MSG_ERR);
throw new BuildException(ex);
}
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]