diff --git a/docs/manual/CoreTypes/custom-programming.html b/docs/manual/CoreTypes/custom-programming.html new file mode 100644 index 000000000..f75d4b065 --- /dev/null +++ b/docs/manual/CoreTypes/custom-programming.html @@ -0,0 +1,391 @@ + +
+ ++ Custom components are conditions, selectors, filters and other + objects that are defined outside ant core. +
++ In Ant 1.6 custom conditions, selectors and filters has + been overhauled. +
++ It is now possible to define custom conditions, selectors and filters + that behave like Ant Core components. + This is achieved by allowing datatypes defined in build scripts + to be used as custom components if the class of the datatype + is compatible, or has been adapted by an adapter class. +
++ The old methods of defining custom components are still supported. +
++ A custom component is a normal Java class that implements a particular + interface or extends a particular class, or has been adapted to the + interface or class. +
++ It is exactly like writing a + custom task. + One defines attributes and nested elements by writing setter + methods and add methods. +
+
+ After the class has been written, it is added to the ant system
+ by using <typedef>
.
+
+ Custom conditions are datatypes that implement
+ org.apache.tools.ant.taskdefs.condition.Condition
.
+ For example a custom condition that returns true if a
+ string is all upper case could be written as:
+
++ ++package com.mydomain; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.condition.Condition; + +public class AllUpperCaseCondition extends Condition { + private String value; + + // The setter for the "value" attribute + public void setValue(String value) { + this.value = value; + } + + // This method evaluates the condition + public boolean eval() { + if (value == null) { + throw new BuildException("value attribute is not set"); + } + return value.toUpperCase().equals(value); + } +} ++
+ Adding the condition to the system is achieved as follows: +
++++<typedef + name="alluppercase" + classname="com.mydomain.AllUpperCaseCondition" + classpath="${mydomain.classes"/> ++
+ This condition can now be used wherever a Core Ant condition + is used. +
++++<condition property="allupper"> + <alluppercase value="THIS IS ALL UPPER CASE"/> +</condition> ++
+ Custom selectors are datatypes that implement
+ org.apache.tools.ant.types.selectors.FileSelector
.
+
There is only one method required.
+ public boolean isSelected(File basedir, String filename,
+ File file)
.
+ It returns true
+ or false depending on whether the given file should be
+ selected or not.
+
+ An example of a custom selection that selects filenames ending + in ".java" would be: +
++++package com.mydomain; +import org.apache.tools.ant.types.selectors.FileSelector; +public class JavaSelector { + public boolean isSelected(File b, String filename, File f) { + return filename.toLowerCase().endsWith(".java"); + } +} ++
+
++ Adding the selector to the system is achieved as follows: +
++++<typedef + name="javaselector" + classname="com.mydomain.JavaSelector" + classpath="${mydomain.classes"/> ++
+ This selector can now be used wherever a Core Ant selector + is used. +
+
+ One may use
+ org.apache.tools.ant.types.selectors.BaseSelector
,
+ a convenience class that provides reasonable default
+ behaviour.
+ It has some predefined behaviours you can take advantage
+ of. Any time you encounter a problem when setting attributes or
+ adding tags, you can call setError(String errmsg) and the class
+ will know that there is a problem. Then, at the top of your
+ isSelected()
method call validate()
and
+ a BuildException will be thrown with the contents of your error
+ message. The validate()
method also gives you a
+ last chance to check your settings for consistency because it
+ calls verifySettings()
. Override this method and
+ call setError()
within it if you detect any
+ problems in how your selector is set up.
+ To write custom selector containers one should extend
+ org.apache.tools.ant.types.selectors.BaseSelectorContainer
.
+ Implement the
+ public boolean isSelected(File baseDir, String filename, File file)
+ method to do the right thing. Chances are you'll want to iterate
+ over the selectors under you, so use
+ selectorElements()
to get an iterator that will do
+ that.
+
+ For example to create a selector container that will select files + if a certain number of contained selectors select, one could write + a selector as follows: +
++++public class MatchNumberSelectors extends BaseSelectorContainer { + private int number = -1; + public void setNumber(int number) { + this.number = number; + } + public void verifySettings() { + if (number < 0) { + throw new BuildException("Number attribute should be set"); + } + } + public boolean isSelected(File baseDir, String filename, File file) { + validate(); + int numberSelected = 0; + for (Enumeration e = selectorElements(); e.hasNextElement();) { + FileSelector s = (FileSelector) e.nextElement(); + if (s.isSelected(baseDir, filename, file)) { + numberSelected++; + } + } + return numberSelected == number; + } +} ++
+ To define and use this selector one could do: +
++++<typedef name="numberselected" + classname="com.mydomain.MatchNumberSelectors"/> +... +<fileset dir="${src.path}"> + <numberselected number="2"> + <contains text="script" casesensitive="no"/> + <size value="4" units="Ki" when="more"/> + <javaselector/> + </numberselected> +</fileset> ++
+ The custom selector +
++ The custom selector was the pre ant 1.6 way of defining custom selectors. + This method is still supported for backward compatiblity. +
+You can write your own selectors and use them within the selector + containers by specifying them within the <custom> tag.
+ +To create a new Custom Selector, you have to create a class that
+ implements
+ org.apache.tools.ant.types.selectors.ExtendFileSelector
.
+ The easiest way to do that is through the convenience base class
+ org.apache.tools.ant.types.selectors.BaseExtendSelector
,
+ which provides all of the methods for supporting
+ <param>
tags. First, override the
+ isSelected()
method, and optionally the
+ verifySettings()
method. If your custom
+ selector requires parameters to be set, you can also override
+ the setParameters()
method and interpret the
+ parameters that are passed in any way you like. Several of the
+ core selectors demonstrate how to do that because they can
+ also be used as custom selectors.
Once that is written, you include it in your build file by using
+ the <custom>
tag.
+
Attribute | +Description | +Required | +
classname | +The name of your class that implements
+ org.apache.tools.ant.types.selectors.FileSelector .
+ |
+ Yes | +
classpath | +The classpath to use in order to load the + custom selector class. If neither this classpath nor the + classpathref are specified, the class will be + loaded from the classpath that Ant uses. + | +No | +
classpathref | +A reference to a classpath previously + defined. If neither this reference nor the + classpath above are specified, the class will be + loaded from the classpath that Ant uses. + | +No | +
Here is how you use <custom>
to
+ use your class as a selector:
+
+ + ++<fileset dir="${mydir}" includes="**/*"> + <custom classname="com.mydomain.MySelector"> + <param name="myattribute" value="myvalue"/> + </custom> +</fileset> +
The core selectors that can also be used as custom selectors + are
+ +org.apache.tools.ant.types.selectors.ContainsSelector
+ org.apache.tools.ant.types.selectors.DateSelector
+ org.apache.tools.ant.types.selectors.DepthSelector
+ org.apache.tools.ant.types.selectors.FilenameSelector
+ org.apache.tools.ant.types.selectors.SizeSelector
+ Here is the example from the Depth Selector section rewritten
+ to use the selector through <custom>
.
+ ++<fileset dir="${doc.path}" includes="**/*"> + <custom classname="org.apache.tools.ant.types.selectors.DepthSelector"> + <param name="max" value="1"/> + </custom> +</fileset> +
Selects all files in the base directory and one directory below + that.
+ +
+ Custom filter readers selectors are datatypes that implement
+ org.apache.tools.ant.types.filters.ChainableReader
.
+
There is only one method required.
+ Reader chain(Reader reader)
.
+ This returns a reader that filters input from the specified
+ reader.
+
+ For example a filterreader that removes every second character + could be: +
++++public class RemoveOddCharacters implements ChainableReader { + public Reader chain(Reader reader) { + return new BaseFilterReader(reader) { + int count = 0; + public int read() throws IOException { + while (true) { + int c = in.read(); + if (c == -1) { + return c; + } + count++; + if ((count % 2) == 1) { + return c; + } + } + } + } + } +} ++
+ For line oriented filters it may be easier to extend
+ ChainableFilterReader
an inner class of
+ org.apache.tools.ant.filters.TokenFilter
.
+
+ For example a filter that appends the line number could be +
+++ + ++public class AddLineNumber extends ChainableReaderFilter { + private void lineNumber = 0; + public String filter(String string) { + lineNumber++; + return "" + lineNumber + "\t" + string; + } +} ++
Copyright © 2003 Apache Software Foundation. All rights + Reserved.
+ + + diff --git a/docs/manual/conceptstypeslist.html b/docs/manual/conceptstypeslist.html index 1b95bfce1..dc60cab07 100644 --- a/docs/manual/conceptstypeslist.html +++ b/docs/manual/conceptstypeslist.html @@ -34,5 +34,11 @@ Class Fileset