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 accommodate 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 transformer) 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:
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.<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>
Example:
is equivalent to:<loadfile srcfile="${src.file}" property="src.file.head"> <filterchain> <headfilter lines="15"/> </filterchain> </loadfile>
The following built-in tasks support nested<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>
<filterchain>
elements.Attribute | Description | Required |
classname | The class name of the filter reader. | Yes |
<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.
This filters basic constants defined in a Java Class, and outputs them in lines composed of the format name=value. This filter uses the bcel library to understand the Java Class file. See Library Dependencies.
Important: This filter is different from most of the other filters. Most of the filters operate on a sequence of characters. This filter operates on the sequence of bytes that makes up a class. However the bytes arrive to the filter as a sequence of characters. This means that one must be careful on the choice of character encoding to use. Most encoding lose information on conversion from an arbitary sequence of bytes to characters and back again to bytes. In particular the usual default character encodings (CP152 and UTF-8) do. For this reason, since Ant 1.7, the character encoding ISO-8859-1 is used to convert from characters back to bytes, so one has to use this encoding for reading the java class file.
This loads the constants from a Java class file as Ant properties, prepending the names with a prefix.<loadproperties srcfile="foo.class" encoding="ISO-8859-1"> <filterchain> <classconstants/> </filterchain> </loadproperties>
<loadproperties srcfile="build/classes/org/acme/bar.class" encoding="ISO-8859-1"> <filterchain> <classconstants/> <prefixlines prefix="ini."/> </filterchain> </loadproperties>
This filter converts its input by changing all non US-ASCII characters into their equivalent unicode escape backslash u plus 4 digits.
since Ant 1.6
Convenience method:<loadproperties srcfile="non_ascii_property.properties"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.EscapeUnicode"/> </filterchain> </loadproperties>
<loadproperties srcfile="non_ascii_property.properties"> <filterchain> <escapeunicode/> </filterchain> </loadproperties>
If the data contains data that represents Ant properties (of the form ${...}), that is substituted with the property's actual value.
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> <filterreader classname="org.apache.tools.ant.filters.ExpandProperties"/> </filterchain> </loadfile>
<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>
Parameter Name | Parameter Value | Required |
lines | Number of lines to be read.
Defaults to "10" A negative value means that all lines are passed (useful with skip) |
No |
skip | Number of lines to be skipped (from the beginning). Defaults to "0" | No |
Convenience method:<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>
This stores the first 15 lines, skipping the first 2 lines, of the supplied data in the property src.file.head. (Means: lines 3-17)<loadfile srcfile="${src.file}" property="src.file.head"> <filterchain> <headfilter lines="15"/> </filterchain> </loadfile>
See the testcases for more examples (src\etc\testcases\filters\head-tail.xml in the source distribution).<loadfile srcfile="${src.file}" property="src.file.head"> <filterchain> <headfilter lines="15" skip="2"/> </filterchain> </loadfile>
Parameter Type | Parameter Value | Required |
contains | Substring to be searched for. | Yes |
negate | Whether to select non-matching lines only. Since Ant 1.7 | No |
foo
and
bar
.
Convenience method:<filterreader classname="org.apache.tools.ant.filters.LineContains"> <param type="contains" value="foo"/> <param type="contains" value="bar"/> </filterreader>
Negation:<linecontains> <contains value="foo"/> <contains value="bar"/> </linecontains>
or<filterreader classname="org.apache.tools.ant.filters.LineContains"> <param type="negate" value="true"/> <param type="contains" value="foo"/> <param type="contains" value="bar"/> </filterreader>
<linecontains negate="true"> <contains value="foo"/> <contains value="bar"/> </linecontains>
Parameter Type | Parameter Value | Required |
regexp | Regular expression to be searched for. | Yes |
negate | Whether to select non-matching lines only. Since Ant 1.7 | No |
foo
Convenience method:<filterreader classname="org.apache.tools.ant.filters.LineContainsRegExp"> <param type="regexp" value="foo*"/> </filterreader>
Negation:<linecontainsregexp> <regexp pattern="foo*"/> </linecontainsregexp>
or<filterreader classname="org.apache.tools.ant.filters.LineContainsRegExp"> <param type="negate" value="true"/> <param type="regexp" value="foo*"/> </filterreader>
<linecontainsregexp negate="true"> <regexp pattern="foo*"/> </linecontainsregexp>
Parameter Name | Parameter Value | Required |
prefix | Prefix to be attached to lines. | Yes |
Foo
to all lines.
Convenience method:<filterreader classname="org.apache.tools.ant.filters.PrefixLines"> <param name="prefix" value="Foo"/> </filterreader>
<prefixlines prefix="Foo"/>
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 |
propertiesfile | Not applicable. | Properties file to take tokens from. | No |
Convenience method:<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>
This will treat each properties file entry in sample.properties as a token/key pair :<tstamp/> <loadfile srcfile="${src.file}" property="${src.file.replaced}"> <filterchain> <replacetokens> <token key="DATE" value="${TODAY}"/> </replacetokens> </filterchain> </loadfile>
<loadfile srcfile="${src.file}" property="${src.file.replaced}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.ReplaceTokens"> <param type="propertiesfile" value="sample.properties"/> </filterreader> </filterchain> </loadfile> </filterchain>
Convenience method:<loadfile srcfile="${java.src.file}" property="${java.src.file.nocomments}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.StripJavaComments"/> </filterchain> </loadfile>
<loadfile srcfile="${java.src.file}" property="${java.src.file.nocomments}"> <filterchain> <stripjavacomments/> </filterchain> </loadfile>
Parameter Name | Parameter Value | Required |
linebreaks | Characters that are to be stripped out. Defaults to "\r\n" | No |
Convenience method:<loadfile srcfile="${src.file}" property="${src.file.contents}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.StripLineBreaks"/> </filterchain> </loadfile>
This treats the '(' and ')' characters as line break characters and strips them.<loadfile srcfile="${src.file}" property="${src.file.contents}"> <filterchain> <striplinebreaks/> </filterchain> </loadfile>
<loadfile srcfile="${src.file}" property="${src.file.contents}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.StripLineBreaks"> <param name="linebreaks" value="()"/> </filterreader> </filterchain> </loadfile>
Parameter Type | Parameter Value | Required |
comment | Strings that identify a line as a comment when they appear at the start of the line. | Yes |
Convenience method:<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>
<striplinecomments> <comment value="#"/> <comment value="--"/> <comment value="REM "/> <comment value="rem "/> <comment value="//"/> </striplinecomments>
Parameter Name | Parameter Value | Required |
tablength | Defaults to "8" | No |
Convenience method:<loadfile srcfile="${src.file}" property="${src.file.notab}"> <filterchain> <filterreader classname="org.apache.tools.ant.filters.TabsToSpaces"/> </filterchain> </loadfile>
<loadfile srcfile="${src.file}" property="${src.file.notab}"> <filterchain> <tabstospaces/> </filterchain> </loadfile>
Parameter Name | Parameter Value | Required |
lines | Number of lines to be read.
Defaults to "10" A negative value means that all lines are passed (useful with skip) |
No |
skip | Number of lines to be skipped (from the end). Defaults to "0" | No |
Content | Filter | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Line 1 |
|
|||||||||||||
Line 2 | ||||||||||||||
Line 3 | ||||||||||||||
Line 4 | ||||||||||||||
Line 5 | ||||||||||||||
Lines ... | ||||||||||||||
Line 95 | ||||||||||||||
Line 96 | ||||||||||||||
Line 97 | ||||||||||||||
Line 98 | ||||||||||||||
Line 99 |
Convenience method:<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>
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.tail}"> <filterchain> <tailfilter lines="15"/> </filterchain> </loadfile>
Convenience method:<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>
This stores the last 10 lines, skipping the last 2 lines, of the supplied data in the property src.file.head. (Means: if supplied data contains 60 lines, lines 49-58 are extracted)<loadfile srcfile="${src.file}" property="${src.file.mid}"> <filterchain> <headfilter lines="15"/> <tailfilter lines="5"/> </filterchain> </loadfile>
<loadfile srcfile="${src.file}" property="src.file.head"> <filterchain> <tailfilter lines="10" skip="2"/> </filterchain> </loadfile>
This filter deletes specified characters.
since Ant 1.6
This filter is only available in the convenience form.
Parameter Name | Parameter Value | Required |
chars | The characters to delete. This attribute is backslash enabled. | Yes |
<deletecharacters chars="\t\r"/>
This filter prepends or appends the content file to the filtered files.
since Ant 1.6
Parameter Name | Parameter Value | Required |
prepend | The name of the file which content should be prepended to the file. | No |
append | The name of the file which content should be appended to the file. | No |
Adds a license text before each java source:<filterchain> <concatfilter/> </filterchain>
<filterchain> <concatfilter prepend="apache-license-java.txt"/> </filterchain>
since Ant 1.6
Only one tokenizer element may be used, the LineTokenizer is the default if none are specified. A tokenizer splits the input into token strings and trailing delimiter strings.
There may be zero or more string filters. A string filter processes a token and either returns a string or a null. It the string is not null it is passed to the next filter. This proceeds until all the filters are called. If a string is returned after all the filters, the string is outputs with its associated token delimitier (if one is present). The trailing delimiter may be overridden by the delimOutput attribute.
blackslash interpretation A number of attributes (including delimOutput) interpret backslash escapes. The following are understood: \n, \r, \f, \t and \\.
Attribute | Description | Required |
delimOutput | This overrides the tokendelimiter returned by the tokenizer if it is not empty. This attribute is backslash enabled. | No |
The following tokenizers are provided by the default distribution.
LineTokenizer
FileTokenizer
StringTokenizer
ReplaceString
ContainsString
ReplaceRegex
ContainsRegex
Trim
IgnoreBlank
DeleteCharacters
This tokenizer splits the input into lines. The tokenizer delimits lines by "\r", "\n" or "\r\n". This is the default tokenizer.
Attribute | Description | Required |
includeDelims | Include the line endings in the token. Default is false. | No |
Remove blank lines.<tokenfilter delimoutput="\n"/>
This tokenizer treats all the input as a token. So be careful not to use this on very large input.<tokenfilter> <ignoreblank/> </tokenfilter>
This tokenizer is based on java.util.StringTokenizer. It splits up the input into strings separated by white space, or by a specified list of delimiting characters. If the stream starts with delimiter characters, the first token will be the empty string (unless the delimsaretokens attribute is used).<tokenfilter> <filetokenizer/> <replaceregex pattern="([\n\r]+[ \t]*|^[ \t]*)package" flags="s" replace="\1//package"/> </tokenfilter>
Attribute | Description | Required |
delims | The delimiter characters. White space is used if this is not set. (White space is defined in this case by java.lang.Character.isWhitespace()). | No |
delimsaretokens | If this is true, each delimiter character is returned as a token. Default is false. | No |
suppressdelims | If this is true, delimiters are not returned. Default is false. | No |
includeDelims | Include the delimiters in the token. Default is false. | No |
This is a simple filter to replace strings. This filter may be used directly within a filterchain.<tokenfilter> <stringtokenizer/> <replaceregex pattern="(.+)" replace="[\1]"/> </tokenfilter>
Attribute | Description | Required |
from | The string that must be replaced. | Yes |
to | The new value for the replaced string. When omitted an empty string is used. | No |
This is a simple filter to filter tokens that contains a specified string.<tokenfilter> <replacestring from="sun" to="moon"/> </tokenfilter>
Attribute | Description | Required |
contains | The string that the token must contain. | Yes |
This string filter replaces regular expressions. This filter may be used directly within a filterchain.<tokenfilter> <containsstring contains="foo"/> </tokenfilter>
See Regexp Type concerning the choice of the implementation.
Attribute | Description | Required |
pattern | The regular expression pattern to match in the token. | Yes |
replace | The substitution pattern to replace the matched regular expression. When omitted an empty string is used. | No |
flags | See ReplaceRegexp for an explanation of regex flags. | No |
This filters strings that match regular expressions. The filter may optionally replace the matched regular expression. This filter may be used directly within a filterchain.<tokenfilter> <replaceregex pattern="hello" replace="world" flags="gi"/> </tokenfilter>
See Regexp Type concerning the choice of regular expression implementation.
Attribute | Description | Required |
pattern | The regular expression pattern to match in the token. | Yes |
replace | The substitution pattern to replace the matched regular expression. When omitted the orignal token is returned. | No |
flags | See ReplaceRegexp for an explanation of regex flags. | No |
This example replaces lines like "SUITE(TestSuite, bits);" with "void register_bits();" and removes other lines.<tokenfilter> <containsregex pattern="(hello|world)" flags="i"/> </tokenfilter>
This filter trims whitespace from the start and end of tokens. This filter may be used directly within a filterchain. This filter removes empty tokens. This filter may be used directly within a filterchain. This filter deletes specified characters from tokens.<tokenfilter> <containsregex pattern="^ *SUITE\(.*,\s*(.*)\s*\).*" replace="void register_\1();"/> </tokenfilter>
Attribute | Description | Required |
chars | The characters to delete. This attribute is backslash enabled. | Yes |
This is an optional filter that executes a script in a Apache BSF or JSR 223 supported language. See the Script task for an explanation of scripts and dependencies.<tokenfilter> <deletecharacters chars="\t"/> <trim/> <ignoreblank/> </tokenfilter>
The script is provided with an object self that has getToken() and setToken(String) methods. The getToken() method returns the current token. The setToken(String) method replaces the current token.
This filter may be used directly within a filterchain.
Attribute | Description | Required |
language | The programming language the script is written in. Must be a supported Apache BSF or JSR 223 language | Yes |
manager | The script engine manager to use. See the script task for using this attribute. | No - default is "auto" |
src | The location of the script as a file, if not inline | No |
setbeans | whether to have all properties, references and targets as global variables in the script. | No, default is "true". |
classpath | The classpath to pass into the script. | No |
classpathref | The classpath to use, given as a reference to a path defined elsewhere. | No |
This filter can take a nested <classpath> element. See the script task on how to use this element.
Remove lines containing the string "bad" while copying text files:<tokenfilter> <scriptfilter language="javascript"> self.setToken(self.getToken().toUpperCase()); </scriptfilter> </tokenfilter>
<copy todir="dist"> <fileset dir="src" includes="**/*.txt"/> <filterchain> <scriptfilter language="beanshell"> if (self.getToken().indexOf("bad") != -1) { self.setToken(null); } </scriptfilter> </filterchain> </copy>
<typedef/>
. For
example a string filter that capitalizes words may be declared as:
This may be used as follows:package my.customant; import org.apache.tools.ant.filters.TokenFilter; public class Capitalize implements TokenFilter.Filter { public String filter(String token) { if (token.length() == 0) return token; return token.substring(0, 1).toUpperCase() + token.substring(1); } }
<typedef type="capitalize" classname="my.customant.Capitalize" classpath="my.customant.path"/> <copy file="input" tofile="output"> <filterchain> <tokenfilter> <stringtokenizer/> <capitalize/> </tokenfilter> </filterchain> </copy>