@@ -0,0 +1,115 @@ | |||||
<project name="test" basedir="."> | |||||
<target name="addpath"> | |||||
<typedef name="mypath" classname="org.apache.tools.ant.types.Path"/> | |||||
<path> | |||||
<mypath path="build.xml"/> | |||||
</path> | |||||
</target> | |||||
<target name="addcondition"> | |||||
<typedef name="mycondition" | |||||
classname="org.apache.tools.ant.taskdefs.condition.Equals"/> | |||||
<condition property="mycondition.set"> | |||||
<mycondition arg1="string" arg2="string"/> | |||||
</condition> | |||||
<fail unless="mycondition.set"/> | |||||
</target> | |||||
<target name="addfilter"> | |||||
<typedef name="headfilter2" | |||||
classname="org.apache.tools.ant.filters.HeadFilter"/> | |||||
<concat>This is line 1 | |||||
This is line 2 | |||||
This is line 3 | |||||
<filterchain> | |||||
<headfilter2 lines="2"/> | |||||
</filterchain> | |||||
</concat> | |||||
</target> | |||||
<target name="addselector"> | |||||
<typedef | |||||
name="myselector" | |||||
classname="org.apache.tools.ant.types.selectors.ContainsSelector"/> | |||||
<fileset id="myselector.test" dir="${basedir}" includes="*"> | |||||
<myselector text="myselector"/> | |||||
</fileset> | |||||
</target> | |||||
<target name="init"> | |||||
<property name="nested.package" value="org.apache.tools.ant.types."/> | |||||
<path id="test-classes"> | |||||
<pathelement location="../../../../build/testcases" /> | |||||
<pathelement path="${java.class.path}" /> | |||||
</path> | |||||
<typedef loaderref="nested.loader" classpathref="test-classes" | |||||
name = "nested.a" | |||||
classname="${nested.package}AddTypeTest$AImpl"/> | |||||
<typedef loaderref="nested.loader" classpathref="test-classes" | |||||
name = "nested.b" | |||||
classname="${nested.package}AddTypeTest$BImpl"/> | |||||
<typedef loaderref="nested.loader" classpathref="test-classes" | |||||
name = "nested.c" | |||||
classname="${nested.package}AddTypeTest$CImpl"/> | |||||
<typedef loaderref="nested.loader" classpathref="test-classes" | |||||
name = "nested.ab" | |||||
classname="${nested.package}AddTypeTest$ABImpl"/> | |||||
<taskdef loaderref="nested.loader" classpathref="test-classes" | |||||
name = "nested.container" | |||||
classname="${nested.package}AddTypeTest$NestedContainer"/> | |||||
<taskdef loaderref="nested.loader" classpathref="nested.classes" | |||||
name = "nested.condition.task" | |||||
classname="${nested.package}AddTypeTest$MyCondition"/> | |||||
<typedef loaderref="nested.loader" classpathref="nested.classes" | |||||
name = "nested.condition.type" | |||||
classname="${nested.package}AddTypeTest$MyCondition"/> | |||||
</target> | |||||
<target name="nested.a" depends="init"> | |||||
<nested.container> | |||||
<nested.a/> | |||||
</nested.container> | |||||
</target> | |||||
<target name="nested.b" depends="init"> | |||||
<nested.container> | |||||
<nested.b/> | |||||
</nested.container> | |||||
</target> | |||||
<target name="nested.c" depends="init"> | |||||
<nested.container> | |||||
<nested.c/> | |||||
</nested.container> | |||||
</target> | |||||
<target name="nested.ab" depends="init"> | |||||
<nested.container> | |||||
<nested.ab/> | |||||
</nested.container> | |||||
</target> | |||||
<!-- tests for task adaptor --> | |||||
<target name="condition.type" depends="init"> | |||||
<echo>before</echo> | |||||
<nested.condition.type/> | |||||
<echo>after</echo> | |||||
</target> | |||||
<target name="condition.task" depends="init"> | |||||
<echo>before</echo> | |||||
<nested.condition.task/> | |||||
<echo>after</echo> | |||||
</target> | |||||
<target name="condition.condition.type" depends="init"> | |||||
<condition property="condition.condition.type"> | |||||
<nested.condition.type/> | |||||
</condition> | |||||
</target> | |||||
<target name="condition.condition.task" depends="init"> | |||||
<condition property="condition.condition.task">> | |||||
<nested.condition.task/> | |||||
</condition> | |||||
</target> | |||||
</project> |
@@ -161,6 +161,41 @@ public class ComponentHelper { | |||||
return component; | 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 | /** Initialization code - implementing the original ant component | ||||
* loading from /org/apache/tools/ant/taskdefs/default.properties | * loading from /org/apache/tools/ant/taskdefs/default.properties | ||||
* and .../types/default.properties | * and .../types/default.properties | ||||
@@ -58,8 +58,10 @@ import java.io.File; | |||||
import java.lang.reflect.Constructor; | import java.lang.reflect.Constructor; | ||||
import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import java.util.ArrayList; | |||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Hashtable; | import java.util.Hashtable; | ||||
import java.util.List; | |||||
import java.util.Locale; | import java.util.Locale; | ||||
import org.apache.tools.ant.types.EnumeratedAttribute; | import org.apache.tools.ant.types.EnumeratedAttribute; | ||||
import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
@@ -97,6 +99,11 @@ public class IntrospectionHelper implements BuildListener { | |||||
*/ | */ | ||||
private Hashtable nestedCreators; | 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 | * Map from attribute names to methods to store configured nested types | ||||
* (String to NestedStorer). | * (String to NestedStorer). | ||||
@@ -199,6 +206,7 @@ public class IntrospectionHelper implements BuildListener { | |||||
nestedTypes = new Hashtable(); | nestedTypes = new Hashtable(); | ||||
nestedCreators = new Hashtable(); | nestedCreators = new Hashtable(); | ||||
nestedStorers = new Hashtable(); | nestedStorers = new Hashtable(); | ||||
addTypeMethods = new ArrayList(); | |||||
this.bean = bean; | this.bean = bean; | ||||
@@ -209,6 +217,14 @@ public class IntrospectionHelper implements BuildListener { | |||||
Class returnType = m.getReturnType(); | Class returnType = m.getReturnType(); | ||||
Class[] args = m.getParameterTypes(); | 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 | // not really user settable properties on tasks | ||||
if (org.apache.tools.ant.Task.class.isAssignableFrom(bean) | if (org.apache.tools.ant.Task.class.isAssignableFrom(bean) | ||||
&& args.length == 1 && isHiddenSetMethod(name, args[0])) { | && args.length == 1 && isHiddenSetMethod(name, args[0])) { | ||||
@@ -534,6 +550,16 @@ public class IntrospectionHelper implements BuildListener { | |||||
public Object createElement(Project project, Object parent, | public Object createElement(Project project, Object parent, | ||||
String elementName) throws BuildException { | String elementName) throws BuildException { | ||||
NestedCreator nc = (NestedCreator) nestedCreators.get(elementName); | 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) { | if (nc == null && parent instanceof DynamicConfigurator) { | ||||
DynamicConfigurator dc = (DynamicConfigurator) parent; | DynamicConfigurator dc = (DynamicConfigurator) parent; | ||||
Object nestedElement = dc.createDynamicElement(elementName); | Object nestedElement = dc.createDynamicElement(elementName); | ||||
@@ -578,7 +604,8 @@ public class IntrospectionHelper implements BuildListener { | |||||
*/ | */ | ||||
public boolean supportsNestedElement(String elementName) { | public boolean supportsNestedElement(String elementName) { | ||||
return nestedCreators.containsKey(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. | * @param event Ignored in this implementation. | ||||
*/ | */ | ||||
public void messageLogged(BuildEvent event) {} | 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; | |||||
} | |||||
} | } |
@@ -59,8 +59,8 @@ import java.util.Hashtable; | |||||
import java.util.Vector; | import java.util.Vector; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.DynamicConfigurator; | |||||
import org.apache.tools.ant.Project; | 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.EnumeratedAttribute; | ||||
import org.apache.tools.ant.types.Parameter; | import org.apache.tools.ant.types.Parameter; | ||||
import org.apache.tools.ant.types.RegularExpression; | import org.apache.tools.ant.types.RegularExpression; | ||||
@@ -80,7 +80,7 @@ import org.apache.tools.ant.util.regexp.Regexp; | |||||
*/ | */ | ||||
public class TokenFilter | public class TokenFilter | ||||
extends BaseFilterReader | extends BaseFilterReader | ||||
implements ChainableReader, DynamicConfigurator | |||||
implements ChainableReader | |||||
{ | { | ||||
/** | /** | ||||
* input stream tokenizers implement this interface | * input stream tokenizers implement this interface | ||||
@@ -229,9 +229,7 @@ public class TokenFilter | |||||
*/ | */ | ||||
public void addLineTokenizer(LineTokenizer tokenizer) { | 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) { | 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 | * add a file tokenizer | ||||
*/ | */ | ||||
public void addFileTokenizer(FileTokenizer tokenizer) { | public void addFileTokenizer(FileTokenizer tokenizer) { | ||||
add(tokenizer); | |||||
} | |||||
/** | |||||
* add a tokenizer | |||||
*/ | |||||
public void add(Tokenizer tokenizer) { | |||||
if (this.tokenizer != null) | if (this.tokenizer != null) | ||||
throw new BuildException("Only one tokenizer allowed"); | throw new BuildException("Only one tokenizer allowed"); | ||||
this.tokenizer = tokenizer; | this.tokenizer = tokenizer; | ||||
} | } | ||||
// ----------------------------------------- | // ----------------------------------------- | ||||
// Predefined filters | // Predefined filters | ||||
// ----------------------------------------- | // ----------------------------------------- | ||||
@@ -297,48 +300,7 @@ public class TokenFilter | |||||
filters.addElement(filter); | 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 | // Tokenizer Classes | ||||
@@ -349,6 +311,7 @@ public class TokenFilter | |||||
* class to read the complete input into a string | * class to read the complete input into a string | ||||
*/ | */ | ||||
public static class FileTokenizer | public static class FileTokenizer | ||||
extends ProjectComponent | |||||
implements Tokenizer | implements Tokenizer | ||||
{ | { | ||||
/** | /** | ||||
@@ -378,6 +341,7 @@ public class TokenFilter | |||||
* by \r (mac style), \r\n (dos/windows style) or \n (unix style) | * by \r (mac style), \r\n (dos/windows style) or \n (unix style) | ||||
*/ | */ | ||||
public static class LineTokenizer | public static class LineTokenizer | ||||
extends ProjectComponent | |||||
implements Tokenizer | implements Tokenizer | ||||
{ | { | ||||
private String lineEnd = ""; | private String lineEnd = ""; | ||||
@@ -466,6 +430,7 @@ public class TokenFilter | |||||
* as delims flag is set). | * as delims flag is set). | ||||
*/ | */ | ||||
public static class StringTokenizer | public static class StringTokenizer | ||||
extends ProjectComponent | |||||
implements Tokenizer | implements Tokenizer | ||||
{ | { | ||||
private String intraString = ""; | private String intraString = ""; | ||||
@@ -585,6 +550,7 @@ public class TokenFilter | |||||
// -------------------------------------------- | // -------------------------------------------- | ||||
public static abstract class ChainableReaderFilter | public static abstract class ChainableReaderFilter | ||||
extends ProjectComponent | |||||
implements ChainableReader, Filter | implements ChainableReader, Filter | ||||
{ | { | ||||
private boolean byLine = true; | private boolean byLine = true; | ||||
@@ -596,7 +562,7 @@ public class TokenFilter | |||||
public Reader chain(Reader reader) { | public Reader chain(Reader reader) { | ||||
TokenFilter tokenFilter = new TokenFilter(reader); | TokenFilter tokenFilter = new TokenFilter(reader); | ||||
if (!byLine) | if (!byLine) | ||||
tokenFilter.addFileTokenizer(new FileTokenizer()); | |||||
tokenFilter.add(new FileTokenizer()); | |||||
tokenFilter.add(this); | tokenFilter.add(this); | ||||
return tokenFilter; | return tokenFilter; | ||||
} | } | ||||
@@ -656,6 +622,7 @@ public class TokenFilter | |||||
* Simple filter to filter lines contains strings | * Simple filter to filter lines contains strings | ||||
*/ | */ | ||||
public static class ContainsString | public static class ContainsString | ||||
extends ProjectComponent | |||||
implements Filter | implements Filter | ||||
{ | { | ||||
private String contains; | private String contains; | ||||
@@ -818,6 +785,7 @@ public class TokenFilter | |||||
* Filter to delete characters | * Filter to delete characters | ||||
*/ | */ | ||||
public static class DeleteCharacters | public static class DeleteCharacters | ||||
extends ProjectComponent | |||||
implements Filter, ChainableReader | implements Filter, ChainableReader | ||||
{ | { | ||||
// Attributes | // Attributes | ||||
@@ -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.PresentSelector; | ||||
import org.apache.tools.ant.types.selectors.SelectSelector; | import org.apache.tools.ant.types.selectors.SelectSelector; | ||||
import org.apache.tools.ant.types.selectors.SizeSelector; | 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. | * 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); | 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). | * Delete the file(s). | ||||
*/ | */ | ||||
@@ -426,6 +426,7 @@ public abstract class MatchingTask extends Task implements SelectorContainer { | |||||
public void addDifferent(DifferentSelector selector) { | public void addDifferent(DifferentSelector selector) { | ||||
fileset.addDifferent(selector); | fileset.addDifferent(selector); | ||||
} | } | ||||
/** | /** | ||||
* add a type selector entry on the type list | * add a type selector entry on the type list | ||||
* @param selector | * @param selector | ||||
@@ -435,6 +436,14 @@ public abstract class MatchingTask extends Task implements SelectorContainer { | |||||
fileset.addType(selector); | fileset.addType(selector); | ||||
} | } | ||||
/** | |||||
* add an arbitary selector | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void add(FileSelector selector) { | |||||
fileset.add(selector); | |||||
} | |||||
/** | /** | ||||
* Accessor for the implict fileset. | * Accessor for the implict fileset. | ||||
* | * | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* The Apache Software License, Version 1.1 | * 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. | * reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * 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);} | public void addIsReference(IsReference i) {conditions.addElement(i);} | ||||
/** | |||||
* Add an arbitary condition | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void add(Condition c) {conditions.addElement(c);} | |||||
} | } |
@@ -649,6 +649,14 @@ public abstract class AbstractFileSet extends DataType implements Cloneable, | |||||
appendSelector(selector); | 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 | * Returns included files as a list of semicolon-separated filenames | ||||
* | * | ||||
@@ -59,7 +59,6 @@ import java.io.Reader; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.tools.ant.BuildException; | 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.ChainableReader; | ||||
import org.apache.tools.ant.filters.ClassConstants; | import org.apache.tools.ant.filters.ClassConstants; | ||||
import org.apache.tools.ant.filters.EscapeUnicode; | import org.apache.tools.ant.filters.EscapeUnicode; | ||||
@@ -85,7 +84,7 @@ import org.apache.tools.ant.taskdefs.Concat; | |||||
* @author Magesh Umasankar | * @author Magesh Umasankar | ||||
*/ | */ | ||||
public final class FilterChain extends DataType | public final class FilterChain extends DataType | ||||
implements Cloneable, DynamicConfigurator | |||||
implements Cloneable | |||||
{ | { | ||||
private Vector filterReaders = new Vector(); | private Vector filterReaders = new Vector(); | ||||
@@ -246,38 +245,14 @@ public final class FilterChain extends DataType | |||||
super.setRefid(r); | 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 | * @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); | |||||
} | } | ||||
} | } |
@@ -220,6 +220,19 @@ public class Path extends DataType implements Cloneable { | |||||
setChecked( false ); | 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 <code><path></code> element. | * Creates a nested <code><path></code> element. | ||||
*/ | */ | ||||
@@ -79,8 +79,6 @@ import org.apache.tools.ant.Task; | |||||
public class ScriptFilter | public class ScriptFilter | ||||
extends TokenFilter.ChainableReaderFilter | extends TokenFilter.ChainableReaderFilter | ||||
{ | { | ||||
/** The current project - set by ant reflection */ | |||||
private Project project; | |||||
/** The language - attribute of element */ | /** The language - attribute of element */ | ||||
private String language; | private String language; | ||||
/** The script - inline text or external file */ | /** The script - inline text or external file */ | ||||
@@ -94,16 +92,6 @@ public class ScriptFilter | |||||
/** the token used by the script */ | /** the token used by the script */ | ||||
private String token; | 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). | * Defines the language (required). | ||||
* | * | ||||
@@ -305,5 +305,14 @@ public abstract class BaseSelectorContainer extends BaseSelector | |||||
appendSelector(selector); | appendSelector(selector); | ||||
} | } | ||||
/** | |||||
* add an arbitary selector | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void add(FileSelector selector) { | |||||
appendSelector(selector); | |||||
} | |||||
} | } | ||||
@@ -189,5 +189,11 @@ public interface SelectorContainer { | |||||
* @since ant 1.6 | * @since ant 1.6 | ||||
*/ | */ | ||||
public void addDifferent(DifferentSelector selector); | public void addDifferent(DifferentSelector selector); | ||||
/** | |||||
* add an arbitary selector | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void add(FileSelector selector); | |||||
} | } | ||||
@@ -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 | |||||
* <http://www.apache.org/>. | |||||
*/ | |||||
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"); | |||||
} | |||||
} | |||||
} |