Look at Unix pipes - they offer you so much flexibility - say you wanted to copy just those lines that contained the string blee from the first 10 lines of a file 'foo' to a file 'bar' - you would do something like
cat foo|head -n10|grep blee > bar
Ant was not flexible enough. There was no way for the <copy> task to do something similar. If you wanted the <copy> task to get the first 10 lines, you would have had to create special attributes:
<copy file="foo" tofile="bar" head="10" contains="blee"/>
The obvious problem thus surfaced: Ant tasks would not be able to accomodate such data transformation attributes as they would be endless. The task would also not know in which order these attributes were to be interpreted. That is, must the task execute the contains attribute first and then the head attribute or vice-versa? What Ant tasks needed was a mechanism to allow pluggable filter (data tranformer) chains. Ant would provide a few filters for which there have been repeated requests. Users with special filtering needs would be able to easily write their own and plug them in.
The solution was to refactor data transformation oriented tasks to support FilterChains. A FilterChain is a group of ordered FilterReaders. Users can define their own FilterReaders by just extending the java.io.FilterReader class. Such custom FilterReaders can be easily plugged in as nested elements of <filterchain> by using <filterreader> elements.
Example:
<copy file="${src.file}" tofile="${dest.file}"> <filterchain> <filterreader classname="your.extension.of.java.io.FilterReader"> <param name="foo" value="bar"/> </filterreader> <filterreader classname="another.extension.of.java.io.FilterReader"> <classpath> <pathelement path="${classpath}"/> </classpath> <param name="blah" value="blee"/> <param type="abra" value="cadabra"/> </filterreader> </filterchain> </copy>
Ant provides some built-in filter readers. These filter readers can also be declared using a syntax similar to the above syntax. However, they can be declared using some simpler syntax also.
Example:
<loadfile srcfile="${src.file}" property="${src.file.head}"> <filterchain> <headfilter lines="15"/> </filterchain> </loadfile>is equivalent to:
<loadfile srcfile="${src.file}" property="${src.file.head}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.HeadFilter"> <param name="lines" value="15"/> </filterreader> </filterchain> </loadfile>The following built-in tasks support nested <filterchain> elements.
Copy, LoadFile, LoadProperties, MoveA FilterChain is formed by defining zero or more of the following nested elements. FilterReader ClassConstants ExpandProperties HeadFilter LineContains LineContainsRegExp PrefixLines ReplaceTokens StripJavaComments StripLineBreaks StripLineComments TabsToSpaces TailFilter
FilterReader The filterreader element is the generic way to define a filter. User defined filter elements are defined in the build file using this. Please note that built in filter readers can also be defined using this syntax. A FilterReader element must be supplied with a class name as an attribute value. The class resolved by this name must extend java.io.FilterReader. If the custom filter reader needs to be parameterized, it must implement org.apache.tools.type.Parameterizable. Attribute Description Required classname The class name of the filter reader. Yes
Nested Elements: <filterreader> supports <classpath> and <param> as nested elements. Each <param> element may take in the following attributes - name, type and value.
The following FilterReaders are supplied with the default distribution.
ClassConstants This filters basic constants defined in a Java Class, and outputs them in lines composed of the format name=value
Example: This loads the basic constants defined in a Java class as Ant properties.
<loadproperties srcfile="foo.class"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.ClassConstants"/> </filterchain> </loadproperties>Convenience method:
<loadproperties srcfile="foo.class"> <filterchain> <classconstants/> </filterchain> </loadproperties>ExpandProperties If the data contains data that represents Ant properties (of the form ${...}), that is substituted with the property's actual value.
Example: This results in the property modifiedmessage holding the value "All these moments will be lost in time, like teardrops in the rain"
<echo message="All these moments will be lost in time, like teardrops in the ${weather}" file="loadfile1.tmp" /> <property name="weather" value="rain" /> <loadfile property="modifiedmessage" srcFile="loadfile1.tmp"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.ExpandProperties"/> </filterchain> </loadfile>Convenience method:
<echo message="All these moments will be lost in time, like teardrops in the ${weather}" file="loadfile1.tmp" /> <property name="weather" value="rain" /> <loadfile property="modifiedmessage" srcFile="loadfile1.tmp"> <filterchain> <expandproperties/> </filterchain> </loadfile>
HeadFilter This filter reads the first few lines from the data supplied to it. Parameter Name Parameter Value Required lines Number of lines to be read. Defaults to "10" No
Example:
This stores the first 15 lines of the supplied data in the property ${src.file.head}
<loadfile srcfile="${src.file}" property="${src.file.head}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.HeadFilter"> <param name="lines" value="15"/> </filterreader> </filterchain> </loadfile>Convenience method:
<loadfile srcfile="${src.file}" property="${src.file.head}"> <filterchain> <headfilter lines="15"/> </filterchain> </loadfile>
LineContains This filter includes only those lines that contain all the user-specified strings. Parameter Type Parameter Value Required contains Substring to be searched for. Yes
Example: This will include only those lines that contain foo and bar.
<filterreader classname="org.apache.tools.ant.filters.LineContains"> <param type="contains" value="foo"/> <param type="contains" value="bar"/> </filterreader>Convenience method:
<linecontains> <contains value="foo"> <contains value="bar"> </linecontains>LineContainsRegExp Filter which includes only those lines that contain the user-specified regular expression matching strings. Parameter Type Parameter Value Required regexp Pattern of the substring to be searched for. Yes
Example: This will fetch all those lines that contain the pattern foo
<filterreader classname="org.apache.tools.ant.filters.LineContainsRegExp"> <param type="regexp" value="foo*"/> </filterreader>Convenience method:
<linecontainsregexp> <regexp pattern="foo*"> </linecontainsregexp>PrefixLines Attaches a prefix to every line. Parameter Name Parameter Value Required prefix Prefix to be attached to lines. Yes
Example: This will attach the prefix Foo to all lines.
<filterreader classname="org.apache.tools.ant.filters.PrefixLines"> <param name="prefix" value="Foo"/> </filterreader>Convenience method:
<prefixlines prefix="Foo"/>ReplaceTokens This filter reader replaces all strings that are sandwiched between begintoken and endtoken with user defined values. Parameter Type Parameter Name Parameter Value Required tokenchar begintoken Character marking the beginning of a token. Defaults to @ No tokenchar endtoken Character marking the end of a token. Defaults to @ No token User defined String. User defined search String Yes
Example: This replaces occurences of the string @DATE@ in the data with today's date and stores it in the property ${src.file.replaced}
<tstamp/> <loadfile srcfile="${src.file}" property="${src.file.replaced}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.ReplaceTokens"> <param type="token" name="DATE" value="${TODAY}"/> </filterreader> </filterchain> </loadfile>Convenience method:
<tstamp/> <loadfile srcfile="${src.file}" property="${src.file.replaced}"> <filterchain> <replacetokens> <token key="DATE" value="${TODAY}"/> </replacetokens> </filterchain> </loadfile>
StripJavaComments This filter reader strips away comments from the data, using Java syntax guidelines. This filter does not take in any parameters.
Example:
<loadfile srcfile="${java.src.file}" property="${java.src.file.nocomments}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.StripJavaComments"/> </filterchain> </loadfile>Convenience method:
<loadfile srcfile="${java.src.file}" property="${java.src.file.nocomments}"> <filterchain> <stripjavacomments/> </filterchain> </loadfile>StripLineBreaks This filter reader strips away specific characters from the data supplied to it. Parameter Name Parameter Value Required linebreaks Characters that are to be stripped out. Defaults to "
Examples:
This strips the 'r' and '
n' characters.
<loadfile srcfile="${src.file}" property="${src.file.contents}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.StripLineBreaks"/> </filterchain> </loadfile>Convenience method:
<loadfile srcfile="${src.file}" property="${src.file.contents}"> <filterchain> <striplinebreaks/> </filterchain> </loadfile>This treats the '(' and ')' characters as line break characters and strips them.
<loadfile srcfile="${src.file}" property="${src.file.contents}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.StripLineBreaks"> <param name="linebreaks" value="()"/> </filterreader> </filterchain> </loadfile>StripLineComments This filter removes all those lines that begin with strings that represent comments as specified by the user. Parameter Type Parameter Value Required comment Strings that identify a line as a comment when they appear at the start of the line. Yes
Examples: This removes all lines that begin with #, -, REM, rem and //
<filterreader classname="org.apache.tools.ant.filters.StripLineComments"> <param type="comment" value="#"/> <param type="comment" value="--"/> <param type="comment" value="REM "/> <param type="comment" value="rem "/> <param type="comment" value="//"/> </filterreader>Convenience method:
<striplinecomments> <comment value="#"/> <comment value="--"/> <comment value="REM "/> <comment value="rem "/> <comment value="//"/> </striplinecomments>TabsToSpaces This filter replaces tabs with spaces Parameter Name Parameter Value Required lines tablength Defaults to "8" No
Examples: This replaces tabs in ${src.file} with spaces.
<loadfile srcfile="${src.file}" property="${src.file.notab}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.TabsToSpaces"/> </filterchain> </loadfile>Convenience method:
<loadfile srcfile="${src.file}" property="${src.file.notab}"> <filterchain> <tabstospaces/> </filterchain> </loadfile>
TailFilter This filter reads the last few lines from the data supplied to it. Parameter Name Parameter Value Required lines Number of lines to be read. Defaults to "10" No
Examples: This stores the last 15 lines of the supplied data in the property ${src.file.tail}
<loadfile srcfile="${src.file}" property="${src.file.tail}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.TailFilter"> <param name="lines" value="15"/> </filterreader> </filterchain> </loadfile>Convenience method:
<loadfile srcfile="${src.file}" property="${src.file.tail}"> <filterchain> <tailfilter lines="15"/> </filterchain> </loadfile>This stores the last 5 lines of the first 15 lines of the supplied data in the property ${src.file.mid}
<loadfile srcfile="${src.file}" property="${src.file.mid}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.HeadFilter"> <param name="lines" value="15"/> </filterreader> <filterreader classname="org.apache.tools.ant.filters.TailFilter"> <param name="lines" value="5"/> </filterreader> </filterchain> </loadfile>Convenience method:
<loadfile srcfile="${src.file}" property="${src.file.mid}"> <filterchain> <headfilter lines="15"/> <tailfilter lines="5"/> </filterchain> </loadfile>