| <html><head> |
| <title> |
| Apache Ant Task Design Guidelines |
| </title> |
| </head><body> |
| |
| <h1>Apache Ant Task Design Guidelines</h1> |
| |
| This document covers how to write ant tasks to a standard required to be |
| incorporated into the Ant distribution. You may find it useful when |
| writing tasks for personal use as the issues it addresses are still |
| there in such a case. |
| |
| |
| <h2>Use built in helper classes</h2> |
| |
| Ant includes helper tasks to simplify mauch of your work. Be warned that |
| these helper classes will look very different in ant2.0 from these 1.x |
| versions. However it is still better to use them than roll your own, for |
| development, maintenance and code size reasons. |
| |
| <h4>Execute</h4> |
| |
| Execute will spawn off separate programs under all the platforms which |
| ant supports, dealing with Java version issues as well as platform |
| issues. Always use this task to invoke other programs. |
| |
| <h4>Java, ExecuteJava</h4> |
| |
| These classes can be used to spawn Java programs in a separate VM (they |
| use execute) or in the same VM -with or without a different classloader. |
| When deriving tasks from this, it often benefits users to permit the |
| classpath to be specified, and for forking to be an optional attribute. |
| |
| |
| <h4>Project</h4> |
| |
| Project has some helper functions to touch a file, to |
| copy a file and the like. Use these instead of trying to code them |
| yourself -or trying to use tasks which may be less stable and fiddlier |
| to use. |
| |
| |
| <h2>Obey the Sun/Java style guidelines</h2> |
| |
| The Ant codebase aims to have a single unified coding standard, and that |
| standard is the |
| <a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html"> |
| Sun Java coding guidelines |
| </a> |
| <p> |
| |
| It's not that they are better than any alternatives, but they are a |
| standard and they are what is consistently used in the rest of the |
| tasks. Code will not be incorporated into the database until it complies |
| with these. |
| |
| <p> |
| |
| If you are writing a task for your personal or organisational use, you |
| are free to use whatever style you like. But using the Sun Java style |
| will help you to become comfortable with the rest of the Ant source, |
| which may be important. |
| |
| <p> |
| |
| One important rule is 'no tabs'. Use four spaces instead. Not two, |
| not eight, four. Even if your editor is configured to have a tab of four |
| spaces, lots of others aren't -spaces have more consistency across |
| editors and platforms. |
| |
| <h2>Recommended Names for attributes and elements</h2> |
| |
| The ant1.x tasks are very inconsistent regarding naming of attributes |
| -some tasks use source, others src. Here is a list of preferred attribute |
| names. |
| |
| <table> |
| <tr> |
| <td> |
| failonerror |
| </td> |
| <td> |
| boolean to control whether failure to execute should throw a |
| <tt>BuildException</tt> or just print an error. |
| Parameter validation failures should always throw an error, regardless |
| of this flag |
| </td> |
| </tr> |
| <tr> |
| <td> |
| destdir |
| </td> |
| <td> |
| destination directory for output |
| </td> |
| </tr> |
| </table> |
| Yes, this is a very short list. Try and be vaguely consistent with the core |
| tasks, at the very least. |
| |
| <h2>Design for controlled re-use</h2> |
| |
| Keep member variables private. If read access by subclasses is required. |
| add accessor methods rather than change the accessiblity of the member. |
| This enables subclasses to access the contents, yet |
| still be decoupled from the actual implementation. |
| <p> |
| |
| The other common re-use mechanism in ant is for one task to create and |
| configure another. This is fairly simple. |
| |
| <h2>Do your own Dependency Checking</h2> |
| |
| Make has the edge over Ant in its integrated dependency checking: the |
| command line apps make invokes dont need to do their own work. Ant tasks |
| do have to do their own dependency work, but if this can be done then |
| it can be done well. A good dependency aware task can work out the dependencies |
| without explicit dependency information in the build file, and be smart |
| enough to work out the real dependencies, perhaps through a bit of file parsing. |
| The <tt>depends</tt> task is the best example of this. Some of the zip/jar |
| tasks are pretty good too, as they can update the archive when needed. |
| Most tasks just compare source and destination timestamps and work from there. |
| Tasks which don't do any dependency checking do not help users as much as |
| they can, because their needless work can trickle through the entire build, test |
| and deploy process. |
| |
| <h2>Support Java 1.1 through Java 1.4</h2> |
| |
| Ant is designed to support Java1.1: to build on it, to run on it. Sometimes |
| functionality of tasks have to degrade in that environment -<touch> |
| is a case in point- this is usually due to library limitations; |
| such behaviour change must always be noted in the documentation. |
| <p> |
| What is problematic is code which is dependent on Java1.2 features |
| -Collections, Reader and Writer classes, extra methods in older classes. |
| These can not be used directly by any code and still be able to compile |
| and run on a Java 1.1 system. So please stick to the older collection |
| classes, and the older IO classes. If a new method in an existing class |
| is to be used, it must be used via reflection and the |
| <tt>NoSuchMethodException</tt> handled somehow. |
| <p> |
| What if code simply does not work on Java1.1? It can happen. It will |
| probably be OK to have the task as an optional task, with compilation |
| restricted to Java1.2 or later through build.xml modifications. |
| Better still, use reflection to link to the classes at run time. |
| <p> |
| Java 1.4 adds a new optional change to the language itself, the |
| <tt>assert</tt> keyword, which is only enabled if the compiler is told |
| to compile 1.4 version source. Clearly with the 1.1 compatibility requirement, |
| Ant tasks can not use this keyword. They also need to move away from |
| using the JUnit <tt>assert()</tt> method and start calling <tt>assertTrue()</tt> |
| instead. |
| |
| |
| |
| <h2>Refactor</h2> |
| |
| If the changes made to a task are making it too unwieldy, split it up |
| into a cleaner design, refactor the code and submit not just feature |
| creep but cleaner tasks. A common design pattern which tends to occur in |
| the ant process is the adoption of the adapter pattern, in which a base |
| class (say Javac or Rmi) starts off simple, then gets convoluted with |
| support for multiple back ends -javac, jikes, jvc. A refactoring to |
| split the programmable front end from the classes which provide the back |
| end cleans up the design and makes it much easier to add new back ends. |
| But to carry this off one needs to keep the interface and behaviour of |
| the front end identical, and to be sure that no subclasses have been |
| accessing data members directly -because these data members may not |
| exist in the refactored design. Which is why having private data members |
| is so important. |
| |
| |
| <h2>Test</h2> |
| |
| Look in <tt>jakarta-ant/src/testcases</tt> and you will find JUnit tests for the |
| shipping ant tasks, to see how it is done and what is expected of a new |
| task. Most of them are rudimentary, and no doubt you could do better for |
| your task -feel free to do so! |
| |
| <p> |
| |
| A well written set of test cases will break the Ant task while it is in |
| development, until the code is actually complete. And every bug which |
| surfaces later should have a test case added to demonstrate the problem, |
| and to fix it. |
| |
| <p> |
| |
| The test cases are a great way of testing your task during development. |
| A simple call to 'ant run-test' in the ant source tree will run all ant |
| tests, to verify that your changes don't break anything. |
| To test a single task, use the one shot <code>ant run-single-test |
| -Dtestcase=${testname}</code> where ${testname} is the name of your test class. |
| |
| |
| <p> |
| |
| The test cases are also used by the committers to verify that changes |
| and patches do what they say. If you've got test cases it increases your |
| credibility significantly. |
| |
| <p> |
| |
| Remember also that Ant 1.x is designed to compile and run on Java1.1, so |
| you should test on Java 1.1 as well as any later version which you use. |
| You can download an old SDK from Sun for this purpose. |
| |
| <h2>Document</h2> |
| |
| Without documentation, the task can't be used. So remember to provide a |
| succint and clear html (soon, xml) page describing the task in a similar |
| style to that of existing tasks. It should include a list of attributes |
| and elements, and at least one working example of the task. Many users |
| cut and paste the examples into their build files as a starting point, |
| so make the examples practical and test them too. |
| |
| <h2>Licensing and Copyright</h2> |
| |
| Any code submitted to the Apache project must be compatible with the |
| Apache Software License, and the act of submission must be viewed as an |
| implicit transfer of ownership of the submitted code to the Apache |
| Software Foundation. |
| |
| <p> |
| This is important. |
| |
| <p> |
| |
| The fairly laissez-faire license of Apache is not compabitible with |
| either the GPL or the Lesser GPL of the Free Software Foundation -the |
| Gnu project. Their license requires all changes to the source to be made |
| public, and give the licensee of any software the right to distribute |
| copies. It also requires derivative works to be made available under the |
| same license terms. None of these requirements are in the Apache Software |
| Foundation license, which permits people and organisations to build |
| commercial and closed source applications atop the Apache libraries and |
| source -but not use the Apache, Ant or Jakarta Project names without |
| permission. |
| |
| <p> |
| |
| Because the Gnu GPL license immediately extends to cover any larger |
| application (or library, in the case of GLPL) into which it is |
| incorporated, the Ant team can not incorporate any task based upon GPL |
| or LGPL source into the Ant codebase. You are free to submit it, but it |
| will be politely and firmly rejected. |
| |
| <p> |
| |
| Once ant-2 adds better dynamic task incorporation, it may be possible to |
| provide a framework for supporting [L]GPL code, but still no tasks |
| direcely subject to the Gnu licenses will ever be included in the Ant |
| CVS tree. |
| |
| <h3>Dont re-invent the wheel</h3> |
| |
| We've all done it: written and submitted a task only to discover it |
| was already implemented in a small corner of another task, or it has |
| been submitted by someone else and not committed. You can avoid this |
| by being aware of what is in the latest CVS tree -keep getting the daily |
| source updates, look at manual changes and subscribe to the ant-dev |
| mailing list. |
| |
| <p> |
| |
| If you are thinking of writing a task, posting a note on your thoughts |
| to the list can be informative -you well get other peoples insight and |
| maybe some half written task to do the basics, all without writing a |
| line of code. |
| |
| |
| <h2>Submitting to Ant</h2> |
| |
| The process for submitting an Ant task is documented on the |
| <a href="http://jakarta.apache.org/site/guidelines.html"> |
| jakarta web site</a>. |
| The basic mechanism is to mail it to the ant-dev mailing list. |
| It helps to be on this list, as you will see other submissions, and |
| any debate about your own submission. |
| <p> |
| |
| Patches to existing files should be generated with |
| <code>cvs diff -u filename</code> |
| and save the output to a file. If you want to get |
| the changes made to multiple files in a directory , just use <code>cvs |
| diff -u</code>. The patches should be sent as an attachment to a message titled [PATCH] |
| and distinctive one-line summary in the subject of the patch. The |
| filename/task and the change usually suffices. It's important to include |
| the changes as an attachment, as too many mailers reformat the text |
| pasted in, which breaks the patch. |
| <p> |
| Then you wait for one of the committers to commit the patch, if it is |
| felt appropriate to do so. Bug fixes go in quickly, other changes |
| often spark a bit of discussion before a (perhaps revised) commit is |
| made. |
| <p> |
| |
| New submissions should be proceeded with [SUBMIT]. The mailer-daemon |
| will reject any messages over 100KB, so any large update should be |
| zipped up. If your submission is bigger than that, why not break it up |
| into separate tasks. |
| <p> |
| |
| If you hear nothing after a couple of weeks, remind the mailing list. |
| Sometimes really good submissions get lost in the noise of other issues. |
| This is particularly the case just prior to a new point release of |
| the product. At that time anything other than bug fixes will tend |
| to be neglected. |
| |
| <h2>Checklists</h2> |
| |
| These are the things you should verify before submitting patches and new |
| tasks. Things don't have to be perfect, it may take a couple of |
| iterations before a patch or submission is committed, and these items |
| can be addressed in the process. But by the time the code is committed, |
| everything including the documentation and some test cases will have |
| been done, so by getting them out the way up front can save time. |
| The committers look more favourably on patches and submissions with test |
| cases, while documentation helps sell the reason for a task. |
| |
| <h3>Checklist before submitting a patch</h3> |
| <ul> |
| <li>Added code complies with style guidelines |
| <li>Code compiles and runs on Java1.1 |
| <li>New member variables are private, and provide public accessor methods |
| if access is actually needed. |
| <li>Existing test cases succeed. |
| <li>New test cases written and succeed. |
| <li>Documentation page extended as appropriate. |
| <li>Example task declarations in the documentation tested. |
| <li>Diff files generated using cvs diff -u |
| <li>Message to ant-dev contains [PATCH], task name and patch reason in |
| subject. |
| <li>Message body contains a rationale for the patch. |
| <li>Message attachment contains the patch file(s). |
| </ul> |
| |
| <h3>Checklist before submitting a new task</h3> |
| <ul> |
| <li>Java file begins with Apache copyright and license statement. |
| <li>Task does not depend on GPL or LGPL code. |
| <li>Source code complies with style guidelines |
| <li>Code compiles and runs on Java1.1 |
| <li>Member variables are private, and provide public accessor methods |
| if access is actually needed. |
| <li><i>Maybe</i> Task has failonerror attribute to control failure behaviour |
| <li>New test cases written and succeed |
| <li>Documentation page written |
| <li>Example task declarations in the documentation tested. |
| <li>Patch files generated using cvs diff -u |
| <li>patch files include a patch to defaults.properties to register the |
| tasks |
| <li>patch files include a patch to coretasklist.html or |
| optionaltasklist.html to link to the new task page |
| <li>Message to ant-dev contains [SUBMIT] and task name in subject |
| <li>Message body contains a rationale for the task |
| <li>Message attachments contain the required files -source, documentation, |
| test and patches |
| </ul> |
| <hr> |
| <p align="center">Copyright © 2001 Apache Software Foundation. All rights |
| Reserved.</p> |
| |
| </body></html> |
| |