Browse Source

found two non-closed tags (were missing the > sign). Had to make it well-formed XML so Emacs' nXML mode could assist me.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1026374 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 14 years ago
parent
commit
0ce95ee95e
1 changed files with 48 additions and 49 deletions
  1. +48
    -49
      docs/manual/tutorial-writing-tasks.html

+ 48
- 49
docs/manual/tutorial-writing-tasks.html View File

@@ -18,6 +18,7 @@
<head> <head>
<title>Tutorial: Writing Tasks</title> <title>Tutorial: Writing Tasks</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style.css"> <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
</link>
</head> </head>
<body> <body>
<h1>Tutorial: Writing Tasks</h1> <h1>Tutorial: Writing Tasks</h1>
@@ -25,7 +26,7 @@
<p>This document provides a step by step tutorial for writing <p>This document provides a step by step tutorial for writing
tasks.</p> tasks.</p>
<h2>Content</h2> <h2>Content</h2>
<p><ul>
<ul>
<li><a href="#buildenvironment">Set up the build environment</a></li> <li><a href="#buildenvironment">Set up the build environment</a></li>
<li><a href="#write1">Write the Task</a></li> <li><a href="#write1">Write the Task</a></li>
<li><a href="#use1">Use the Task</a></li> <li><a href="#use1">Use the Task</a></li>
@@ -39,16 +40,16 @@ tasks.</p>
<li><a href="#TestingTasks">Test the Task</a></li> <li><a href="#TestingTasks">Test the Task</a></li>
<li><a href="#Debugging">Debugging</a></li> <li><a href="#Debugging">Debugging</a></li>
<li><a href="#resources">Resources</a></li> <li><a href="#resources">Resources</a></li>
</ul></p>
</ul>


<a name="buildenvironment"></a> <a name="buildenvironment"></a>
<h2>Set up the build environment</h2> <h2>Set up the build environment</h2>
<p>Ant builds itself, we are using Ant too (why we would write <p>Ant builds itself, we are using Ant too (why we would write
a task if not? :-) therefore we should use Ant for our build.<p>
a task if not? :-) therefore we should use Ant for our build.</p>
<p>We choose a directory as root directory. All things will be done <p>We choose a directory as root directory. All things will be done
here if I say nothing different. I will reference this directory here if I say nothing different. I will reference this directory
as <i>root-directory</i> of our project. In this root-directory we as <i>root-directory</i> of our project. In this root-directory we
create a text file names <i>build.xml</i>. What should Ant do for us?
create a text file names <i>build.xml</i>. What should Ant do for us?</p>
<ul> <ul>
<li>compiles my stuff</li> <li>compiles my stuff</li>
<li>make the jar, so that I can deploy it</li> <li>make the jar, so that I can deploy it</li>
@@ -130,7 +131,7 @@ its <i>depends</i>-clause the "compile" is executed before).
<p>But after creating the jar we want to use our new Task. Therefore we need a <p>But after creating the jar we want to use our new Task. Therefore we need a
new target "use". Before we can use our new task we have to declare it with new target "use". Before we can use our new task we have to declare it with
<a href="http://ant.apache.org/manual/Tasks/taskdef.html" target="_blank"> <a href="http://ant.apache.org/manual/Tasks/taskdef.html" target="_blank">
<code>&lt;taskdef&gt;</code> [2]</a>. And for easier process we change the default clause:
<code>&lt;taskdef&gt;</code> [2]</a>. And for easier process we change the default clause:</p>
<pre class="code"> <pre class="code">
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;project name="MyTask" basedir="." default="<b>use</b>"&gt; &lt;project name="MyTask" basedir="." default="<b>use</b>"&gt;
@@ -145,10 +146,10 @@ new target "use". Before we can use our new task we have to declare it with
&lt;/project&gt; &lt;/project&gt;
</pre> </pre>


Important is the <i>classpath</i>-attribute. Ant searches in its /lib directory for
<p>Important is the <i>classpath</i>-attribute. Ant searches in its /lib directory for
tasks and our task isn't there. So we have to provide the right location. </p> tasks and our task isn't there. So we have to provide the right location. </p>


<p>Now we can type in <tt>ant</tt> and all should work ...
<p>Now we can type in <tt>ant</tt> and all should work ...</p>
<pre class="output"> <pre class="output">
Buildfile: build.xml Buildfile: build.xml


@@ -178,7 +179,7 @@ setting a reference to the project and calling the <i>execute()</i> method.</p>


