source: release-kits/lirk3/resources/gs3-release-maker/ant/docs/manual/CoreTypes/custom-programming.html@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 13.2 KB
Line 
1<html>
2 <head>
3 <meta http-equiv="Content-Language" content="en-us"></meta>
4<title>Custom Components</title>
5<link rel="stylesheet" type="text/css" href="../stylesheets/antmanual.css">
6 </head>
7 <body>
8 <h2>Custom Components</h2>
9 <h3>Overview</h3>
10 <p>
11 Custom components are conditions, selectors, filters and other
12 objects that are defined outside ant core.
13 </p>
14 <p>
15 In Ant 1.6 custom conditions, selectors and filters has
16 been overhauled.
17 </p>
18 <p>
19 It is now possible to define custom conditions, selectors and filters
20 that behave like Ant Core components.
21 This is achieved by allowing datatypes defined in build scripts
22 to be used as custom components if the class of the datatype
23 is compatible, or has been adapted by an adapter class.
24 </p>
25 <p>
26 The old methods of defining custom components are still supported.
27 </p>
28 <h3>Definition and use</h3>
29 <p>
30 A custom component is a normal Java class that implements a particular
31 interface or extends a particular class, or has been adapted to the
32 interface or class.
33 </p>
34 <p>
35 It is exactly like writing a
36 <a href="../develop.html#writingowntask">custom task</a>.
37 One defines attributes and nested elements by writing <i>setter</i>
38 methods and <i>add</i> methods.
39 </p>
40 <p>
41 After the class has been written, it is added to the ant system
42 by using <code>&lt;typedef&gt;</code>.
43 </p>
44 <h3><a name="customconditions">Custom Conditions</a></h3>
45 <p>
46 Custom conditions are datatypes that implement
47 <code>org.apache.tools.ant.taskdefs.condition.Condition</code>.
48 For example a custom condition that returns true if a
49 string is all upper case could be written as:
50 </p>
51 <blockquote>
52 <pre>
53package com.mydomain;
54
55import org.apache.tools.ant.BuildException;
56import org.apache.tools.ant.taskdefs.condition.Condition;
57
58public class AllUpperCaseCondition implements Condition {
59 private String value;
60
61 // The setter for the "value" attribute
62 public void setValue(String value) {
63 this.value = value;
64 }
65
66 // This method evaluates the condition
67 public boolean eval() {
68 if (value == null) {
69 throw new BuildException("value attribute is not set");
70 }
71 return value.toUpperCase().equals(value);
72 }
73}
74 </pre>
75 </blockquote>
76
77 <p>
78 Adding the condition to the system is achieved as follows:
79 </p>
80 <blockquote>
81 <pre>
82&lt;typedef
83 name="alluppercase"
84 classname="com.mydomain.AllUpperCaseCondition"
85 classpath="${mydomain.classes}"/&gt;
86 </pre>
87 </blockquote>
88 <p>
89 This condition can now be used wherever a Core Ant condition
90 is used.
91 </p>
92 <blockquote>
93 <pre>
94&lt;condition property="allupper"&gt;
95 &lt;alluppercase value="THIS IS ALL UPPER CASE"/&gt;
96&lt;/condition&gt;
97 </pre>
98 </blockquote>
99 <h3><a name="customselectors">Custom Selectors</a></h3>
100 <p>
101 Custom selectors are datatypes that implement
102 <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
103 </p>
104 <p>There is only one method required.
105 <code>public boolean isSelected(File basedir, String filename,
106 File file)</code>.
107 It returns true
108 or false depending on whether the given file should be
109 selected or not.
110 </p>
111 <p>
112 An example of a custom selection that selects filenames ending
113 in ".java" would be:
114 </p>
115 <blockquote>
116 <pre>
117package com.mydomain;
118import java.io.File;
119import org.apache.tools.ant.types.selectors.FileSelector;
120public class JavaSelector implements FileSelector {
121 public boolean isSelected(File b, String filename, File f) {
122 return filename.toLowerCase().endsWith(".java");
123 }
124}
125 </pre>
126 </blockquote>
127 <p>
128 Adding the selector to the system is achieved as follows:
129 </p>
130 <blockquote>
131 <pre>
132&lt;typedef
133 name="javaselector"
134 classname="com.mydomain.JavaSelector"
135 classpath="${mydomain.classes}"/&gt;
136 </pre>
137 </blockquote>
138 <p>
139 This selector can now be used wherever a Core Ant selector
140 is used, for example:
141 </p>
142 <blockquote>
143 <pre>
144&lt;copy todir="to"&gt;
145 &lt;fileset dir="src"&gt;
146 &lt;javaselector/&gt;
147 &lt;/fileset&gt;
148&lt;/copy&gt;
149 </pre>
150 </blockquote>
151
152 <p>
153 One may use
154 <code>org.apache.tools.ant.types.selectors.BaseSelector</code>,
155 a convenience class that provides reasonable default
156 behaviour.
157 It has some predefined behaviours you can take advantage
158 of. Any time you encounter a problem when setting attributes or
159 adding tags, you can call setError(String errmsg) and the class
160 will know that there is a problem. Then, at the top of your
161 <code>isSelected()</code> method call <code>validate()</code> and
162 a BuildException will be thrown with the contents of your error
163 message. The <code>validate()</code> method also gives you a
164 last chance to check your settings for consistency because it
165 calls <code>verifySettings()</code>. Override this method and
166 call <code>setError()</code> within it if you detect any
167 problems in how your selector is set up.
168 </p>
169 <p>
170 To write custom selector containers one should extend
171 <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
172 Implement the
173 <code>public boolean isSelected(File baseDir, String filename, File file)</code>
174 method to do the right thing. Chances are you'll want to iterate
175 over the selectors under you, so use
176 <code>selectorElements()</code> to get an iterator that will do
177 that.
178 </p>
179 <p>
180 For example to create a selector container that will select files
181 if a certain number of contained selectors select, one could write
182 a selector as follows:
183 </p>
184 <blockquote>
185 <pre>
186public class MatchNumberSelectors extends BaseSelectorContainer {
187 private int number = -1;
188 public void setNumber(int number) {
189 this.number = number;
190 }
191 public void verifySettings() {
192 if (number &lt; 0) {
193 throw new BuildException("Number attribute should be set");
194 }
195 }
196 public boolean isSelected(File baseDir, String filename, File file) {
197 validate();
198 int numberSelected = 0;
199 for (Enumeration e = selectorElements(); e.hasNextElement();) {
200 FileSelector s = (FileSelector) e.nextElement();
201 if (s.isSelected(baseDir, filename, file)) {
202 numberSelected++;
203 }
204 }
205 return numberSelected == number;
206 }
207}
208 </pre>
209 </blockquote>
210 <p>
211 To define and use this selector one could do:
212 </p>
213 <blockquote>
214 <pre>
215&lt;typedef name="numberselected"
216 classname="com.mydomain.MatchNumberSelectors"/&gt;
217...
218&lt;fileset dir="${src.path}"&gt;
219 &lt;numberselected number="2"&gt;
220 &lt;contains text="script" casesensitive="no"/&gt;
221 &lt;size value="4" units="Ki" when="more"/&gt;
222 &lt;javaselector/&gt;
223 &lt;/numberselected&gt;
224&lt;/fileset&gt;
225 </pre>
226 </blockquote>
227 <p>
228 <i>The custom selector</i>
229 </p>
230 <p>
231 The custom selector was the pre ant 1.6 way of defining custom selectors.
232 This method is still supported for backward compatibility.
233 </p>
234 <p>You can write your own selectors and use them within the selector
235 containers by specifying them within the <code>&lt;custom&gt;</code> tag.</p>
236
237 <p>To create a new Custom Selector, you have to create a class that
238 implements
239 <code>org.apache.tools.ant.types.selectors.ExtendFileSelector</code>.
240 The easiest way to do that is through the convenience base class
241 <code>org.apache.tools.ant.types.selectors.BaseExtendSelector</code>,
242 which provides all of the methods for supporting
243 <code>&lt;param&gt;</code> tags. First, override the
244 <code>isSelected()</code> method, and optionally the
245 <code>verifySettings()</code> method. If your custom
246 selector requires parameters to be set, you can also override
247 the <code>setParameters()</code> method and interpret the
248 parameters that are passed in any way you like. Several of the
249 core selectors demonstrate how to do that because they can
250 also be used as custom selectors.</p>
251
252
253 <p>Once that is written, you include it in your build file by using
254 the <code>&lt;custom&gt;</code> tag.
255 </p>
256
257 <table border="1" cellpadding="2" cellspacing="0">
258 <tr>
259 <td valign="top"><b>Attribute</b></td>
260 <td valign="top"><b>Description</b></td>
261 <td align="center" valign="top"><b>Required</b></td>
262 </tr>
263 <tr>
264 <td valign="top">classname</td>
265 <td valign="top">The name of your class that implements
266 <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
267 </td>
268 <td valign="top" align="center">Yes</td>
269 </tr>
270 <tr>
271 <td valign="top">classpath</td>
272 <td valign="top">The classpath to use in order to load the
273 custom selector class. If neither this classpath nor the
274 classpathref are specified, the class will be
275 loaded from the classpath that Ant uses.
276 </td>
277 <td valign="top" align="center">No</td>
278 </tr>
279 <tr>
280 <td valign="top">classpathref</td>
281 <td valign="top">A reference to a classpath previously
282 defined. If neither this reference nor the
283 classpath above are specified, the class will be
284 loaded from the classpath that Ant uses.
285 </td>
286 <td valign="top" align="center">No</td>
287 </tr>
288 </table>
289
290 <p>Here is how you use <code>&lt;custom&gt;</code> to
291 use your class as a selector:
292 </p>
293
294 <blockquote><pre>
295&lt;fileset dir="${mydir}" includes="**/*"&gt;
296 &lt;custom classname="com.mydomain.MySelector"&gt;
297 &lt;param name="myattribute" value="myvalue"/&gt;
298 &lt;/custom&gt;
299&lt;/fileset&gt;
300 </pre></blockquote>
301
302
303 <p>The core selectors that can also be used as custom selectors
304 are</p>
305
306 <ul>
307 <li><a href="selectors.html#containsselect">Contains Selector</a> with
308 classname <code>org.apache.tools.ant.types.selectors.ContainsSelector</code>
309 </li>
310 <li><a href="selectors.html#dateselect">Date Selector</a> with
311 classname <code>org.apache.tools.ant.types.selectors.DateSelector</code>
312 </li>
313 <li><a href="selectors.html#depthselect">Depth Selector</a> with
314 classname <code>org.apache.tools.ant.types.selectors.DepthSelector</code>
315 </li>
316 <li><a href="selectors.html#filenameselect">Filename Selector</a> with
317 classname <code>org.apache.tools.ant.types.selectors.FilenameSelector</code>
318 </li>
319 <li><a href="selectors.html#sizeselect">Size Selector</a> with
320 classname <code>org.apache.tools.ant.types.selectors.SizeSelector</code>
321 </li>
322 </ul>
323
324 <p>Here is the example from the Depth Selector section rewritten
325 to use the selector through <code>&lt;custom&gt;</code>.</p>
326
327 <blockquote><pre>
328&lt;fileset dir="${doc.path}" includes="**/*"&gt;
329 &lt;custom classname="org.apache.tools.ant.types.selectors.DepthSelector"&gt;
330 &lt;param name="max" value="1"/&gt;
331 &lt;/custom&gt;
332&lt;/fileset&gt;
333 </pre></blockquote>
334
335 <p>Selects all files in the base directory and one directory below
336 that.</p>
337
338 <h3><a name="filterreaders">Custom Filter Readers</a></h3>
339 <p>
340 Custom filter readers selectors are datatypes that implement
341 <code>org.apache.tools.ant.types.filters.ChainableReader</code>.
342 </p>
343 <p>There is only one method required.
344 <code>Reader chain(Reader reader)</code>.
345 This returns a reader that filters input from the specified
346 reader.
347 </p>
348 <p>
349 For example a filterreader that removes every second character
350 could be:
351 </p>
352 <blockquote>
353 <pre>
354public class RemoveOddCharacters implements ChainableReader {
355 public Reader chain(Reader reader) {
356 return new BaseFilterReader(reader) {
357 int count = 0;
358 public int read() throws IOException {
359 while (true) {
360 int c = in.read();
361 if (c == -1) {
362 return c;
363 }
364 count++;
365 if ((count % 2) == 1) {
366 return c;
367 }
368 }
369 }
370 }
371 }
372}
373 </pre>
374 </blockquote>
375 <p>
376 For line oriented filters it may be easier to extend
377 <code>ChainableFilterReader</code> an inner class of
378 <code>org.apache.tools.ant.filters.TokenFilter</code>.
379 </p>
380 <p>
381 For example a filter that appends the line number could be
382 </p>
383 <blockquote>
384 <pre>
385public class AddLineNumber extends ChainableReaderFilter {
386 private void lineNumber = 0;
387 public String filter(String string) {
388 lineNumber++;
389 return "" + lineNumber + "\t" + string;
390 }
391}
392 </pre>
393 </blockquote>
394
395
396 <hr></hr>
397 <p align="center">Copyright &copy; 2003-2004 The Apache Software Foundation. All rights
398 Reserved.</p>
399 </body>
400</html>
401
Note: See TracBrowser for help on using the repository browser.