| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <html> |
| <head> |
| <meta http-equiv="Content-Language" content="en-us"></meta> |
| <link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> |
| <title>Custom Components</title> |
| </head> |
| <body> |
| <h2>Custom Components</h2> |
| <h3>Overview</h3> |
| <p> |
| Custom components are conditions, selectors, filters and other |
| objects that are defined outside ant core. |
| </p> |
| <p> |
| In Ant 1.6 custom conditions, selectors and filters has |
| been overhauled. |
| </p> |
| <p> |
| 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. |
| </p> |
| <p> |
| The old methods of defining custom components are still supported. |
| </p> |
| <h3>Definition and use</h3> |
| <p> |
| 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. |
| </p> |
| <p> |
| It is exactly like writing a |
| <a href="../develop.html#writingowntask">custom task</a>. |
| One defines attributes and nested elements by writing <i>setter</i> |
| methods and <i>add</i> methods. |
| </p> |
| <p> |
| After the class has been written, it is added to the ant system |
| by using <code><typedef></code>. |
| </p> |
| <h3><a name="customconditions">Custom Conditions</a></h3> |
| <p> |
| Custom conditions are datatypes that implement |
| <code>org.apache.tools.ant.taskdefs.condition.Condition</code>. |
| For example a custom condition that returns true if a |
| string is all upper case could be written as: |
| </p> |
| <blockquote> |
| <pre> |
| package com.mydomain; |
| |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.taskdefs.condition.Condition; |
| |
| public class AllUpperCaseCondition implements 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); |
| } |
| } |
| </pre> |
| </blockquote> |
| |
| <p> |
| Adding the condition to the system is achieved as follows: |
| </p> |
| <blockquote> |
| <pre> |
| <typedef |
| name="alluppercase" |
| classname="com.mydomain.AllUpperCaseCondition" |
| classpath="${mydomain.classes}"/> |
| </pre> |
| </blockquote> |
| <p> |
| This condition can now be used wherever a Core Ant condition |
| is used. |
| </p> |
| <blockquote> |
| <pre> |
| <condition property="allupper"> |
| <alluppercase value="THIS IS ALL UPPER CASE"/> |
| </condition> |
| </pre> |
| </blockquote> |
| <h3><a name="customselectors">Custom Selectors</a></h3> |
| <p> |
| Custom selectors are datatypes that implement |
| <code>org.apache.tools.ant.types.selectors.FileSelector</code>. |
| </p> |
| <p>There is only one method required. |
| <code>public boolean isSelected(File basedir, String filename, |
| File file)</code>. |
| It returns true |
| or false depending on whether the given file should be |
| selected or not. |
| </p> |
| <p> |
| An example of a custom selection that selects filenames ending |
| in ".java" would be: |
| </p> |
| <blockquote> |
| <pre> |
| package com.mydomain; |
| import java.io.File; |
| import org.apache.tools.ant.types.selectors.FileSelector; |
| public class JavaSelector implements FileSelector { |
| public boolean isSelected(File b, String filename, File f) { |
| return filename.toLowerCase().endsWith(".java"); |
| } |
| } |
| </pre> |
| </blockquote> |
| <p> |
| Adding the selector to the system is achieved as follows: |
| </p> |
| <blockquote> |
| <pre> |
| <typedef |
| name="javaselector" |
| classname="com.mydomain.JavaSelector" |
| classpath="${mydomain.classes}"/> |
| </pre> |
| </blockquote> |
| <p> |
| This selector can now be used wherever a Core Ant selector |
| is used, for example: |
| </p> |
| <blockquote> |
| <pre> |
| <copy todir="to"> |
| <fileset dir="src"> |
| <javaselector/> |
| </fileset> |
| </copy> |
| </pre> |
| </blockquote> |
| |
| <p> |
| One may use |
| <code>org.apache.tools.ant.types.selectors.BaseSelector</code>, |
| 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 |
| <code>isSelected()</code> method call <code>validate()</code> and |
| a BuildException will be thrown with the contents of your error |
| message. The <code>validate()</code> method also gives you a |
| last chance to check your settings for consistency because it |
| calls <code>verifySettings()</code>. Override this method and |
| call <code>setError()</code> within it if you detect any |
| problems in how your selector is set up. |
| </p> |
| <p> |
| To write custom selector containers one should extend |
| <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>. |
| Implement the |
| <code>public boolean isSelected(File baseDir, String filename, File file)</code> |
| method to do the right thing. Chances are you'll want to iterate |
| over the selectors under you, so use |
| <code>selectorElements()</code> to get an iterator that will do |
| that. |
| </p> |
| <p> |
| 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: |
| </p> |
| <blockquote> |
| <pre> |
| 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; |
| } |
| } |
| </pre> |
| </blockquote> |
| <p> |
| To define and use this selector one could do: |
| </p> |
| <blockquote> |
| <pre> |
| <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> |
| </pre> |
| </blockquote> |
| <p> |
| <i>The custom selector</i> |
| </p> |
| <p> |
| The custom selector was the pre ant 1.6 way of defining custom selectors. |
| This method is still supported for backward compatibility. |
| </p> |
| <p>You can write your own selectors and use them within the selector |
| containers by specifying them within the <code><custom></code> tag.</p> |
| |
| <p>To create a new Custom Selector, you have to create a class that |
| implements |
| <code>org.apache.tools.ant.types.selectors.ExtendFileSelector</code>. |
| The easiest way to do that is through the convenience base class |
| <code>org.apache.tools.ant.types.selectors.BaseExtendSelector</code>, |
| which provides all of the methods for supporting |
| <code><param></code> tags. First, override the |
| <code>isSelected()</code> method, and optionally the |
| <code>verifySettings()</code> method. If your custom |
| selector requires parameters to be set, you can also override |
| the <code>setParameters()</code> 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.</p> |
| |
| |
| <p>Once that is written, you include it in your build file by using |
| the <code><custom></code> tag. |
| </p> |
| |
| <table border="1" cellpadding="2" cellspacing="0"> |
| <tr> |
| <td valign="top"><b>Attribute</b></td> |
| <td valign="top"><b>Description</b></td> |
| <td align="center" valign="top"><b>Required</b></td> |
| </tr> |
| <tr> |
| <td valign="top">classname</td> |
| <td valign="top">The name of your class that implements |
| <code>org.apache.tools.ant.types.selectors.FileSelector</code>. |
| </td> |
| <td valign="top" align="center">Yes</td> |
| </tr> |
| <tr> |
| <td valign="top">classpath</td> |
| <td valign="top">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. |
| </td> |
| <td valign="top" align="center">No</td> |
| </tr> |
| <tr> |
| <td valign="top">classpathref</td> |
| <td valign="top">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. |
| </td> |
| <td valign="top" align="center">No</td> |
| </tr> |
| </table> |
| |
| <p>Here is how you use <code><custom></code> to |
| use your class as a selector: |
| </p> |
| |
| <blockquote><pre> |
| <fileset dir="${mydir}" includes="**/*"> |
| <custom classname="com.mydomain.MySelector"> |
| <param name="myattribute" value="myvalue"/> |
| </custom> |
| </fileset> |
| </pre></blockquote> |
| |
| |
| <p>The core selectors that can also be used as custom selectors |
| are</p> |
| |
| <ul> |
| <li><a href="selectors.html#containsselect">Contains Selector</a> with |
| classname <code>org.apache.tools.ant.types.selectors.ContainsSelector</code> |
| </li> |
| <li><a href="selectors.html#dateselect">Date Selector</a> with |
| classname <code>org.apache.tools.ant.types.selectors.DateSelector</code> |
| </li> |
| <li><a href="selectors.html#depthselect">Depth Selector</a> with |
| classname <code>org.apache.tools.ant.types.selectors.DepthSelector</code> |
| </li> |
| <li><a href="selectors.html#filenameselect">Filename Selector</a> with |
| classname <code>org.apache.tools.ant.types.selectors.FilenameSelector</code> |
| </li> |
| <li><a href="selectors.html#sizeselect">Size Selector</a> with |
| classname <code>org.apache.tools.ant.types.selectors.SizeSelector</code> |
| </li> |
| </ul> |
| |
| <p>Here is the example from the Depth Selector section rewritten |
| to use the selector through <code><custom></code>.</p> |
| |
| <blockquote><pre> |
| <fileset dir="${doc.path}" includes="**/*"> |
| <custom classname="org.apache.tools.ant.types.selectors.DepthSelector"> |
| <param name="max" value="1"/> |
| </custom> |
| </fileset> |
| </pre></blockquote> |
| |
| <p>Selects all files in the base directory and one directory below |
| that.</p> |
| |
| <h3><a name="filterreaders">Custom Filter Readers</a></h3> |
| <p> |
| Custom filter readers selectors are datatypes that implement |
| <code>org.apache.tools.ant.types.filters.ChainableReader</code>. |
| </p> |
| <p>There is only one method required. |
| <code>Reader chain(Reader reader)</code>. |
| This returns a reader that filters input from the specified |
| reader. |
| </p> |
| <p> |
| For example a filterreader that removes every second character |
| could be: |
| </p> |
| <blockquote> |
| <pre> |
| 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; |
| } |
| } |
| } |
| } |
| } |
| } |
| </pre> |
| </blockquote> |
| <p> |
| For line oriented filters it may be easier to extend |
| <code>ChainableFilterReader</code> an inner class of |
| <code>org.apache.tools.ant.filters.TokenFilter</code>. |
| </p> |
| <p> |
| For example a filter that appends the line number could be |
| </p> |
| <blockquote> |
| <pre> |
| public class AddLineNumber extends ChainableReaderFilter { |
| private void lineNumber = 0; |
| public String filter(String string) { |
| lineNumber++; |
| return "" + lineNumber + "\t" + string; |
| } |
| } |
| </pre> |
| </blockquote> |
| |
| |
| <hr></hr> |
| </body> |
| </html> |
| |