Index: src/main/org/apache/tools/ant/IntrospectionHelper.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/IntrospectionHelper.java,v
retrieving revision 1.44
diff -u -w -r1.44 IntrospectionHelper.java
--- src/main/org/apache/tools/ant/IntrospectionHelper.java      25 Jul 2002 15:21:01 -0000      1.44
+++ src/main/org/apache/tools/ant/IntrospectionHelper.java      26 Nov 2002 19:56:54 -0000
@@ -98,7 +98,11 @@
     private Hashtable nestedCreators;
 
     /**
-     * Map from attribute names to methods to store configured nested types 
+     * Holds methods to add nested elements;
+     */
+    private Hashtable nestedAdders;
+
+    /**     * Map from attribute names to methods to store configured nested types
      * (String to NestedStorer).
      */
     private Hashtable nestedStorers;
@@ -198,6 +202,7 @@
         attributeSetters = new Hashtable();
         nestedTypes = new Hashtable();
         nestedCreators = new Hashtable();
+        nestedAdders = new Hashtable();
         nestedStorers = new Hashtable();
 
         this.bean = bean;
@@ -294,7 +299,7 @@
                         args[0].getConstructor(new Class[] {});
                     String propName = getPropertyName(name, "addConfigured");
                     nestedTypes.put(propName, args[0]);
