diff --git a/src/etc/testcases/types/addtype.xml b/src/etc/testcases/types/addtype.xml
new file mode 100644
index 000000000..88d93eb80
--- /dev/null
+++ b/src/etc/testcases/types/addtype.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is line 1
+ This is line 2
+ This is line 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ before
+
+ after
+
+
+ before
+
+ after
+
+
+
+
+
+
+
+ >
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/ComponentHelper.java b/src/main/org/apache/tools/ant/ComponentHelper.java
index 05ec724e9..574a7a05e 100644
--- a/src/main/org/apache/tools/ant/ComponentHelper.java
+++ b/src/main/org/apache/tools/ant/ComponentHelper.java
@@ -161,6 +161,41 @@ public class ComponentHelper {
return component;
}
+ /**
+ * get the class of a particular component
+ */
+ 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);
+ }
+
+ /**
+ * create a named component
+ */
+ 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;
+ }
+
/** Initialization code - implementing the original ant component
* loading from /org/apache/tools/ant/taskdefs/default.properties
* and .../types/default.properties
diff --git a/src/main/org/apache/tools/ant/IntrospectionHelper.java b/src/main/org/apache/tools/ant/IntrospectionHelper.java
index 93ee07751..b8dd4d1e2 100644
--- a/src/main/org/apache/tools/ant/IntrospectionHelper.java
+++ b/src/main/org/apache/tools/ant/IntrospectionHelper.java
@@ -58,8 +58,10 @@ import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.List;
import java.util.Locale;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Path;
@@ -97,6 +99,11 @@ public class IntrospectionHelper implements BuildListener {
*/
private Hashtable nestedCreators;
+ /**
+ * Vector of methods matching add[Configured](Class) pattern
+ */
+ private List addTypeMethods;
+
/**
* Map from attribute names to methods to store configured nested types
* (String to NestedStorer).
@@ -199,6 +206,7 @@ public class IntrospectionHelper implements BuildListener {
nestedTypes = new Hashtable();
nestedCreators = new Hashtable();
nestedStorers = new Hashtable();
+ addTypeMethods = new ArrayList();
this.bean = bean;
@@ -209,6 +217,14 @@ public class IntrospectionHelper implements BuildListener {
Class returnType = m.getReturnType();
Class[] args = m.getParameterTypes();
+ // check of add[Configured](Class) pattern
+ if (args.length == 1
+ && java.lang.Void.TYPE.equals(returnType)
+ && (name.equals("add") /*|| name.equals("addConfigured")*/)) {
+ insertAddTypeMethod(m);
+ continue;
+ }
+
// not really user settable properties on tasks
if (org.apache.tools.ant.Task.class.isAssignableFrom(bean)
&& args.length == 1 && isHiddenSetMethod(name, args[0])) {
@@ -534,6 +550,16 @@ public class IntrospectionHelper implements BuildListener {
public Object createElement(Project project, Object parent,
String elementName) throws BuildException {
NestedCreator nc = (NestedCreator) nestedCreators.get(elementName);
+ if (nc == null && addTypeMethods.size() > 0) {
+ Object nestedElement = createAddTypeElement(
+ project, parent, elementName);
+ if (nestedElement != null) {
+ if (project != null) {
+ project.setProjectReference(nestedElement);
+ }
+ return nestedElement;
+ }
+ }
if (nc == null && parent instanceof DynamicConfigurator) {
DynamicConfigurator dc = (DynamicConfigurator) parent;
Object nestedElement = dc.createDynamicElement(elementName);
@@ -578,7 +604,8 @@ public class IntrospectionHelper implements BuildListener {
*/
public boolean supportsNestedElement(String elementName) {
return nestedCreators.containsKey(elementName) ||
- DynamicConfigurator.class.isAssignableFrom(bean);
+ DynamicConfigurator.class.isAssignableFrom(bean) ||
+ addTypeMethods.size() != 0;
}
/**
@@ -978,4 +1005,102 @@ public class IntrospectionHelper implements BuildListener {
* @param event Ignored in this implementation.
*/
public void messageLogged(BuildEvent event) {}
+
+ /**
+ * Check if the parent accepts a typed nested element
+ * and if so, create the object, call the parents
+ * addmethod.
+ * This method is part of the initial support
+ * for add(Type) and addConfigured(Type).
+ * AddConfigured(Type) will be done later.
+ */
+
+ private Object createAddTypeElement(
+ Project project, Object parent, String elementName)
+ {
+ ComponentHelper helper = ComponentHelper.getComponentHelper(project);
+ Object addedObject = null;
+ Method addMethod = null;
+
+ Class clazz = helper.getComponentClass(elementName);
+ if (clazz == null) {
+ return null;
+ }
+ addMethod = findMatchingMethod(clazz, addTypeMethods);
+ if (addMethod == null) {
+ return null;
+ }
+ addedObject = helper.createComponent(elementName);
+ if (addedObject == null) {
+ return null;
+ }
+
+ try {
+ addMethod.invoke(parent, new Object[] {addedObject});
+ } catch (IllegalAccessException ex) {
+ throw new BuildException(ex);
+ } catch (InvocationTargetException ex) {
+ Throwable t = ex.getTargetException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(t);
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ return addedObject;
+ }
+
+ /**
+ * Inserts an add or addConfigured method into
+ * the addTypeMethods array. The array is
+ * ordered so that the more derived classes
+ * are first.
+ */
+
+ private void insertAddTypeMethod(Method method) {
+ Class argClass = method.getParameterTypes()[0];
+ for (int c = 0; c < addTypeMethods.size(); ++c) {
+ Method current = (Method) addTypeMethods.get(c);
+ if (current.getParameterTypes()[0].equals(argClass)) {
+ return; // Already present
+ }
+ if (current.getParameterTypes()[0].isAssignableFrom(
+ argClass)) {
+ addTypeMethods.add(c, method);
+ return; // higher derived
+ }
+ }
+ addTypeMethods.add(method);
+ }
+
+
+ /**
+ * Search the list of methods to find the first method
+ * that has a parameter that accepts the nested element object
+ */
+ private Method findMatchingMethod(Class paramClass, List methods) {
+ Class matchedClass = null;
+ Method matchedMethod = null;
+
+ for (int i = 0; i < methods.size(); ++i) {
+ Method method = (Method) methods.get(i);
+ Class methodClass = method.getParameterTypes()[0];
+ if (methodClass.isAssignableFrom(paramClass)) {
+ if (matchedClass == null) {
+ matchedClass = methodClass;
+ matchedMethod = method;
+ } else {
+ if (! methodClass.isAssignableFrom(matchedClass)) {
+ throw new BuildException(
+ "ambiguous: types " + matchedClass.getName() +
+ " and " + methodClass.getName() +
+ " match " + paramClass.getName());
+ }
+ }
+ }
+ }
+ return matchedMethod;
+ }
+
}
diff --git a/src/main/org/apache/tools/ant/filters/TokenFilter.java b/src/main/org/apache/tools/ant/filters/TokenFilter.java
index 27d0a307d..ec1e35afb 100644
--- a/src/main/org/apache/tools/ant/filters/TokenFilter.java
+++ b/src/main/org/apache/tools/ant/filters/TokenFilter.java
@@ -59,8 +59,8 @@ import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DynamicConfigurator;
import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Parameter;
import org.apache.tools.ant.types.RegularExpression;
@@ -80,7 +80,7 @@ import org.apache.tools.ant.util.regexp.Regexp;
*/
public class TokenFilter
extends BaseFilterReader
- implements ChainableReader, DynamicConfigurator
+ implements ChainableReader
{
/**
* input stream tokenizers implement this interface
@@ -229,9 +229,7 @@ public class TokenFilter
*/
public void addLineTokenizer(LineTokenizer tokenizer) {
- if (this.tokenizer != null)
- throw new BuildException("Only one tokenizer allowed");
- this.tokenizer = tokenizer;
+ add(tokenizer);
}
/**
@@ -239,21 +237,26 @@ public class TokenFilter
*/
public void addStringTokenizer(StringTokenizer tokenizer) {
- if (this.tokenizer != null)
- throw new BuildException("Only one tokenizer allowed");
- this.tokenizer = tokenizer;
+ add(tokenizer);
}
/**
* add a file tokenizer
*/
public void addFileTokenizer(FileTokenizer tokenizer) {
+ add(tokenizer);
+ }
+
+ /**
+ * add a tokenizer
+ */
+
+ public void add(Tokenizer tokenizer) {
if (this.tokenizer != null)
throw new BuildException("Only one tokenizer allowed");
this.tokenizer = tokenizer;
}
-
-
+
// -----------------------------------------
// Predefined filters
// -----------------------------------------
@@ -297,48 +300,7 @@ public class TokenFilter
filters.addElement(filter);
}
- /**
- * create the named datatype and check if it
- * is a filter or a tokenizer
- *
- * @throws BuildException if unknown datatype or incorrect datatype
- */
-
- public Object createDynamicElement(String name)
- {
- if (getProject() == null)
- throw new BuildException(
- "createDynamicElement.TokenFilter" +
- " - Unable to get the project");
-
- Object obj = getProject().createDataType(name);
- if (obj == null)
- throw new BuildException("Unknown type " + name);
- if (obj instanceof Filter)
- filters.addElement(obj);
- else if (obj instanceof Tokenizer) {
- if (this.tokenizer != null)
- throw new BuildException("Only one tokenizer allowed");
- tokenizer = (Tokenizer) obj;
- }
- else
- throw new BuildException(
- "type " + name + " is not a TokenFilter.Filter or " +
- "TokenFiler.Tokenizer");
- return obj;
- }
-
-
- /**
- * Needed for dynamic element support.
- *
- * @throws BuildException always
- */
-
- public void setDynamicAttribute(String name, String value) {
- throw new BuildException("Unknown attribute " + name);
- }
-
+
// --------------------------------------------
//
// Tokenizer Classes
@@ -349,6 +311,7 @@ public class TokenFilter
* class to read the complete input into a string
*/
public static class FileTokenizer
+ extends ProjectComponent
implements Tokenizer
{
/**
@@ -378,6 +341,7 @@ public class TokenFilter
* by \r (mac style), \r\n (dos/windows style) or \n (unix style)
*/
public static class LineTokenizer
+ extends ProjectComponent
implements Tokenizer
{
private String lineEnd = "";
@@ -466,6 +430,7 @@ public class TokenFilter
* as delims flag is set).
*/
public static class StringTokenizer
+ extends ProjectComponent
implements Tokenizer
{
private String intraString = "";
@@ -585,6 +550,7 @@ public class TokenFilter
// --------------------------------------------
public static abstract class ChainableReaderFilter
+ extends ProjectComponent
implements ChainableReader, Filter
{
private boolean byLine = true;
@@ -596,7 +562,7 @@ public class TokenFilter
public Reader chain(Reader reader) {
TokenFilter tokenFilter = new TokenFilter(reader);
if (!byLine)
- tokenFilter.addFileTokenizer(new FileTokenizer());
+ tokenFilter.add(new FileTokenizer());
tokenFilter.add(this);
return tokenFilter;
}
@@ -656,6 +622,7 @@ public class TokenFilter
* Simple filter to filter lines contains strings
*/
public static class ContainsString
+ extends ProjectComponent
implements Filter
{
private String contains;
@@ -818,6 +785,7 @@ public class TokenFilter
* Filter to delete characters
*/
public static class DeleteCharacters
+ extends ProjectComponent
implements Filter, ChainableReader
{
// Attributes
diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java
index 9200043d4..93c373842 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Delete.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java
@@ -76,6 +76,7 @@ import org.apache.tools.ant.types.selectors.OrSelector;
import org.apache.tools.ant.types.selectors.PresentSelector;
import org.apache.tools.ant.types.selectors.SelectSelector;
import org.apache.tools.ant.types.selectors.SizeSelector;
+import org.apache.tools.ant.types.selectors.FileSelector;
/**
* Deletes a file or directory, or set of files defined by a fileset.
@@ -418,6 +419,15 @@ public class Delete extends MatchingTask {
super.addContainsRegexp(selector);
}
+ /**
+ * add an arbitary selector
+ * @since Ant 1.6
+ */
+ public void add(FileSelector selector) {
+ usedMatchingTask = true;
+ super.add(selector);
+ }
+
/**
* Delete the file(s).
*/
diff --git a/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java b/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java
index b7f72962b..a52d6a5ef 100644
--- a/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/MatchingTask.java
@@ -426,6 +426,7 @@ public abstract class MatchingTask extends Task implements SelectorContainer {
public void addDifferent(DifferentSelector selector) {
fileset.addDifferent(selector);
}
+
/**
* add a type selector entry on the type list
* @param selector
@@ -435,6 +436,14 @@ public abstract class MatchingTask extends Task implements SelectorContainer {
fileset.addType(selector);
}
+ /**
+ * add an arbitary selector
+ * @since Ant 1.6
+ */
+ public void add(FileSelector selector) {
+ fileset.add(selector);
+ }
+
/**
* Accessor for the implict fileset.
*
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java b/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
index b05967e8e..092b32352 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2001-2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -203,4 +203,10 @@ public abstract class ConditionBase extends ProjectComponent {
*/
public void addIsReference(IsReference i) {conditions.addElement(i);}
+ /**
+ * Add an arbitary condition
+ * @since Ant 1.6
+ */
+ public void add(Condition c) {conditions.addElement(c);}
+
}
diff --git a/src/main/org/apache/tools/ant/types/AbstractFileSet.java b/src/main/org/apache/tools/ant/types/AbstractFileSet.java
index 56fccb58c..f4c82f65b 100644
--- a/src/main/org/apache/tools/ant/types/AbstractFileSet.java
+++ b/src/main/org/apache/tools/ant/types/AbstractFileSet.java
@@ -649,6 +649,14 @@ public abstract class AbstractFileSet extends DataType implements Cloneable,
appendSelector(selector);
}
+ /**
+ * add an arbitary selector
+ * @since Ant 1.6
+ */
+ public void add(FileSelector selector) {
+ appendSelector(selector);
+ }
+
/**
* Returns included files as a list of semicolon-separated filenames
*
diff --git a/src/main/org/apache/tools/ant/types/FilterChain.java b/src/main/org/apache/tools/ant/types/FilterChain.java
index 321b15245..fa2cfac5c 100644
--- a/src/main/org/apache/tools/ant/types/FilterChain.java
+++ b/src/main/org/apache/tools/ant/types/FilterChain.java
@@ -59,7 +59,6 @@ import java.io.Reader;
import java.io.IOException;
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DynamicConfigurator;
import org.apache.tools.ant.filters.ChainableReader;
import org.apache.tools.ant.filters.ClassConstants;
import org.apache.tools.ant.filters.EscapeUnicode;
@@ -85,7 +84,7 @@ import org.apache.tools.ant.taskdefs.Concat;
* @author Magesh Umasankar
*/
public final class FilterChain extends DataType
- implements Cloneable, DynamicConfigurator
+ implements Cloneable
{
private Vector filterReaders = new Vector();
@@ -246,38 +245,14 @@ public final class FilterChain extends DataType
super.setRefid(r);
}
-
+
/**
- * create the named datatype and check if it
- * is a filter.
- *
- * @throws BuildException if unknown datatype or incorrect datatype
+ * add a chainfilter
* @since Ant 1.6
*/
-
- public Object createDynamicElement(String name)
- {
- if (getProject() == null)
- throw new BuildException("Unable to get the project");
-
- Object obj = getProject().createDataType(name);
- if (obj == null)
- throw new BuildException("Unknown type " + name);
- if (! (obj instanceof ChainableReader))
- throw new BuildException(
- "type " + name + " is not a filterreader");
- filterReaders.addElement(obj);
- return obj;
- }
- /**
- * Needed for dynamic element support.
- *
- * @throws BuildException always
- */
-
- public void setDynamicAttribute(String name, String value) {
- throw new BuildException("Unknown attribute " + name);
+ public void add(ChainableReader filter) {
+ filterReaders.addElement(filter);
}
}
diff --git a/src/main/org/apache/tools/ant/types/Path.java b/src/main/org/apache/tools/ant/types/Path.java
index 6b7e6dccd..0516e3aea 100644
--- a/src/main/org/apache/tools/ant/types/Path.java
+++ b/src/main/org/apache/tools/ant/types/Path.java
@@ -220,6 +220,19 @@ public class Path extends DataType implements Cloneable {
setChecked( false );
}
+ /**
+ * Adds a nested path
+ * @since Ant 1.6
+ */
+ public void add(Path path) throws BuildException {
+ if (isReference()) {
+ throw noChildrenAllowed();
+ }
+ elements.addElement(path);
+ setChecked( false );
+
+ }
+
/**
* Creates a nested <path>
element.
*/
diff --git a/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java b/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java
index b08618ee8..adf14f63b 100644
--- a/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java
+++ b/src/main/org/apache/tools/ant/types/optional/ScriptFilter.java
@@ -79,8 +79,6 @@ import org.apache.tools.ant.Task;
public class ScriptFilter
extends TokenFilter.ChainableReaderFilter
{
- /** The current project - set by ant reflection */
- private Project project;
/** The language - attribute of element */
private String language;
/** The script - inline text or external file */
@@ -94,16 +92,6 @@ public class ScriptFilter
/** the token used by the script */
private String token;
- /** Called by ant reflection to set the project */
- public void setProject(Project project) {
- this.project = project;
- }
-
- /** this is provided to allow easier CAP from the ScriptTask */
- private Project getProject() {
- return project;
- }
-
/**
* Defines the language (required).
*
diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
index 81ab28937..479b4638e 100644
--- a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
@@ -305,5 +305,14 @@ public abstract class BaseSelectorContainer extends BaseSelector
appendSelector(selector);
}
+
+ /**
+ * add an arbitary selector
+ * @since Ant 1.6
+ */
+ public void add(FileSelector selector) {
+ appendSelector(selector);
+ }
+
}
diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
index 07b4b64d9..bbbf28a86 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
@@ -189,5 +189,11 @@ public interface SelectorContainer {
* @since ant 1.6
*/
public void addDifferent(DifferentSelector selector);
+
+ /**
+ * add an arbitary selector
+ * @since Ant 1.6
+ */
+ public void add(FileSelector selector);
}
diff --git a/src/testcases/org/apache/tools/ant/types/AddTypeTest.java b/src/testcases/org/apache/tools/ant/types/AddTypeTest.java
new file mode 100644
index 000000000..60ede5971
--- /dev/null
+++ b/src/testcases/org/apache/tools/ant/types/AddTypeTest.java
@@ -0,0 +1,164 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 apache@apache.org.
+ *
+ * 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
+ * .
+ */
+
+package org.apache.tools.ant.types;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileTest;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.condition.Condition;
+
+public class AddTypeTest extends BuildFileTest {
+
+ public AddTypeTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("src/etc/testcases/types/addtype.xml");
+ }
+
+ public void testAddPath() {
+ executeTarget("addpath");
+ }
+
+ public void testAddCondition() {
+ executeTarget("addcondition");
+ }
+
+ public void testAddFilter() {
+ executeTarget("addfilter");
+ }
+
+ public void testAddSelector() {
+ executeTarget("addselector");
+ }
+
+ public void testNestedA() {
+ expectLogContaining("nested.a", "add A called");
+ }
+
+ public void testNestedB() {
+ expectLogContaining("nested.b", "add B called");
+ }
+
+ public void testNestedC() {
+ expectLogContaining("nested.c", "add C called");
+ }
+
+ public void testNestedAB() {
+ expectBuildExceptionContaining(
+ "nested.ab", "Should have got ambiguous", "ambiguous");
+ }
+
+ public void testConditionType() {
+ expectLogContaining("condition.type", "beforeafter");
+ }
+
+ public void testConditionTask() {
+ expectLogContaining("condition.task", "My Condition execution");
+ }
+ public void testConditionConditionType() {
+ expectLogContaining("condition.condition.type", "My Condition eval");
+ }
+ public void testConditionConditionTask() {
+ expectBuildExceptionContaining(
+ "condition.condition.task", "task masking condition",
+ "doesn't support the nested");
+ }
+
+ // The following will be used as types and tasks
+
+ public static interface A {}
+ public static interface B {}
+ public static interface C extends A {}
+ public static interface AB extends A, B {}
+
+ public static class AImpl implements A{}
+ public static class BImpl implements B{}
+ public static class CImpl implements C{}
+ public static class ABImpl implements AB{}
+
+ public static class NestedContainer
+ extends Task
+ {
+ public void add(A el) {
+ log("add A called");
+ }
+ public void add(B el) {
+ log("add B called");
+ }
+ public void add(C el) {
+ log("add C called");
+ }
+ }
+
+ public static class MyCondition
+ implements Condition
+ {
+ Project project;
+ public void setProject(Project project) {
+ this.project = project;
+ }
+ public boolean eval() {
+ project.log("My Condition eval");
+ return true;
+ }
+ public void execute() {
+ project.log("My Condition execution");
+ }
+ }
+
+}