You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

custom-programming.html 13 KiB

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