-                    nestedCreators.put(propName, new NestedCreator() {
+                    nestedAdders.put(propName, new NestedCreator() {
 
                             public Object create(Object parent)
                                 throws InvocationTargetException, IllegalAccessException, InstantiationException {
@@ -327,7 +332,7 @@
                         args[0].getConstructor(new Class[] {});
                     String propName = getPropertyName(name, "add");
                     nestedTypes.put(propName, args[0]);
-                    nestedCreators.put(propName, new NestedCreator() {
+                    nestedAdders.put(propName, new NestedCreator() {
 
                             public Object create(Object parent)
                                 throws InvocationTargetException, IllegalAccessException, InstantiationException {
@@ -514,6 +519,12 @@
             }
         }
         if (nc == null) {
+            nc = (NestedCreator) nestedAdders.get( elementName );
+        }
+        if ( nc == null ) {
+            nc = getPolymorphicTypeCreator( project, elementName );
+        }
+        if (nc == null) {
             String msg = project.getElementName(parent) +
                 " doesn't support the nested \"" + elementName + "\" element.";
             throw new BuildException(msg);
@@ -539,6 +550,63 @@
         }
     }
 
+
+    private final NestedCreator getPolymorphicTypeCreator(
+        final Project project, final String elementName ) {
+
+        // Is this a type?
+        final Hashtable typeDefs = project.getDataTypeDefinitions();
+        if ( typeDefs.containsKey( elementName ) ) {
+            // OK it is a defined type
+            final Class typeClass = (Class)typeDefs.get( elementName );
+
+            final Method[] methods = bean.getMethods();
+            if ( methods != null ) {
+                for ( int i = 0; i < methods.length; i++ ) {
+                    final Method m = methods[i];
+                    final String name = m.getName();
+                    String propName = null;
+                    if ( name.startsWith( "add" ) ) {
+                        final Class[] params = m.getParameterTypes();
+                        if ( params != null && params.length == 1 ) {
+                            if ( params[0].isAssignableFrom( typeClass ) ) {
+                                String paramClassName = params[0].getName();
+                                if ( paramClassName.lastIndexOf('.') > 0) {
+                                    paramClassName = paramClassName.substring(
+                                        paramClassName.lastIndexOf('.') + 1 );
+                                }
+                                if ( name.startsWith( "addConfigured" ) ) {
+                                    propName = getPropertyName(name, "addConfigured");
+                                } else {
+                                    propName = getPropertyName(name, "add");
+                                }
+                                if ( paramClassName.equalsIgnoreCase( propName ) ) {
+                                    try {
+                                        final Constructor c =
+                                            typeClass.getConstructor( new Class[] {} );
+                                        return new NestedCreator() {
+                                            public Object create( Object parent )
+                                                throws InvocationTargetException,
+                                                       IllegalAccessException,
+                                                       InstantiationException {
+                                                    Object o = c.newInstance( new Object[] {} );
+                                                    m.invoke( parent, new Object[] {o} );
+                                                    return o;
+                                            }
+                                        };
+                                    }
+                                    catch ( final NoSuchMethodException nse ) {
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     /**
      * Stores a named nested element using a storage method determined
      * by the initial introspection. If no appropriate storage method
@@ -884,6 +952,8 @@
         attributeSetters.clear();
         nestedTypes.clear();
         nestedCreators.clear();
+        nestedStorers.clear();
+        nestedAdders.clear();
         addText = null;
         helpers.clear();
     }
Index: src/main/org/apache/tools/ant/Project.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/Project.java,v
retrieving revision 1.116
diff -u -w -r1.116 Project.java
--- src/main/org/apache/tools/ant/Project.java  10 Sep 2002 22:21:18 -0000      1.116
+++ src/main/org/apache/tools/ant/Project.java  26 Nov 2002 19:56:55 -0000
@@ -56,6 +56,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.FileInputStream;
 import java.io.InputStream;
 import java.lang.reflect.Modifier;
 import java.util.Enumeration;
@@ -249,6 +250,62 @@
      */
     public void init() throws BuildException {
         setJavaVersionProperty();
+        final String customTypes = System.getProperty("ant.custom.types");
+        final String customTasks = System.getProperty("ant.custom.tasks");
+
+        if ( customTasks != null ) {
+            try {
+                Properties props = new Properties();
+                InputStream in = new FileInputStream( customTasks );
+                if (in != null) {
+                    props.load(in);
+                    in.close();
+
+                    Enumeration enum = props.propertyNames();
+                    while (enum.hasMoreElements()) {
+                        String key = (String) enum.nextElement();
+                        String value = props.getProperty(key);
+                        try {
+                            Class taskClass = Class.forName(value);
+                            addTaskDefinition(key, taskClass);
+                        } catch (NoClassDefFoundError ncdfe) {
+                            log("Could not load a dependent class ("
+                                + ncdfe.getMessage() + ") for task " + key, MSG_DEBUG);
+                        } catch (ClassNotFoundException cnfe) {
+                            log("Could not load class (" + value
+                                + ") for task " + key, MSG_DEBUG);
+                        }
+                    }
+                }
+            } catch (IOException ioe) {
+            }
+        }
+
+        if ( customTypes != null ) {
+            try {
+                Properties props = new Properties();
+                InputStream in = new FileInputStream( customTypes );
+                if (in != null) {
+                    props.load(in);
+                    in.close();
+
+                    Enumeration enum = props.propertyNames();
+                    while (enum.hasMoreElements()) {
+                        String key = (String) enum.nextElement();
+                        String value = props.getProperty(key);
+                        try {
+                            Class dataClass = Class.forName(value);
+                            addDataTypeDefinition(key, dataClass);
+                        } catch (NoClassDefFoundError ncdfe) {
+                            // ignore...
+                        } catch (ClassNotFoundException cnfe) {
+                            // ignore...
+                        }
+                    }
+                }
+            } catch (IOException ioe) {
+            }
+        }
 
         String defs = "/org/apache/tools/ant/taskdefs/defaults.properties";
Index: src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
===================================================================
RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java,v
retrieving revision 1.16
diff -u -w -r1.16 ConditionBase.java
--- src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java 9 Sep 2002 08:21:39 -0000       1.16
+++ src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java 26 Nov 2002 19:56:55 -0000
@@ -203,4 +203,12 @@
      */
     public void addIsReference(IsReference i) {conditions.addElement(i);}
 
+    /**
+     * Add a condition.
+     *
+     * @since Ant 1.6
+     */
+    public final void addCondition( final Condition c ) {
+        conditions.addElement( c );
+    }
 }