<p><i>Setting a reference to the project</i>? Could be interesting. The Project class <p><i>Setting a reference to the project</i>? Could be interesting. The Project class
gives us some nice abilities: access to Ant's logging facilities getting and setting gives us some nice abilities: access to Ant's logging facilities getting and setting
properties and much more. So we try to use that class:
properties and much more. So we try to use that class:</p>
<pre class="code"> <pre class="code">
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;


@@ -200,7 +201,7 @@ and the execution with <tt>ant</tt> will show us the expected
<pre class="output"> <pre class="output">
use: use:
Here is project 'MyTask'. Here is project 'MyTask'.
</pre></p>
</pre>




<a name="derivingFromTask"></a> <a name="derivingFromTask"></a>
@@ -210,7 +211,7 @@ That class is integrated in Ant, get's the project-reference, provides documenta
fiels, provides easier access to the logging facility and (very useful) gives you fiels, provides easier access to the logging facility and (very useful) gives you
the exact location where <i>in the buildfile</i> this task instance is used.</p> the exact location where <i>in the buildfile</i> this task instance is used.</p>


<p>Oki-doki - let's us use some of these:
<p>Oki-doki - let's us use some of these:</p>
<pre class="code"> <pre class="code">
import org.apache.tools.ant.Task; import org.apache.tools.ant.Task;


@@ -227,27 +228,27 @@ public class HelloWorld extends Task {
} }
} }
</pre> </pre>
which gives us when running
<p>which gives us when running</p>
<pre class="output"> <pre class="output">
use: use:
[helloworld] Here is project 'MyTask'. [helloworld] Here is project 'MyTask'.
[helloworld] I am used in: C:\tmp\anttests\MyFirstTask\build.xml:23: [helloworld] I am used in: C:\tmp\anttests\MyFirstTask\build.xml:23:
</pre> </pre>


<a name="accessTaskProject">
<a name="accessTaskProject"></a>
<h2>Accessing the Task's Project</h2> <h2>Accessing the Task's Project</h2>
<p>The parent project of your custom task may be accessed through method <code>getProject()</code>. However, do not call this from the custom task constructor, as the return value will be null. Later, when node attributes or text are set, or method <code>execute()</code> is called, the Project object is available.</p> <p>The parent project of your custom task may be accessed through method <code>getProject()</code>. However, do not call this from the custom task constructor, as the return value will be null. Later, when node attributes or text are set, or method <code>execute()</code> is called, the Project object is available.</p>
<p>Here are two useful methods from class Project:
<p>Here are two useful methods from class Project:</p>
<ul> <ul>
<li><code>String getProperty(String propertyName)</code></li> <li><code>String getProperty(String propertyName)</code></li>
<li> <li>
<code>String replaceProperties(String value)</code> <code>String replaceProperties(String value)</code>
</li> </li>
</ul
</p>
</ul>
<p>The method <code>replaceProperties()</code> is discussed further in section <a href="#NestedText">Nested Text</a>.</p> <p>The method <code>replaceProperties()</code> is discussed further in section <a href="#NestedText">Nested Text</a>.</p>


<a name="attributes">
<a name="attributes"></a>
<h2>Attributes</h2> <h2>Attributes</h2>
<p>Now we want to specify the text of our message (it seems that we are <p>Now we want to specify the text of our message (it seems that we are
rewriting the <code>&lt;echo/&gt;</code> task :-). First we well do that with an attribute. rewriting the <code>&lt;echo/&gt;</code> task :-). First we well do that with an attribute.
@@ -279,7 +280,7 @@ string provided there is written as build-failes-message. Here it's necessary be
the log() method can't handle a <i>null</i> value as parameter and throws a NullPointerException. the log() method can't handle a <i>null</i> value as parameter and throws a NullPointerException.
(Of course you can initialize the <i>message</i> with a default string.)</p> (Of course you can initialize the <i>message</i> with a default string.)</p>


<p>After that we have to modify our buildfile:
<p>After that we have to modify our buildfile:</p>
<pre class="code"> <pre class="code">
&lt;target name="use" description="Use the Task" depends="jar"&gt; &lt;target name="use" description="Use the Task" depends="jar"&gt;
&lt;taskdef name="helloworld" &lt;taskdef name="helloworld"
@@ -288,10 +289,10 @@ the log() method can't handle a <i>null</i> value as parameter and throws a Null
&lt;helloworld <b>message="Hello World"</b>/&gt; &lt;helloworld <b>message="Hello World"</b>/&gt;
&lt;/target&gt; &lt;/target&gt;
</pre> </pre>
That's all.</p>
<p>That's all.</p>


