jhm 2003/09/29 07:30:17 Modified: docs/manual tutorial-tasks-filesets-properties.html Log: Second working draft. Ready for discussion. Revision Changes Path 1.2 +278 -51 ant/docs/manual/tutorial-tasks-filesets-properties.html Index: tutorial-tasks-filesets-properties.html =================================================================== RCS file: /home/cvs/ant/docs/manual/tutorial-tasks-filesets-properties.html,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- tutorial-tasks-filesets-properties.html 25 Sep 2003 17:39:53 -0000 1.1 +++ tutorial-tasks-filesets-properties.html 29 Sep 2003 14:30:17 -0000 1.2 @@ -1,6 +1,6 @@ <html> <head> - <title>Tutorial: Tasks using Properties & Filesets</title> + <title>Tutorial: Tasks using Properties, Filesets & Paths</title> <meta name="author" content="Jan Matčrne"> <style type="text/css"> <!-- @@ -10,15 +10,23 @@ </style> </head> <body> -<h1>Tutorial: Tasks using Properties & Filesets</h1> +<h1>Tutorial: Tasks using Properties, Filesets & Paths</h1> <p>After reading the tutorial about <a href="tutorial-writing-tasks.html">writing -tasks</a> this tutorial explains how to get and set properties and how to use -nested filesets and paths.</p> +tasks [1]</a> this tutorial explains how to get and set properties and how to use +nested filesets and paths. Finally it explains how to contribute tasks to Ant.</p> <h2>Content</h2> <p><ul> -<li><a href="#s">s</a></li> +<li><a href="#goal">The goal</a></li> +<li><a href="#buildenvironment">Build environment</a></li> +<li><a href="#propertyaccess">Property access</a></li> +<li><a href="#filesets">Using filesets</a></li> +<li><a href="#path">Using nested paths</a></li> +<li><a href="#returning-list">Returning a list</a></li> +<li><a href="#documentation">Documentation</a></li> +<li><a href="#contribute">Contribute the new task</a></li> +<li><a href="#resources">Resources</a></li> </ul></p> @@ -45,11 +53,15 @@ </project> </pre> +<p>The buildfile is in the archive <a href="tutorial-tasks-filesets-properties.zip"> +tutorial-tasks-filesets-properties.zip [2]</a> in <tt>/build.xml.01-propertyaccess</tt> +(future version saved as *.02..., final version as build.xml; same for sources).</p> + <a name="propertyaccess"/> <h2>Property access</h2> -<p>Our first step is to set a property to a value and print the value of property. So our scenario -would be +<p>Our first step is to set a property to a value and print the value of that property. +So our scenario would be <pre class="code"> <find property="test" value="test-value"/> <find print="test"/> @@ -60,8 +72,8 @@ <echo message="${test}"/> </pre> but I have to start on known ground :-)</p> -<p>So what to do? Handling three attributes (property, value, print) and an execute. Because this -is only an introduction example I donīt do much checking: +<p>So what to do? Handling three attributes (property, value, print) and an execute method. +Because this is only an introduction example I donīt do much checking: <pre class="code"> import org.apache.tools.ant.BuildException; @@ -92,10 +104,10 @@ </pre> As said in the other tutorial, the property access is done via Project instance. -This instance we get via the public <tt>getProject()</tt> method which we inherit from +We get this instance via the public <tt>getProject()</tt> method which we inherit from <tt>Task</tt> (more precise from ProjectComponent). Reading a property is done via <tt>getProperty(<i>propertyname</i>)</tt> (very simple, isnīt it?). This property returns -the value (String) or <i>null</i> if not set.<br> +the value as String or <i>null</i> if not set.<br> Setting a property is ... not really difficult, but there is more than one setter. You can use the <tt>setProperty()</tt> method which will do the job like expected. But there is a golden rule in Ant: <i>properties are immutable</i>. And this method sets the property @@ -153,8 +165,8 @@ </p> <p>What do we need? A task with two attributes (file, location) and nested -filesets. Because we had attribute handling already in the example above and the handling -of nested elements is described in the other tutorial the code should be very easy: +filesets. Because we had attribute handling already explained in the example above and the +handling of nested elements is described in the other tutorial the code should be very easy: <pre class="code"> public class Find extends Task { @@ -281,9 +293,9 @@ <p>On <b>//1</b> we check the prerequisites for our task. Doing that in a <tt>validate</tt>-method is a common way, because we separate the prerequisites from the real work. On <b>//2</b> we iterate -over all nested filesets. We we donīt want to handle multiple filesets, the <tt>addFileset()</tt> -method has to reject the further calls. We can get the result of fileset via its DirectoryScanner -like done <b>//3</b>. After that we create a plattform independend String representation of +over all nested filesets. If we donīt want to handle multiple filesets, the <tt>addFileset()</tt> +method has to reject the further calls. We can get the result of a fileset via its DirectoryScanner +like done in <b>//3</b>. After that we create a plattform independend String representation of the file path (<b>//4</b>, can be done in other ways of course). We have to do the <tt>replace()</tt>, because we work with a simple string comparison. Ant itself is platform independant and can therefore run on filesystems with slash (/, e.g. Linux) or backslash (\, e.g. Windows) as @@ -298,9 +310,10 @@ whithout being complex :-)</p> <p>The test case uses the ant property <i>ant.home</i> as reference. This property is set by the -<tt>Launcher</tt> class which starts ant. We can use that property in our buildfiles as a build-in -property (see [XXX]). But if we create a new ant environment we have to set that value for our own. -And we use the <junit< task in fork-mode. Therefore we have do modify our buildfile: +<tt>Launcher</tt> class which starts ant. We can use that property in our buildfiles as a +<a href="using.html#built-in-props">build-in property [3]</a>. But if we create a new ant +environment we have to set that value for our own. And we use the <junit> task in fork-mode. +Therefore we have do modify our buildfile: <pre class="code"> <target name="junit" description="Runs the unit tests" depends="jar"> <delete dir="${junit.out.dir.xml}" /> @@ -323,9 +336,10 @@ possibility of bundling files: the <path>. Fileset are easy if the files are all under a common base directory. But if this is not the case you have a problem. Another disadvantage is its speed: if you have only a few files in a huge directory structure, why not use a -<fileset> instead? <path>s combines these datatypes in that way that a path contains -other paths, filesets, dirsets and filelists. This is way <a href="">Ant-Contribs [XXX]</a> -<foreach> task is modified to support paths instead of filesets. So we want that, too.</p> +<filelist> instead? <path>s combines these datatypes in that way that a path contains +other paths, filesets, dirsets and filelists. This is why <a href="http://ant-contrib.sourceforge.net/"> +Ant-Contribs [4]</a> <foreach> task is modified to support paths instead of filesets. So we want that, +too.</p> <p>Changing from fileset to path support is very easy:</p> <pre class="code"> @@ -353,7 +367,7 @@ <p>On <b>*1</b> we rename only the vector. Itīs just for better reading the source. On <b>*2</b> we have to provide the right method: an add<i>Name</i>(<i>Type</i> t). Therefore replace the fileset with path here. Finally we have to modify our buildfile on <b>*3</b> because our task -donīt support nested filesets any longer. So we wrap the fileset inside a path.</p> +doesnīt support nested filesets any longer. So we wrap the fileset inside a path.</p> <p>And now we modify the testcase. Oh, not very much to do :-) Renaming the <tt>testMissingFileset()</tt> (not really a <i>must-be</i> but better itīs named like the think it does) and update the @@ -363,9 +377,9 @@ <p>The test are finished. Now we have to adapt the task implementation. The easiest modification is in the <tt>validate()</tt> method where we change le last line to <tt>if (paths.size()<1) throw new -BuildException("path not set");</tt>. In the <tt>execute()</tt> method we have a liitle more work. -... mmmh ... in reality itīs lesser work, because the Path class does a the whole DirectoryScanner-handling -and creating absolute paths stuff for us. So the execute method is just:</p> +BuildException("path not set");</tt>. In the <tt>execute()</tt> method we have a little more work. +... mmmh ... in reality itīs lesser work, because the Path class does the whole DirectoryScanner-handling +and creating-absolute-paths stuff for us. So the execute method is just:</p> <pre class="code"> public void execute() { @@ -463,7 +477,7 @@ <p>Now we need a directory structure where we CAN find files with the same name in different directories. Because we canīt sure to have one we create -one on <b>*1, *2</b>. And of course we clean up that on <b>*4</b>. The creation +one on <b>*1</b> and <b>*2</b>. And of course we clean up that on <b>*4</b>. The creation can be done inside our test target or in a separate one, which will be better for reuse later (<b>*3</b>). @@ -534,7 +548,8 @@ it has advantages if you use that: all task users know that form, this form is requested if you decide to contribute your task. So we will doc our task in that form.</p> -<p>If you have a look at the manual page of the <a href="">java [XXX]</a> task you will see<ul> +<p>If you have a look at the manual page of the <a href="CoreTasks/java.html">java [5]</a> + task you will see<ul> <li>it is plain html</li> <li>starts with the name</li> <li>has sections: description, parameters, nested elements, (maybe return codes) and (most @@ -595,7 +610,7 @@ </html> </pre> -<p>For our task we have <a href="">that [XXX]</a>:</p> +<p>For our task we have <a href="CoreTasks/find.html">that [6]</a>:</p> <pre class="code"> <html> @@ -680,7 +695,8 @@ <li>create a patch file</li> <li>publishing that patch file</li> </ul> -The <a href="">Ant Task Guidelines [XXX]</a> support additional information on that.</p> +The <a href="../ant_task_guidelines.html">Ant Task Guidelines [7]</a> support additional +information on that.</p> <p>Now we will check the "Checklist before submitting a new task" described in that guideline. <ul> @@ -707,53 +723,264 @@ <h3>Package / Directories</h3> -This task does not depend any external library. Therefore we can use this as -a core task. This task contains only one class. So we can use the standardd package +<p>This task does not depend on any external library. Therefore we can use this as +a core task. This task contains only one class. So we can use the standard package for core tasks: <tt>org.apache.tools.ant.taskdefs</tt>. Implementations are in the directory <tt>src/main</tt>, tests in <tt>src/testcases</tt> and buildfiles for -tests in <tt>src/etc/testcases</tt>. +tests in <tt>src/etc/testcases</tt>.</p> + +<p>Now we integrate our work into Ants distribution. So first we do an update of our +cvs tree. If not done yet, you have to checkout the ant module from Apaches cvs server +as described in <a href="http://ant.apache.org/cvs.html">Access the Source Tree (AnonCVS) +[8]</a> (password is <i>anoncvs</i>):<pre class="output"> +cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic login //1 +cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic checkout ant //2 +</pre> +If you have a local copy of Ants sources just do an update +<pre class="output"> +cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic login +cd ant //3 +cvs -d :pserver:[EMAIL PROTECTED]:/home/cvspublic update //4 +</pre></p> + +<p>We use the <i>-d</i> flag on <b>//1</b> to specifiy the cvs directory. You can +specify the environment variable CVSROOT with that value and after that you havenīt +to use that flag any more. On <b>//2</b> we get the whole cvs tree of ant. (Sorry, +but that uses a lot of time ... 10 up to 30 minutes are not unusual ... but this has +to be done only once :-). A cvs update doesnīt use a modulename but you have to be +inside the directory. Therefore we go into that on <b>//3</b> and do the update +on <b>//4</b>.</p> + +<p>Now we will build our Ant distribution and do a test. So we can see if there +are any tests failing on our machine. (We can ignore these failing tests on later +steps; windows syntax used here- translate to xNIX if needed): +<pre class="output"> +ANTHOME> build // 1 +ANTHOME> set ANT_HOME=%CD%\dist // 2 +ANTHOME> ant test -Dtest.haltonfailure=false // 3 +</pre> + +First we have to build our Ant distribution (<b>//1</b>). On <b>//2</b> we set the ANT_HOME +environment variable to the directory where the new created distribution is stored +(%CD% is expanded to the current directory on Windows 2000 and XP, on 9x and NT +write it out). On <b>//3</b> we let Ant do all the tests (which enforced a compile +of all tests) without stopping on first failure.</p> + +<p>Next we apply our work onto Ants sources. Because we havenīt modified any, this is +a relative simple step. <i>(Because I have a local copy of Ant and usually contribute my +work, I work on the local copy just from the beginning. The advantage: this step isnīt +necessary and saves a lot of work if you modify existing source :-)</i>. + +<ul> +<li>move the Find.java to ANTHOME/src/main/org/apache/tools/ant/taskdefs/Find.java </li> +<li>move the FindTest.java to ANTHOME/src/testcases/org/apache/tools/ant/taskdefs/FindTest.java </li> +<li>move the build.xml to ANTHOME/src/etc/testcases/taskdefs/<b>find.xml</b> (!!! renamed !!!)</li> +<li>add a <tt>package org.apache.tools.ant.taskdefs;</tt> at the beginning of the two java files </li> +<li>delete all stuff from find.xml keeping the targets "testFileNotPresent", "testFilePresent", + "test.init" and "testMultipleFiles" </li> +<li>delete the dependency to "use.init" in the find.xml </li> +<li>in FindTest.java change the line <tt>configureProject("build.xml");</tt> to + <tt>configureProject("src/etc/testcases/taskdefs/find.xml");</tt> </li> +<li>move the find.html to ANTHOME/docs/manual/CoreTasks/find.html </li> +<li>add a <tt><a href="CoreTasks/find.html">Find</a><br></tt> + in the ANTHOME/docs/manual/coretasklist.html </li> +</ul> + +Now our modifications are done and we will retest it: +<pre class="output"> +ANTHOME> build +ANTHOME> ant run-single-test // 1 + -Dtestcase=org.apache.tools.ant.taskdefs.FindTest // 2 + -Dtest.haltonfailure=false +</pre> +Because we only want to test our new class, we use the target for single tests, specify +the test to use and configure not to halt on the first failure - we want to see all +failures of our own test (<b>//1 + 2</b>).</p> + +<p>And ... oh, all tests fail: <i>Ant could not find the task or a class this task relies upon.</i></p> + +<p>Ok: in the earlier steps we told Ant to use the Find class for the <find> task (remember the +<taskdef> statement in the "use.init" target). But now we want to introduce that task as +a core task. And nobody wants to taskdef the javac, echo, ... So what to do? The answer is the +src/main/.../taskdefs/default.properties. Here is the mapping between taskname and implementing +class done. So we add a <tt>find=org.apache.tools.ant.taskdefs.Find</tt> as the last core +task (just before the <tt># optional tasks</tt> line). Now a second try: +<pre class="output"> +ANTHOME> build // 1 +ANTHOME> ant run-single-test + -Dtestcase=org.apache.tools.ant.taskdefs.FindTest + -Dtest.haltonfailure=false +</pre> +We have to rebuild (<b>//1</b>) Ant because the test look in the %ANT_HOME%\lib\ant.jar +(more precise: on the classpath) for the properties file. And we have only modified it in the +source path. So we have to rebuild that jar. But now all tests pass and we check whether our class +breaks some other tests. +<pre class="output"> +ANTHOME> ant test -Dtest.haltonfailure=false +</pre> +Because there are a lot of tests this step requires a little bit of time. So use the <i>run-single-test</i> +during development and do the <i>test</i> only at the end (maybe sometimes during development too). +We use the <i>-Dtest.haltonfailure=false</i> here because there could be other tests fail and we have +to look into them.</p> + +<p>This test run should show us two things: our test will run and the number of failing tests +is the same as directly after the cvs update (without our modifications).</p> + <h3>Apache copyright and license statement</h3> <p>Simply copy the license text from one the other source from the Ant source tree. But ensure that the current year is used in the<tt> * Copyright (c) 2000-2003 The Apache Software -Foundation. All rights reserved.</tt> lines. +Foundation. All rights reserved.</tt> lines. Donīt forget to add a license statement at the end +of the find.html. (Can be copied from other manual files.)</p> + + +<h3>Test on JDK 1.2</h3> +<p>Until version 1.5 Ant must be able to run on a JDK 1.1. With version 1.6 this is not a +requisite any more. But JDK 1.2 is a must be able. So we have to test that. You can download older +JDKs from <a href="http://java.sun.com/products/archive/index.html">Sun [9]</a>.</p> + +<p>Clean the ANT_HOME variable, delete the <i>build, bootstrap</i> and <i>dist</i> directory +and point JAVA_HOME to the JDK 1.2 home directory. Then do the <tt>build</tt>, set ANT_HOME +and run <tt>ant test</tt> (like above).</p> + +<p>Our test should pass.</p> + <h3>Checkstyle</h3> -There are many things we have to ensure. Indentation with 4 spaces, blanks here and there, ... -(all described in the <a href="">Ant Task Guidelines [XXX]</a> which includes the -<a href="">Sun code style [XXX]</a>. Because there are so many things we would be happy -to have a tool for do the checks. There is one: checkstyle. Checkstyle is available -at <a href="">Sourceforge [XXX]</a> and Ant provides with the <tt>check.xml</tt> a buildfile -which will do the job for us. +<p>There are many things we have to ensure. Indentation with 4 spaces, blanks here and there, ... +(all described in the <a href="../ant_task_guidelines.html">Ant Task Guidelines [7]</a> which +includes the <a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html">Sun code style +[10]</a>). Because there are so many things we would be happy to have a tool for do the checks. +There is one: checkstyle. Checkstyle is available at <a href="http://checkstyle.sourceforge.net/"> +Sourceforge [11]</a> and Ant provides with the <tt>check.xml</tt> a buildfile which will do the job +for us.</p> + +<p>Download it and put the checkstyle-*-all.jar into your %USERPROFILE%\.ant\lib directory. +All jarīs stored there are available to Ant so you havenīt to add it to you %ANT_HOME%\lib +directory (this feature was added with Ant 1.6).</p> + +<p>So we will run the tests with +<pre class="output"> +ANTHOME> ant -f check.xml checkstyle htmlreport +</pre> +I prefer the HTML report because there are lots of messages and we can navigate faster. +Open the ANTHOME/build/reports/checkstyle/html/index.html and navigate to the Find.java. Now we +see that there are some errors: missing whitespaces, unused imports, missing javadocs. So we have +to do that.</p> + +<p>Hint: start at the <b>buttom</b> of the file so the line numbers in the report will keep +up to date and you will find the next error place much more easier without redoing the checkstyle.</p> + +<p>After cleaning up the code according to the messages we delete the reports directory and +do a second checkstyle run. Now our task isnīt listed. Thatīs fine :-)</p> + + -<h3>Test on JDK 1.2</h3> <h3>Creating the diff</h3> +<p>Creating a diff for Ant is very easy: just start <tt>ant -f patch.xml</tt> and all is done +automatically. This step requires a cvs executable in your path and internet access (more precise: +cvs access). As a result we get a file <i> XXX </i>.</p> + + <h3>Publish the task</h3> +<p>Finally we publish that archive. As described in the <a href="../ant_task_guidelines.html"> +Ant Task Guidelines [7]</a> we can post it on the developer mailinglist or we create a BugZilla +entry. For both we need some information:</p> + +<table border="1"> +<tr> + <th>subject</th> + <td><i>short description</i></td> + <td>Task for finding files in a path</td> +</tr> +<tr> + <th>body</th> + <td><i>more details about the path</i></td> + <td>This new task looks inside a nested <path/> for occurrences of a file and stores + all locations as a property. See the included manual for details.</td> +</tr> +<tr> + <th>attachements</th> + <td><i>all files needed to apply the path</td> + <td>Archive containing the path produced with path.xml</td> +</tr> +</table> + +<p>Sending an email with these information is very easy and I think I havenīt to show that. +The other way - BugZilla - is slightly more difficult. But it has the advantage that entries +will not be forgotten (once per week a report is generated). So I will show this way.</p> + +<p>You must have a BugZilla account for that. So open the <a href="http://nagoya.apache.org/bugzilla/"> +BugZilla Main Page [12]</a> and follow the link +<a href="http://nagoya.apache.org/bugzilla/createaccount.cgi">Open a new Bugzilla account [13]</a> +and the steps described there if you havenīt one.</p> + +<ol> +<li>From the BugZilla main page choose <a href="http://nagoya.apache.org/bugzilla/enter_bug.cgi">Enter + a new bug report [14]</a></li> +<li>Choose "Ant" as product </li> +<li>Version is the last "Alpha (nightly)" (at this time 1.7)</li> +<li>Component is "Core tasks"</li> +<li>Plattform and Severity are ok with "Other" and "Normal"</li> +<li>Initial State is ok with "New"</li> +<li>Same with the empy "Assigned to"</li> +<li>It is not required to add yourself as CC, because you are the reporter and therefore will be + informed on changes</li> +<li>URL: no url required</li> +<li>Summary: add the <i>subject</i> from the table</li> +<li>Description: add the <i>body</i> from the table</li> +<li>Then press "Commit"</li> + +<!-- XXX MAT: Attachement eintragen, wenn ich das online auch mache - dazu brauche ich vorher + das CVS Patch --> +</ol> <br><br><br><br><br><br><br><br> -- stichpunkte siehe ... manual -- ist das richtige package gewählt worden? -- checkstyle -- tests -- dokumentation -- jdk 1.2 -- patch erstellen -- bugzilla / mailingliste +- patch erstellen --> zu hause wg. cvs zugang <br> +- bugzilla einstellen --> zu hause wg. abhängigkeit zu patch-file <a name="resources"/> <h2>Resources</h2> --- text durchsehen - [1] <a href="http://ant.apache.org/manual/using.html#built-in-props">http://ant.apache.org/manual/using.html#built-in-props</a><br/> + [1] <a href="tutorial-writing-tasks.html">tutorial-writing-tasks.html</a><br/> + [2] <a href="tutorial-tasks-filesets-properties.zip">tutorial-tasks-filesets-properties.zip</a><br/> + [3] <a href="using.html#built-in-props">using.html#built-in-props</a><br/> + [4] <a href="http://ant-contrib.sourceforge.net/">http://ant-contrib.sourceforge.net/</a><br/> + [5] <a href="CoreTasks/java.html">CoreTasks/java.html</a><br/> + [6] <a href="CoreTasks/find.html">CoreTasks/find.html</a><br/> + [7] <a href="../ant_task_guidelines.html">../ant_task_guidelines.html</a><br/> + [8] <a href="http://ant.apache.org/cvs.html">http://ant.apache.org/cvs.html</a><br/> + [9] <a href="http://java.sun.com/products/archive/index.html">http://java.sun.com/products/archive/index.html</a><br/> + [10] <a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html">http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html</a><br/> + [11] <a href="http://checkstyle.sourceforge.net/">http://checkstyle.sourceforge.net/</a><br/> + [12] <a href="http://nagoya.apache.org/bugzilla/">http://nagoya.apache.org/bugzilla/</a><br/> + [13] <a href="http://nagoya.apache.org/bugzilla/createaccount.cgi">http://nagoya.apache.org/bugzilla/createaccount.cgi</a><br/> + [14] <a href="http://nagoya.apache.org/bugzilla/enter_bug.cgi">http://nagoya.apache.org/bugzilla/enter_bug.cgi</a><br/> + +<br><br><br> + +<!-- + [15] <a href=" "> </a><br/> + [16] <a href=" "> </a><br/> + [17] <a href=" "> </a><br/> + [18] <a href=" "> </a><br/> + [19] <a href=" "> </a><br/> + [20] <a href=" "> </a><br/> + [21] <a href=" "> </a><br/> + [22] <a href=" "> </a><br/> + [23] <a href=" "> </a><br/> + [24] <a href=" "> </a><br/> + [25] <a href=" "> </a><br/> +--> <hr> <p align="center">Copyright © 2003 Apache Software Foundation. All rights
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]