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]