<p>Some background for working with attributes: Ant supports any of these datatypes as <p>Some background for working with attributes: Ant supports any of these datatypes as
arguments of the set-method:<ul>
arguments of the set-method:</p><ul>
<li>elementary data type like <i>int</i>, <i>long</i>, ...</li> <li>elementary data type like <i>int</i>, <i>long</i>, ...</li>
<li>its wrapper classes like <i>java.lang.Integer</i>, <i>java.lang.Long</i>, ...</li> <li>its wrapper classes like <i>java.lang.Integer</i>, <i>java.lang.Long</i>, ...</li>
<li><i>java.lang.String</i></li> <li><i>java.lang.String</i></li>
@@ -308,7 +309,7 @@ would not set the message string to "${msg}" if there is a property "msg" with a
<a name="NestedText"></a> <a name="NestedText"></a>
<h2>Nested Text</h2> <h2>Nested Text</h2>
<p>Maybe you have used the <code>&lt;echo&gt;</code> task in a way like <tt>&lt;echo&gt;Hello World&lt;/echo&gt;</tt>. <p>Maybe you have used the <code>&lt;echo&gt;</code> task in a way like <tt>&lt;echo&gt;Hello World&lt;/echo&gt;</tt>.
For that you have to provide a <tt>public void addText(String text)</tt> method.
For that you have to provide a <tt>public void addText(String text)</tt> method.</p>
<pre class="code"> <pre class="code">
... ...
public class HelloWorld extends Task { public class HelloWorld extends Task {
@@ -320,7 +321,7 @@ public class HelloWorld extends Task {
... ...
} }
</pre> </pre>
But here properties are <b>not</b> resolved! For resolving properties we have to use
<p>But here properties are <b>not</b> resolved! For resolving properties we have to use
Project's <tt>replaceProperties(String propname) : String</tt> method which takes the Project's <tt>replaceProperties(String propname) : String</tt> method which takes the
property name as argument and returns its value (or ${propname} if not set).</p> property name as argument and returns its value (or ${propname} if not set).</p>
<p>Thus, to replace properties in the nested node text, our method <code>addText()</code> can be written as:</p> <p>Thus, to replace properties in the nested node text, our method <code>addText()</code> can be written as:</p>
@@ -335,7 +336,7 @@ property name as argument and returns its value (or ${propname} if not set).</p>
<h2>Nested Elements</h2> <h2>Nested Elements</h2>
<p>There are several ways for inserting the ability of handling nested elements. See <p>There are several ways for inserting the ability of handling nested elements. See
the <a href="http://ant.apache.org/manual/develop.html#nested-elements">Manual [4]</a> for other. the <a href="http://ant.apache.org/manual/develop.html#nested-elements">Manual [4]</a> for other.
We use the first way of the three described ways. There are several steps for that:<ol>
We use the first way of the three described ways. There are several steps for that:</p><ol>
<li>We create a class for collecting all the info the nested element should contain. <li>We create a class for collecting all the info the nested element should contain.
This class is created by the same rules for attributes and nested elements This class is created by the same rules for attributes and nested elements
as for the task (<code>set&lt;attributename&gt;</code>() methods). </li> as for the task (<code>set&lt;attributename&gt;</code>() methods). </li>
@@ -343,7 +344,7 @@ We use the first way of the three described ways. There are several steps for th
<li>A factory method instantiates an object, saves the reference in the list <li>A factory method instantiates an object, saves the reference in the list
and returns it to Ant Core.</li> and returns it to Ant Core.</li>
<li>The execute() method iterates over the list and evaluates its values.</li> <li>The execute() method iterates over the list and evaluates its values.</li>
</ol></p>
</ol>
<pre class="code"> <pre class="code">
import java.util.Vector; import java.util.Vector;
import java.util.Iterator; import java.util.Iterator;
@@ -377,7 +378,7 @@ import java.util.Iterator;
<p>Then we can use the new nested element. But where is xml-name for that defined? <p>Then we can use the new nested element. But where is xml-name for that defined?
The mapping XML-name : classname is defined in the factory method: The mapping XML-name : classname is defined in the factory method:
<tt>public <i>classname</i> create<i>XML-name</i>()</tt>. Therefore we write in <tt>public <i>classname</i> create<i>XML-name</i>()</tt>. Therefore we write in
the buildfile
the buildfile</p>
<pre class="code"> <pre class="code">
&lt;helloworld&gt; &lt;helloworld&gt;
&lt;message msg="Nested Element 1"/&gt; &lt;message msg="Nested Element 1"/&gt;
@@ -385,11 +386,11 @@ the buildfile
&lt;/helloworld&gt; &lt;/helloworld&gt;
</pre> </pre>
<p>Note that if you choose to use methods 2 or 3, the class that represents the nested <p>Note that if you choose to use methods 2 or 3, the class that represents the nested
element must be declared as <pre>static</pre></p>
element must be declared as <code>static</code></p>


<a name="complex"></a> <a name="complex"></a>
<h2>Our task in a little more complex version</h2> <h2>Our task in a little more complex version</h2>
<p>For recapitulation now a little refactored buildfile:
<p>For recapitulation now a little refactored buildfile:</p>
<pre class="code"> <pre class="code">
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;project name="MyTask" basedir="." default="use"&gt; &lt;project name="MyTask" basedir="." default="use"&gt;
@@ -614,7 +615,7 @@ target "test-jar" or you can download a nightly build from
http://gump.covalent.net/jars/latest/ant/ant-testutil.jar [5]</a>.</p> http://gump.covalent.net/jars/latest/ant/ant-testutil.jar [5]</a>.</p>


<p>For executing the test and creating a report we need the optional tasks <code>&lt;junit&gt;</code> <p>For executing the test and creating a report we need the optional tasks <code>&lt;junit&gt;</code>
and <code>&lt;junitreport&gt;</code>. So we add to the buildfile:
and <code>&lt;junitreport&gt;</code>. So we add to the buildfile:</p>
<pre class="code"> <pre class="code">
... ...
<font color="#9F9F9F">&lt;project name="MyTask" basedir="." </font>default="test"<font color="#9F9F9F">&gt;</font> <font color="#9F9F9F">&lt;project name="MyTask" basedir="." </font>default="test"<font color="#9F9F9F">&gt;</font>
@@ -674,12 +675,12 @@ and <code>&lt;junitreport&gt;</code>. So we add to the buildfile:
description="Runs unit tests and creates a report" description="Runs unit tests and creates a report"
/&gt; /&gt;
... ...
</pre></p>
</pre>


<p>Back to the <i>src/HelloWorldTest.java</i>. We create a class extending <p>Back to the <i>src/HelloWorldTest.java</i>. We create a class extending
<i>BuildFileTest</i> with String-constructor (JUnit-standard), a <i>setUp()</i> <i>BuildFileTest</i> with String-constructor (JUnit-standard), a <i>setUp()</i>
method initializing Ant and for each testcase (targets use.*) a <i>testXX()</i> method initializing Ant and for each testcase (targets use.*) a <i>testXX()</i>
method invoking that target.
method invoking that target.</p>
<pre class="code"> <pre class="code">
import org.apache.tools.ant.BuildFileTest; import org.apache.tools.ant.BuildFileTest;


@@ -721,10 +722,10 @@ public class HelloWorldTest extends BuildFileTest {
assertLogContaining("Nested Element 2"); assertLogContaining("Nested Element 2");
} }
} }
</pre></p>
</pre>


