source: other-projects/trunk/realistic-books/packages/AntInstaller/web/manual/ant_task_guidelines.html@ 19253

Last change on this file since 19253 was 19253, checked in by davidb, 15 years ago

Establishing a source code repository for Veronica's Realistic Book's software

File size: 20.2 KB
Line 
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
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16-->
17<html><head>
18<title>
19Apache Ant Task Design Guidelines
20</title>
21</head><body>
22
23<h1>Apache Ant Task Design Guidelines</h1>
24
25This document covers how to write Ant tasks to a standard required to be
26incorporated into the Ant distribution. You may find it useful when
27writing tasks for personal use as the issues it addresses are still
28there in such a case.
29
30<h2>Don't break existing builds</h2>
31
32Even if you find some really hideous problem with Ant, one that is easy to fix,
33if your fix breaks an existing build file then we have problems. Making sure
34that every build file out there still works is one of the goals of all changes.
35As an example of this, Ant 1.5 passes the single dollar sign &quot;$&quot;
36through in strings; Ant 1.4 and before would strip it. To get this fix in we
37first had to write the test suite to expose current behaviour, then change
38something so that single &quot;$&quot; was passed through, but double
39&quot;$$&quot; got mapped to &quot;$&quot; for backwards compatibility.
40
41<h2>Don't break the Java API</h2>
42
43Ant's tasks can be used by third party programs and tasks.
44We cannot make changes that break the API. This includes:
45<ol>
46<li>Moving classes without leaving a backwards-compatible facade.
47<li>Deleting classes.
48<li>Deleting methods or fields, or reducing their accessibility.
49<li>Changing the signature of a <tt>setAttribute(Type)</tt> method. If you need
50to add a restrictive type, add a new attribute, and place it in the source
51<i>above</i> the original. The XML mapper will get the restricted type, old programs
52can still use the old type.
53<li>Don't change semantics. At least, not drastically. All bug fixes are
54implicit changes of semantics, after all.
55</ol>
56
57<h2>Use built in helper classes</h2>
58
59Ant includes helper tasks to simplify much of your work. It is much better to
60use them than roll your own, for development, maintenance and code size reasons.
61
62<h4>Execute</h4>
63
64Execute will spawn off separate programs under all the platforms which
65Ant supports, dealing with Java version issues as well as platform
66issues. Always use this class to invoke other programs.
67
68<h4>Java, ExecuteJava</h4>
69
70These classes can be used to spawn Java programs in a separate VM (they
71use execute) or in the same VM--with or without a different classloader.
72When deriving tasks from this, it often benefits users to permit the
73classpath to be specified, and for forking to be an optional attribute.
74
75<h4>Project and related classes</h4>
76
77Project, FileUtils, JavaEnvUtils all have helper functions to do things like
78touch a file, copy a file and the like. Use these instead of coding them
79yourself or trying to use tasks which may be less stable and fiddlier to use.
80
81<h2>Obey the Sun/Java style guidelines</h2>
82
83The Ant codebase aims to have a single unified coding standard, and that
84standard is the
85<a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html">
86Sun Java coding guidelines
87</a>
88<p>
89
90It's not that they are better than any alternatives, but they are a
91standard and they are what is consistently used in the rest of the
92tasks. Code will not be incorporated into the database until it complies
93with these.
94
95<p>
96
97If you are writing a task for your personal or organisational use, you
98are free to use whatever style you like. But using the Sun Java style
99will help you to become comfortable with the rest of the Ant source,
100which may be important.
101
102<p>
103
104One important rule is 'no tabs'. Use four spaces instead. Not two,
105not eight, four. Even if your editor is configured to have a tab of four
106spaces, lots of others aren't. Spaces have more consistency across
107editors and platforms. Some IDEs (JEdit) can highlight tabs, to stop you
108accidentally inserting them.
109<p>
110There is an Ant build file check.xml in the main ant directory with runs
111 <a href="http://checkstyle.sourceforge.net">checkstyle</a> over
112 Ant's source code.
113
114<h2>Attributes and elements</h2>
115Use the Ant introspection-based mapping of attributes into Java datatypes,
116rather than implementing all your attributes as setFoo(String) and doing
117the mapping to int, boolean or File yourself. This saves work on your part,
118lets Java callers use you in a typesafe manner, and will let the Xdocs
119documentation generator work out what the parameters are.
120
121<p>
122The Ant 1.x tasks are very inconsistent regarding naming of attributes--some
123tasks use <tt>source</tt>, others <tt>src</tt>.
124Here is a list of preferred attribute names:
125<p>
126<table cellpadding="5">
127<tr>
128<td>
129 failonerror
130</td>
131<td>
132 boolean to control whether failure to execute should throw a
133 <tt>BuildException</tt> or just print an error.
134 Parameter validation failures should always throw an error, regardless
135 of this flag.
136</td>
137</tr>
138<tr>
139<td>
140 destdir
141</td>
142<td>
143 destination directory for output
144</td>
145</tr>
146<tr>
147<td>
148 destfile
149</td>
150<td>
151 destination file for output
152</td>
153</tr>
154<tr>
155<td>
156 srcdir
157</td>
158<td>
159 source directory
160</td>
161</tr>
162<tr>
163<td>
164 srcfile
165</td>
166<td>
167 source file
168</td>
169</tr>
170</table>
171<p>
172Yes, this is a very short list. Try and be vaguely consistent with the core
173tasks, at the very least.
174
175<h2>Support classpaths</h2>
176
177Try and make it possible for people to supply a classpath to your task,
178if you need external libraries, rather than make them add everything to
179the ANT_HOME/lib directory. This lets people keep the external libraries
180in their Ant-based project, rather than force all users to make changes
181to their Ant system configuration.
182
183<h2>Design for controlled re-use</h2>
184
185Keep member variables private. If read access by subclasses is required,
186add accessor methods rather than change the accessiblity of the member.
187This enables subclasses to access the contents, yet still be decoupled
188from the actual implementation.
189<p>
190
191The other common re-use mechanism in Ant is for one task to create and
192configure another. This is fairly simple. There are facilities available in
193Ant's API to have the tasks instantiated by their familiar names
194(&quot;java&quot;, &quot;exec&quot;, etc.). It is recommended that you
195<b>not</b> use this approach because of the entirely real possibility that a
196user has overridden the name to point to a different class entirely. Use direct
197constructor calls (or reflection) to instantiate your subtask. Since Ant 1.6.3,
198you can call <code>org.apache.tools.ant.Task#bindToOwner()</code>
199to &quot;mask&quot; a helper task as its parent.
200
201<h2>Do your own Dependency Checking</h2>
202
203Make has the edge over Ant in its integrated dependency checking; the
204command line apps make invokes don't need to do their own work. Ant tasks
205do have to do their own dependency work, but if this can be done then
206it can be done well. A good dependency-aware task can work out the dependencies
207without explicit dependency information in the build file, and be smart
208enough to work out the real dependencies, perhaps through a bit of file parsing.
209The <tt>depends</tt> task is the best example of this. Some of the zip/jar
210tasks are pretty good too, as they can update the archive when needed.
211Most tasks just compare source and destination timestamps and work from there.
212Tasks which don't do any dependency checking do not help users as much as
213they can, because their needless work can trickle through the entire build, test
214and deploy process.
215
216<h2>Support Java 1.2 through Java 1.5+</h2>
217
218Ant 1.5 and lower was designed to support Java 1.1. Ant 1.6 and higher
219is designed to support Java 1.2: to build on it, to run on it. Sometimes
220functionality of tasks have to degrade in that environment--usually due to
221library limitations; such behaviour change must always be noted in the
222documentation.
223<p>
224What is problematic is code which is dependent on Java 1.3 features;
225e.g. java.lang.reflect.Proxy, or Java 1.4 features; e.g. java.io.nio.
226Be also aware of extra methods in older classes;
227e.g. StringBuffer#append(StringBuffer). These cannot be used directly
228by any code and still be able to compile and run on a Java 1.2 system.
229If a new method in an existing class is to be used, it must be used via
230reflection and the <tt>NoSuchMethodException</tt> handled somehow.
231<p>
232What if code simply does not work on Java 1.2? It can happen. It will
233probably be OK to have the task as an optional task, with compilation
234restricted to Java 1.3 or later through build.xml modifications.
235Better still, use reflection to link to the classes at run time.
236<p>
237Java 1.4 adds a new optional change to the language itself, the
238<tt>assert</tt> keyword, which is only enabled if the compiler is told
239to compile 1.4 version source. Clearly with the 1.2 compatibility requirement,
240Ant tasks cannot use this keyword. They also need to move away from
241using the JUnit <tt>assert()</tt> method and call <tt>assertTrue()</tt>
242instead.
243<p>
244Java 1.5 adds the <tt>enum</tt> type; again, this must not be used.
245
246<h2>Explicitly Expand properties in nested text</h2>
247
248For historical reasons, <tt>addText(String text)</tt> is called to
249set the task's nested text, without any property expansion taking place.
250Call <tt>Project.replaceProperties()</tt> to do this manually.
251If you forget, you create a problem that is impossible to fix
252without breaking users' build files.
253
254<h2>Refactor</h2>
255
256If the changes made to a task are making it too unwieldy, split it up
257into a cleaner design, refactor the code and submit not just feature
258creep but cleaner tasks. A common design pattern which tends to occur in
259the Ant process is the adoption of the adapter pattern, in which a base
260class (say Javac or Rmic) starts off simply, then gets convoluted with
261support for multiple back ends: javac, jikes, jvc. A refactoring to
262split the programmable front end from the classes which provide the back
263end cleans up the design and makes it much easier to add new back ends.
264But to carry this off one needs to keep the interface and behaviour of
265the front end identical, and to be sure that no subclasses have been
266accessing data members directly, because these data members may not
267exist in the refactored design. This is why having private data members
268is so important.
269
270<p>
271
272One thing we must not do is move existing tasks around or delete them.
273Remember that Ant has a Java API as well as an XML language. We don't want
274to break that API, or anything that subclasses existing Ant tasks. When
275refactoring, you need to leave facades where the original classes were. so
276existing code does not break.
277
278<h2>Test</h2>
279
280Look in <tt>ant/src/testcases</tt> and you will find JUnit tests for the
281shipping Ant tasks, to see how it is done and what is expected of a new
282task. Most of them are rudimentary, and no doubt you could do better for
283your task--feel free to do so!
284
285<p>
286
287A well written set of test cases will break the Ant task while it is in
288development, until the code is actually complete. And every bug which
289surfaces later should have a test case added to demonstrate the problem,
290and to fix it.
291
292<p>
293
294The test cases are a great way of testing your task during development.
295A simple call to 'build run-test' in the ant source tree will run all ant
296tests, to verify that your changes don't break anything.
297To test a single task, use the one shot <code>ant run-single-test
298-Dtestcase=${testname}</code> where <code>${testname}</code>
299is the name of your test class.
300
301<p>
302
303The test cases are also used by the committers to verify that changes
304and patches do what they say. If you've got test cases it increases your
305credibility significantly. To be precise, we hate submissions without
306test cases, as it means we have to write them ourselves. This is
307something that only gets done if we need the task or it is perceived as
308utterly essential to many users.
309
310<p>
311
312Remember also that Ant 1.x is designed to compile and run on Java 1.2, so
313you should test on Java 1.2 as well as any later version which you use.
314You ought to be able to download an old SDK from Sun for this purpose.
315<p>
316Finally, run a full <code>build test</code> before and after you start
317developing your project, to make sure you haven't broken anything else by
318accident.
319
320<h2>Document</h2>
321
322Without documentation, the task can't be used. So remember to provide a
323succinct and clear html (soon, xml) page describing the task in a similar
324style to that of existing tasks. It should include a list of attributes
325and elements, and at least one working example of the task. Many users
326cut and paste the examples into their build files as a starting point,
327so make the examples practical and test them too.
328<p>
329You can use the xdocs stuff in proposal/xdocs to autogenerate your
330documentation page from the javadocs of the source; this makes life
331easier and will make the transition to a full xdoclet generated
332documentation build process trivial.
333
334<h2>Licensing and Copyright</h2>
335
336Any code submitted to the Apache project must be compatible with the
337Apache Software License, and the act of submission must be viewed as
338an implicit license of the submitted code to the Apache Software
339Foundation.
340
341<p>
342This is important.
343
344<p>
345
346The fairly laissez-faire license of Apache is not currently considered
347compatible with
348either the GPL or the Lesser GPL of the Free Software Foundation--the
349Gnu project. These licenses have stricter terms, &quot;copyleft&quot;,
350which are not in the Apache Software Foundation license.
351This permits people and organisations to build
352commercial and closed source applications atop the Apache libraries and source.
353
354<p>
355
356Because the Gnu GPL license immediately extends to cover any larger
357application (or library, in the case of LGPL) into which it is
358incorporated, the Ant team cannot incorporate any task based upon GPL
359or LGPL source into the Ant codebase. You are free to submit it, but it
360will be politely and firmly rejected.
361
362<p>
363If you link to a GPL or LGPL library, by <code>import</code> or
364reflection, your task must be licensed under the same terms. So tasks
365linking to (L)GPL code can't go into the Apache managed codebase.
366Tasks calling such code can use the 'exec' or 'java' tasks to run the
367programs, as you are just executing them at this point, not linking to
368them.
369<p>
370Even if we cannot include your task into the Apache codebase, we can
371still point to where you host it; just submit a diff to
372xdocs/external.html pointing to your task.
373<p>
374If your task links directly to proprietary code, we have a different
375problem: it is really hard to build the tasks. Please use reflection.
376
377<h3>Don't re-invent the wheel</h3>
378
379We've all done it: written and submitted a task only to discover it
380was already implemented in a small corner of another task, or it has
381been submitted by someone else and not committed. You can avoid this
382by being aware of what is in the latest CVS tree; keep getting the daily
383source updates, look at manual changes and subscribe to the dev
384mailing list.
385
386<p>
387
388If you are thinking of writing a task, posting a note on your thoughts
389to the list can be informative--you will get other peoples' insights and
390maybe some half-written task to do the basics, all without writing a
391line of code.
392
393<h2>Submitting to Ant</h2>
394
395The basic mechanism for submitting an Ant task is to mail it to the
396dev mailing list. It helps to be on this list, as you will see other
397submissions, and any debate about your own submission.
398<p>
399You may create your patch file using either of the following approaches
400(the committers recommend the first):
401<p>
402<ul>
403<li><h3>Approach 1 - The Ant Way</h3>
404<p>
405Use Ant to generate a patch file to Ant:
406<pre class="code">
407ant -f patch.xml
408</pre>
409This will create a file named patch.tar.gz that will contain a unified
410diff of files that have been modified and also include files that have
411been added. Review the file for completeness and correctness. This approach
412is recommended because it standardizes the way in which patch files are
413constructed. It also eliminates the chance of you missing to submit new files
414that constitute part of the patch.
415<p>
416<li><h3>Approach 2 - The Manual Way</h3>
417<p>
418Patches to existing files should be generated with
419<code>svn diff -u filename</code>
420 and save the output to a file. If you want to get
421the changes made to multiple files in a directory , just use <code>cvs
422diff -u</code>. Then, Tar and GZip the patch file as well as any new files
423that you have added.
424</ul>
425<p>
426The patches should be sent as an attachment to a message titled [PATCH]
427and distinctive one-line summary in the subject of the patch. The
428filename/task and the change usually suffices. It's important to include
429the changes as an attachment, as too many mailers reformat the text
430pasted in, which breaks the patch.
431<p>
432Then you wait for one of the committers to commit the patch, if it is
433felt appropriate to do so. Bug fixes go in quickly, other changes
434often spark a bit of discussion before a (perhaps revised) commit is
435made.
436<p>
437
438New submissions should be proceeded with [SUBMIT]. The mailer-daemon
439will reject any messages over 100KB, so any large update should be
440zipped up. If your submission is bigger than that, why not break it up
441into separate tasks.
442<p>
443
444We also like submissions to be added to
445<a href="http://issues.apache.org/bugzilla/">bugzilla</a>, so that they dont get lost. Please submit them by first filing the report with a
446meaningful name, then adding files as attachments. Use CVS diff files
447please!
448<p>
449
450If you hear nothing after a couple of weeks, remind the mailing list.
451Sometimes really good submissions get lost in the noise of other issues.
452This is particularly the case just prior to a new point release of
453the product. At that time anything other than bug fixes will tend
454to be neglected.
455
456<h2>Checklists</h2>
457
458These are the things you should verify before submitting patches and new
459tasks. Things don't have to be perfect; it may take a couple of
460iterations before a patch or submission is committed, and these items
461can be addressed in the process. But by the time the code is committed,
462everything including the documentation and some test cases will have
463been done, so getting them out the way up front can save time.
464The committers look more favourably on patches and submissions with test
465cases, while documentation helps sell the reason for a task.
466
467<h3>Checklist before submitting a patch</h3>
468<ul>
469<li>Added code complies with style guidelines
470<li>Code compiles and runs on Java 1.2
471<li>New member variables are private, and provide public accessor methods
472 if access is actually needed.
473<li>Existing test cases succeed.
474<li>New test cases written and succeed.
475<li>Documentation page extended as appropriate.
476<li>Example task declarations in the documentation tested.
477<li>Diff files generated using svn diff -u
478<li>Message to dev contains [PATCH], task name and patch reason in
479subject.
480<li>Message body contains a rationale for the patch.
481<li>Message attachment contains the patch file(s).
482</ul>
483
484<h3>Checklist before submitting a new task</h3>
485<ul>
486<li>Java file begins with Apache copyright and license statement.
487<li>Task does not depend on GPL or LGPL code.
488<li>Source code complies with style guidelines
489<li>Code compiles and runs on Java 1.2
490<li>Member variables are private, and provide public accessor methods
491 if access is actually needed.
492<li><i>Maybe</i> Task has failonerror attribute to control failure behaviour
493<li>New test cases written and succeed
494<li>Documentation page written
495<li>Example task declarations in the documentation tested.
496<li>Patch files generated using svn diff -u
497<li>patch files include a patch to defaults.properties to register the
498tasks
499<li>patch files include a patch to coretasklist.html or
500optionaltasklist.html to link to the new task page
501<li>Message to dev contains [SUBMIT] and task name in subject
502<li>Message body contains a rationale for the task
503<li>Message attachments contain the required files -source, documentation,
504test and patches zipped up to escape the HTML filter.
505</ul>
506
507
508</body></html>
Note: See TracBrowser for help on using the repository browser.