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 
&quot;<a
  -href="../develop.html#writingowntask">Writing your own task</a>&quot;.</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>  &lt;taskdef name=&quot;myjavadoc&quot; 
classname=&quot;com.mydomain.JavadocTask&quot;/&gt;</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 &copy; 2000-2002 Apache Software Foundation. All 
rights
  +<p align="center">Copyright &copy; 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>  &lt;typedef name=&quot;urlset&quot; 
classname=&quot;com.mydomain.URLSet&quot;/&gt;</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 &copy; 2001-2002 Apache Software
  +<p align="center">Copyright &copy; 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 &lttypedef/&gt 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]

Reply via email to