<p>When starting <tt>ant</tt> we'll get a short message to STDOUT and <p>When starting <tt>ant</tt> we'll get a short message to STDOUT and
a nice HTML-report.
a nice HTML-report.</p>
<pre class="output"> <pre class="output">
C:\tmp\anttests\MyFirstTask&gt;ant C:\tmp\anttests\MyFirstTask&gt;ant
Buildfile: build.xml Buildfile: build.xml
@@ -753,20 +754,20 @@ test:
BUILD SUCCESSFUL BUILD SUCCESSFUL
Total time: 7 seconds Total time: 7 seconds
C:\tmp\anttests\MyFirstTask&gt; C:\tmp\anttests\MyFirstTask&gt;
</pre></p>
</pre>




<a name="Debugging"></a
<a name="Debugging"></a>
<h2>Debugging</h2> <h2>Debugging</h2>


<p>Try running Ant with the flag <code>-verbose</code>. For more information, try flag <code>-debug</code>.</p> <p>Try running Ant with the flag <code>-verbose</code>. For more information, try flag <code>-debug</code>.</p>
<p>For deeper issues, you may need to run the custom task code in a Java debugger. First, get the source for Ant and build it with debugging information.</p> <p>For deeper issues, you may need to run the custom task code in a Java debugger. First, get the source for Ant and build it with debugging information.</p>
<p>Since Ant is a large project, it can be a little tricky to set the right breakpoints. Here are two important breakpoints for version 1.8:
<p>Since Ant is a large project, it can be a little tricky to set the right breakpoints. Here are two important breakpoints for version 1.8:</p>
<ul> <ul>
<li>Initial <code>main()</code> function: <code>com.apache.tools.ant.launch.Launcher.main()</code></li> <li>Initial <code>main()</code> function: <code>com.apache.tools.ant.launch.Launcher.main()</code></li>
<li>Task entry point: <code>com.apache.tools.ant.UnknownElement.execute()</code></li> <li>Task entry point: <code>com.apache.tools.ant.UnknownElement.execute()</code></li>
</ul> </ul>
</p>
<p>If you need to debug when a task attribute or the text is set, begin by debugging into method <code>execute()</code> of your custom task. Then set breakpoints in other methods. This will ensure the class byte-code has been loaded by the Java VM.</p> <p>If you need to debug when a task attribute or the text is set, begin by debugging into method <code>execute()</code> of your custom task. Then set breakpoints in other methods. This will ensure the class byte-code has been loaded by the Java VM.</p>




@@ -775,8 +776,8 @@ C:\tmp\anttests\MyFirstTask&gt;
<h2>Resources</h2> <h2>Resources</h2>
<p>This tutorial and its resources are available via <p>This tutorial and its resources are available via
<a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22570">BugZilla [6]</a>. <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22570">BugZilla [6]</a>.
The ZIP provided there contains<ul>
<li>this tutorial</li>
The ZIP provided there contains</p><ul>
<li>this initial version of this tutorial</li>
<li>the buildfile (last version)</li> <li>the buildfile (last version)</li>
<li>the source of the task (last version)</li> <li>the source of the task (last version)</li>
<li>the source of the unit test (last version)</li> <li>the source of the unit test (last version)</li>
@@ -785,21 +786,19 @@ The ZIP provided there contains<ul>
<li>generated jar</li> <li>generated jar</li>
<li>generated reports</li> <li>generated reports</li>
</ul> </ul>
The last sources and the buildfile are also available
<p>The last sources and the buildfile are also available
<a href="tutorial-writing-tasks-src.zip">here [7]</a> inside the manual. <a href="tutorial-writing-tasks-src.zip">here [7]</a> inside the manual.
</p> </p>



Used Links:<br>
&nbsp;&nbsp;[1] <a href="http://ant.apache.org/manual/properties.html#built-in-props">http://ant.apache.org/manual/properties.html#built-in-props</a><br>
&nbsp;&nbsp;[2] <a href="http://ant.apache.org/manual/Tasks/taskdef.html">http://ant.apache.org/manual/Tasks/taskdef.html</a><br>
&nbsp;&nbsp;[3] <a href="http://ant.apache.org/manual/develop.html#set-magic">http://ant.apache.org/manual/develop.html#set-magic</a><br>
&nbsp;&nbsp;[4] <a href="http://ant.apache.org/manual/develop.html#nested-elements">http://ant.apache.org/manual/develop.html#nested-elements</a><br>
&nbsp;&nbsp;[5] <a href="http://gump.covalent.net/jars/latest/ant/ant-testutil.jar">http://gump.covalent.net/jars/latest/ant/ant-testutil.jar</a><br>
&nbsp;&nbsp;[6] <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22570">http://issues.apache.org/bugzilla/show_bug.cgi?id=22570</a><br>
&nbsp;&nbsp;[7] <a href="tutorial-writing-tasks-src.zip">tutorial-writing-tasks-src.zip</a><br>


<p>Used Links:<br></br>
&nbsp;&nbsp;[1] <a href="http://ant.apache.org/manual/properties.html#built-in-props">http://ant.apache.org/manual/properties.html#built-in-props</a><br></br>
&nbsp;&nbsp;[2] <a href="http://ant.apache.org/manual/Tasks/taskdef.html">http://ant.apache.org/manual/Tasks/taskdef.html</a><br></br>
&nbsp;&nbsp;[3] <a href="http://ant.apache.org/manual/develop.html#set-magic">http://ant.apache.org/manual/develop.html#set-magic</a><br></br>
&nbsp;&nbsp;[4] <a href="http://ant.apache.org/manual/develop.html#nested-elements">http://ant.apache.org/manual/develop.html#nested-elements</a><br></br>
&nbsp;&nbsp;[5] <a href="http://gump.covalent.net/jars/latest/ant/ant-testutil.jar">http://gump.covalent.net/jars/latest/ant/ant-testutil.jar</a><br></br>
&nbsp;&nbsp;[6] <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22570">http://issues.apache.org/bugzilla/show_bug.cgi?id=22570</a><br></br>
&nbsp;&nbsp;[7] <a href="tutorial-writing-tasks-src.zip">tutorial-writing-tasks-src.zip</a><br></br>
</p>


</body> </body>
</html> </html>

Loading…
Cancel
Save