Repository: ant Updated Branches: refs/heads/master 5c9cb3d63 -> 14dfef587
http://git-wip-us.apache.org/repos/asf/ant/blob/14dfef58/manual/tutorial-tasks-filesets-properties.html ---------------------------------------------------------------------- diff --git a/manual/tutorial-tasks-filesets-properties.html b/manual/tutorial-tasks-filesets-properties.html index 8df706f..220ae8d 100644 --- a/manual/tutorial-tasks-filesets-properties.html +++ b/manual/tutorial-tasks-filesets-properties.html @@ -46,7 +46,7 @@ property.</p> <h2 id="buildenvironment">Build environment</h2> <p>We can use the buildfile from the other tutorial and modify it a little bit. That's the advantage of using properties—we can reuse nearly the whole script. :-)</p> -<pre class="code"> +<pre> <?xml version="1.0" encoding="UTF-8"?> <project name="<b>FindTask</b>" basedir="." default="test"> ... @@ -66,18 +66,18 @@ same for sources).</p> <h2 id="propertyaccess">Property access</h2> <p>Our first step is to set a property to a value and print the value of that property. So our scenario would be</p> -<pre class="code"> +<pre> <find property="test" value="test-value"/> <find print="test"/></pre> <p>Ok, it can be rewritten with the core tasks</p> -<pre class="code"> +<pre> <property name="test" value="test-value"/> <echo message="${test}"/></pre> <p>but I have to start on known ground :-)</p> <p>So what to do? Handling three attributes (<var>property</var>, <var>value</var>, <var>print</var>) and an execute method. Because this is only an introduction example I don't do much checking:</p> -<pre class="code"> +<pre> import org.apache.tools.ant.BuildException; public class Find extends Task { @@ -104,15 +104,16 @@ public class Find extends Task { } }</pre> -<p>As said in the other tutorial, the property access is done via Project instance. We get this instance via the -public <code>getProject()</code> method which we inherit from <code>Task</code> (more precisely -from <code>ProjectComponent</code>). Reading a property is done via <code>getProperty(<i>propertyname</i>)</code> (very -simple, isn't it?). This property returns the value as <samp>String</samp> or <code>null</code> if not set.<br/> -Setting a property is ... not really difficult, but there is more than one setter. You can use -the <code>setProperty()</code> method which will do the job as expected. But there is a golden rule in -Ant: <em>properties are immutable</em>. And this method sets the property to the specified value—whether it has a -value before that or not. So we use another way. <code>setNewProperty()</code> sets the property only if there is no -property with that name. Otherwise a message is logged.</p> +<p>As said in the other tutorial, the property access is done via <code class="code">Project</code> instance. We get +this instance via the public <code class="code">getProject()</code> method which we inherit +from <code class="code">Task</code> (more precisely from <code class="code">ProjectComponent</code>). Reading a property +is done via <code class="code">getProperty(<i>propertyname</i>)</code> (very simple, isn't it?). This property returns +the value as <code>String</code> or <code>null</code> if not set.<br/> Setting a property is ... not really difficult, +but there is more than one setter. You can use the <code class="code">setProperty()</code> method which will do the job +as expected. But there is a golden rule in Ant: <em>properties are immutable</em>. And this method sets the property to +the specified value—whether it has a value before that or not. So we use another +way. <code class="code">setNewProperty()</code> sets the property only if there is no property with that name. Otherwise +a message is logged.</p> <p><em>(By the way, a short explanation of Ant's "namespaces"—not to be confused with XML namespaces: an <code><antcall></code> creates a new space for property names. All properties from the caller are passed to the @@ -123,7 +124,7 @@ callee, but the callee can set its own properties without notice by the caller.) <p>After putting our two line example from above into a target names <code>use.simple</code> we can call that from our test case:</p> -<pre class="code"> +<pre> import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -154,7 +155,7 @@ public class FindTest { and I don't have to spend more explanations about their usage in buildfiles. Our goal is to search for a file in path. And in this step the path is simply a fileset (or more precise: a collection of filesets). So our usage would be</p> -<pre class="code"> +<pre> <find file="ant.jar" location="location.ant-jar"> <fileset dir="${ant.home}" includes="**/*.jar"/> </find></pre> @@ -162,7 +163,7 @@ be</p> <p>What do we need? A task with two attributes (<var>file</var>, <var>location</var>) and nested 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:</p> -<pre class="code"> +<pre> public class Find extends Task { private String file; @@ -196,10 +197,10 @@ tested?</p> <li>don't find a present file</li> <li>behaviour if file can't be found</li> </ul> -<p>Maybe you find some more test cases. But this is enough for now.<br/> -For each of these points we create a <code>testXX</code> method.</p> +<p>Maybe you find some more test cases. But this is enough for now.<br/> For each of these points we create +a <code class="code">testXX</code> method.</p> -<pre class="code"> +<pre> public class FindTest { @Rule @@ -252,10 +253,10 @@ public class FindTest { } }</pre> -<p>If we run this test class all test cases (except <var>testFileNotPresent</var>) fail. Now we can implement our task, -so that these test cases will pass.</p> +<p>If we run this test class all test cases (except <code class="code">testFileNotPresent</code>) fail. Now we can +implement our task, so that these test cases will pass.</p> -<pre class="code"> +<pre> protected void validate() { if (file == null) throw new BuildException("file not set"); if (location == null) throw new BuildException("location not set"); @@ -281,28 +282,29 @@ so that these test cases will pass.</p> getProject().setNewProperty(location, foundLocation); }</pre> -<p>On <strong>//1</strong> we check the prerequisites for our task. Doing that in a <code>validate</code>-method is a -common way, because we separate the prerequisites from the real work. On <strong>//2</strong> we iterate over all nested -filesets. If we don't want to handle multiple filesets, the <code>addFileset()</code> method has to reject the further -calls. We can get the result of a fileset via its DirectoryScanner like done in <strong>//3</strong>. After that we -create a platform independent String representation of the file path (<strong>//4</strong>, can be done in other ways of -course). We have to do the <code>replace()</code>, because we work with a simple string comparison. Ant itself is -platform independent and can therefore run on filesystems with slash (<q>/</q>, e.g. Linux) or backslash (<q>\</q>, -e.g. Windows) as path separator. Therefore we have to unify that. If we find our file, we create an absolute path -representation on <strong>//5</strong>, so that we can use that information without knowing the <var>basedir</var>. -(This is very important on use with multiple filesets, because they can have different <var>basedir</var>s and the -return value of the directory scanner is relative to its <var>basedir</var>.) Finally we store the location of the file -as property, if we had found one (<strong>//6</strong>).</p> +<p>On <strong>//1</strong> we check the prerequisites for our task. Doing that in a <code class="code">validate()</code> +method is a common way, because we separate the prerequisites from the real work. On <strong>//2</strong> we iterate +over all nested filesets. If we don't want to handle multiple filesets, the <code class="code">addFileset()</code> +method has to reject the further calls. We can get the result of a fileset via +its <code class="code">DirectoryScanner</code> like done in <strong>//3</strong>. After that we create a platform +independent String representation of the file path (<strong>//4</strong>, can be done in other ways of course). We have +to do the <code class="code">replace()</code>, because we work with a simple string comparison. Ant itself is platform +independent and can therefore run on filesystems with slash (<q>/</q>, e.g. Linux) or backslash (<q>\</q>, e.g. Windows) +as path separator. Therefore we have to unify that. If we find our file, we create an absolute path representation +on <strong>//5</strong>, so that we can use that information without knowing the <var>basedir</var>. (This is very +important on use with multiple filesets, because they can have different <var>basedir</var>s and the return value of the +directory scanner is relative to its <var>basedir</var>.) Finally we store the location of the file as property, if we +had found one (<strong>//6</strong>).</p> <p>Ok, much more easier in this simple case would be to add the <var>file</var> as additional <code>include</code> element to all filesets. But I wanted to show how to handle complex situations without being complex :-)</p> <p>The test case uses the Ant property <code>ant.home</code> as reference. This property is set by -the <code>Launcher</code> class which starts ant. We can use that property in our buildfiles as +the <code class="code">Launcher</code> class which starts ant. We can use that property in our buildfiles as a <a href="properties.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 <code><junit></code> task in <var>fork</var> mode. Therefore we have do modify our buildfile:</p> -<pre class="code"> +<pre> <target name="junit" description="Runs the unit tests" depends="jar"> <delete dir="${junit.out.dir.xml}"/> <mkdir dir="${junit.out.dir.xml}"/> @@ -327,24 +329,24 @@ modified to support paths instead of filesets. So we want that, too.</p> <p>Changing from fileset to path support is very easy:</p> <em><strong>Change Java code from:</strong></em> -<pre class="code"> +<pre> private List<FileSet> filesets = new ArrayList<>(); public void addFileset(FileSet fileset) { filesets.add(fileset); }</pre> <em><strong>to:</strong></em> -<pre class="code"> +<pre> private List<Path> paths = new ArrayList<>(); *1 public void add<b>Path</b>(<b>Path</b> path) { *2 paths.add(path); }</pre> <em><strong>and build file from:</strong></em> -<pre class="code"> +<pre> <find file="ant.jar" location="location.ant-jar"> <fileset dir="${ant.home}" includes="**/*.jar"/> </find></pre> <em><strong>to:</strong></em> -<pre class="code"> +<pre> <find file="ant.jar" location="location.ant-jar"> <b><path></b> *3 <fileset dir="${ant.home}" includes="**/*.jar"/> @@ -355,19 +357,20 @@ have to provide the right method: an <code>add<i>Name</i>(<i>Type</i> t)</code>. here. Finally we have to modify our buildfile on <strong>*3</strong> because our task doesn't support nested filesets any longer. So we wrap the fileset inside a path.</p> -<p>And now we modify the test case. Oh, not very much to do :-) Renaming the <code>testMissingFileset()</code> (not -really a <em>must-be</em> but better it's named like the thing it does) and update the <var>expected</var>-String in -that method (now a <samp>path not set</samp> message is expected). The more complex test cases base on the build -script. So the targets <var>testFileNotPresent</var> and <var>testFilePresent</var> have to be modified in the manner -described above.</p> +<p>And now we modify the test case. Oh, not very much to do :-) Renaming +the <code class="code">testMissingFileset()</code> (not really a <em>must-be</em> but better it's named like the thing +it does) and update the <var>expected</var>-String in that method (now a <samp>path not set</samp> message is +expected). The more complex test cases base on the build script. So the targets <var>testFileNotPresent</var> +and <var>testFilePresent</var> have to be modified in the manner described above.</p> <p>The test are finished. Now we have to adapt the task implementation. The easiest modification is in -the <code>validate()</code> method where we change the last line to <code>if (paths.size()<1) throw new -BuildException("path not set");</code>. In the <code>execute()</code> method we have a little more work. ... mmmh -... in reality it's less work, because the Path class does the whole DirectoryScanner-handling and -creating-absolute-paths stuff for us. So the execute method becomes just:</p> +the <code class="code">validate()</code> method where we change the last line to <code class="code">if +(paths.size()<1) throw new BuildException("path not set");</code>. In the <code class="code">execute()</code> method +we have a little more work. ... mmmh ... in reality it's less work, because the <code class="code">Path</code> class +does the whole <code class="code">DirectoryScanner</code>-handling and creating-absolute-paths stuff for us. So the +execute method becomes just:</p> -<pre class="code"> +<pre> public void execute() { validate(); String foundLocation = null; @@ -395,12 +398,12 @@ And would it be good to get all of them?—It depends ...<p> <p>In this section we will extend that task to support returning a list of all files. Lists as property values are not supported by Ant natively. So we have to see how other tasks use lists. The most famous task using lists is -Ant-Contribs <code><foreach></code>. All list elements are concatenated and separated with a customizable +Ant-Contrib's <code><foreach></code>. All list elements are concatenated and separated with a customizable separator (default <q>,</q>).</p> <p>So we do the following:</p> -<pre class="code"><find ... <b>delimiter=""</b>/> ... </find></pre> +<pre><find ... <b>delimiter=""</b>/> ... </find></pre> <p>if the delimiter is set, we will return all found files as list with that delimiter.</p> @@ -415,7 +418,7 @@ separator (default <q>,</q>).</p> <p>So we add as test case:</p> <strong><em>in the buildfile:</em></strong> -<pre class="code"> +<pre> <target name="test.init"> <mkdir dir="test1/dir11/dir111"/> *1 <mkdir dir="test1/dir11/dir112"/> @@ -446,7 +449,7 @@ separator (default <q>,</q>).</p> </delete> </target></pre> <strong><em>in the test class:</em></strong> -<pre class="code"> +<pre> public void testMultipleFiles() { executeTarget("testMultipleFiles"); String result = getProject().getProperty("location.test"); @@ -461,7 +464,7 @@ reuse later (<strong>*3</strong>). <p>The task implementation is modified as followed:</p> -<pre class="code"> +<pre> private List<String> foundFiles = new ArrayList<>(); ... private String delimiter = null; @@ -531,7 +534,7 @@ add a feature after an Ant release, provide a <em>since Ant xx</em> statement wh </ul> <p>As a template we have:</p> -<pre class="code"> +<pre> <html> <head> @@ -579,7 +582,7 @@ add a feature after an Ant release, provide a <em>since Ant xx</em> statement wh </html></pre> <p>Here is an example documentation page for our task:</p> -<pre class="code"> +<pre> <html> <head> @@ -683,17 +686,18 @@ behaviour <strong><em>hasn't</em></strong></li> <h3>Package / Directories</h3> <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: <code>org.apache.tools.ant.taskdefs</code>. Implementations are in the directory <samp>src/main</samp>, tests -in <samp>src/testcases</samp> and buildfiles for tests in <samp>src/etc/testcases</samp>.</p> +tasks: <code class="code">org.apache.tools.ant.taskdefs</code>. Implementations are in the +directory <samp>src/main</samp>, tests in <samp>src/testcases</samp> and buildfiles for tests +in <samp>src/etc/testcases</samp>.</p> <p>Now we integrate our work into Ant distribution. So first we do an update of our Git tree. If not done yet, you should clone the Ant repository on GitHub[7], then create a local clone:</p> -<pre class="output">git clone https://github.com/<em>your-sig</em>/ant.git</pre> +<pre class="input">git clone https://github.com/<em>your-sig</em>/ant.git</pre> <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 UNIX if needed):</p> -<pre class="output"> +<pre class="input"> ANTREPO> build // 1 ANTREPO> set ANT_HOME=%CD%\dist // 2 ANTREPO> ant test -Dtest.haltonfailure=false // 3</pre> @@ -723,7 +727,7 @@ the beginning. The advantage: this step isn't necessary and saves a lot of work </ul> <p>Now our modifications are done and we will retest it:</p> -<pre class="output"> +<pre class="input"> ANTREPO> build ANTREPO> ant run-single-test // 1 -Dtestcase=org.apache.tools.ant.taskdefs.FindTest // 2 @@ -734,12 +738,12 @@ not to halt on the first failure—we want to see all failures of our own te <p>And ... oh, all tests fail: <em>Ant could not find the task or a class this task relies upon.</em></p> <p>Ok: in the earlier steps we told Ant to use the Find class for the <code><find></code> task (remember -the <code><taskdef></code> 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 <samp>src/main/.../taskdefs/default.properties</samp>. Here is the mapping between taskname and implementing class -done. So we add a <code>find=org.apache.tools.ant.taskdefs.Find</code> as the last core task (just before the <code># -optional tasks</code> line). Now a second try:</p> -<pre class="output"> +the <code><taskdef></code> statement in the <q>use.init</q> target). But now we want to introduce that task as a +core task. And nobody wants to <code>taskdef</code> the <code>javac</code>, <code>echo</code>, ... So what to do? The +answer is the <samp>src/main/.../taskdefs/default.properties</samp>. Here is the mapping between taskname and +implementing class done. So we add a <code>find=org.apache.tools.ant.taskdefs.Find</code> as the last core task (just +before the <code># optional tasks</code> line). Now a second try:</p> +<pre class="input"> ANTREPO> build // 1 ANTREPO> ant run-single-test -Dtestcase=org.apache.tools.ant.taskdefs.FindTest @@ -747,10 +751,10 @@ ANTREPO> ant run-single-test <p>We have to rebuild (<strong>//1</strong>) Ant because the test look in the <samp>%ANT_HOME%\lib\ant.jar</samp> (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.</p> -<pre class="output">ANTREPO> ant test -Dtest.haltonfailure=false</pre> +<pre class="input">ANTREPO> ant test -Dtest.haltonfailure=false</pre> <p>Because there are a lot of tests this step requires a little bit of time. So use the <q>run-single-test</q> during development and do the <q>test</q> only at the end (maybe sometimes during development too). We use -the <code>-Dtest.haltonfailure=false</code> here because there could be other tests fail and we have to look into +the <kbd>-Dtest.haltonfailure=false</kbd> 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 @@ -767,7 +771,7 @@ from <a href="https://www.oracle.com/technetwork/java/archive-139210.html" targe <p>Clean the <code>ANT_HOME</code> variable, delete the <samp>build</samp>, <samp>bootstrap</samp> and <samp>dist</samp> directories, and point <code>JAVA_HOME</code> to the JDK 5 home directory. Then create the patch with your commit, checkout 1.9.x branch in Git, apply your patch and do the <code>build</code>, set <code>ANT_HOME</code> and -run <code>ant test</code> (like above).</p> +run <kbd>ant test</kbd> (like above).</p> <p>Our test should pass.</p> @@ -784,7 +788,7 @@ All jar's stored there are available to Ant so you haven't to add it to you <sam feature is available <em>since Ant 1.6</em>).</p> <p>So we will run the tests with</p> -<pre class="output">ANTREPO> ant -f check.xml checkstyle htmlreport</pre> +<pre class="input">ANTREPO> ant -f check.xml checkstyle htmlreport</pre> <p>I prefer the HTML report because there are lots of messages and we can navigate faster. Open the <samp>ANTREPO/build/reports/checkstyle/html/index.html</samp> and navigate to the <samp>Find.java</samp>. Now we see that there are some errors: missing whitespaces, unused imports, missing javadocs. So we have to do that.</p> http://git-wip-us.apache.org/repos/asf/ant/blob/14dfef58/manual/tutorial-writing-tasks.html ---------------------------------------------------------------------- diff --git a/manual/tutorial-writing-tasks.html b/manual/tutorial-writing-tasks.html index a1dee02..c292f70 100644 --- a/manual/tutorial-writing-tasks.html +++ b/manual/tutorial-writing-tasks.html @@ -17,7 +17,7 @@ <html> <head> <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"/> </head> <body> <h1>Tutorial: Writing Tasks</h1> @@ -53,7 +53,7 @@ names <samp>build.xml</samp>. What should Ant do for us?</p> <li>clean up everything</li> </ul> So the buildfile contains three targets. -<pre class="code"> +<pre> <?xml version="1.0" encoding="UTF-8"?> <project name="MyTask" basedir="." default="jar"> @@ -77,7 +77,7 @@ rewrite that using <code><property></code>s. On second there are some hand requires that the destination directory exists; a call of <q>clean</q> with a non existing classes directory will fail; <q>jar</q> requires the execution of some steps before. So the refactored code is: -<pre class="code"> +<pre> <?xml version="1.0" encoding="UTF-8"?> <project name="MyTask" basedir="." default="jar"> @@ -106,20 +106,20 @@ properties [1]</a> of Ant.</p> <p>Now we write the simplest Task—a HelloWorld Task (what else?). Create a text file <samp>HelloWorld.java</samp> in the src-directory with:</p> -<pre class="code"> +<pre> public class HelloWorld { public void execute() { System.out.println("Hello World"); } }</pre> -<p>and we can compile and jar it with <code>ant</code> (default target is <q>jar</q> and via its <var>depends</var> +<p>and we can compile and jar it with <kbd>ant</kbd> (default target is <q>jar</q> and via its <var>depends</var> attribute the <q>compile</q> is executed before).</p> <h2 id="use1">Use the Task</h2> <p>But after creating the jar we want to use our new Task. Therefore we need a new target <q>use</q>. Before we can use our new task we have to declare it with <a href="Tasks/taskdef.html" target="_top"><code><taskdef></code> [2]</a>. And for easier process we change the <var>default</var> attribute:</p> -<pre class="code"> +<pre> <?xml version="1.0" encoding="UTF-8"?> <project name="MyTask" basedir="." default="<b>use</b>"> @@ -135,7 +135,7 @@ our new task we have to declare it with <a href="Tasks/taskdef.html" target="_to <p>Important is the <var>classpath</var> attribute. Ant searches in its <samp>/lib</samp> directory for tasks and our task isn't there. So we have to provide the right location.</p> -<p>Now we can type in <code>ant</code> and all should work ...</p> +<p>Now we can type in <kbd>ant</kbd> and all should work ...</p> <pre class="output"> Buildfile: build.xml @@ -154,13 +154,14 @@ Total time: 3 seconds</pre> <h2 id="TaskAdapter">Integration with TaskAdapter</h2> <p>Our class has nothing to do with Ant. It extends no superclass and implements no interface. How does Ant know to -integrate? Via name convention: our class provides a method with signature <code>public void execute()</code>. This -class is wrapped by Ant's <code>org.apache.tools.ant.TaskAdapter</code> which is a task and uses reflection for setting -a reference to the project and calling the <code>execute()</code> method.</p> +integrate? Via name convention: our class provides a method with signature <code class="code">public void +execute()</code>. This class is wrapped by Ant's <code class="code">org.apache.tools.ant.TaskAdapter</code> which is a +task and uses reflection for setting a reference to the project and calling the <code class="code">execute()</code> +method.</p> <p><em>Setting a reference to the project</em>? Could be interesting. The Project class 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:</p> -<pre class="code"> +<pre> import org.apache.tools.ant.Project; public class HelloWorld { @@ -176,18 +177,18 @@ public class HelloWorld { project.log("Here is project '" + message + "'.", Project.MSG_INFO); } }</pre> -<p>and the execution with <code>ant</code> will show us the expected</p> +<p>and the execution with <kbd>ant</kbd> will show us the expected</p> <pre class="output"> use: Here is project 'MyTask'.</pre> <h2 id="derivingFromTask">Deriving from Ant's Task</h2> -<p>Ok, that works ... But usually you will extend <code>org.apache.tools.ant.Task</code>. That class is integrated in -Ant, gets the project reference, provides documentation fields, provides easier access to the logging facility and (very -useful) gives you the exact location where <em>in the buildfile</em> this task instance is used.</p> +<p>Ok, that works ... But usually you will extend <code class="code">org.apache.tools.ant.Task</code>. That class is +integrated in Ant, gets the project reference, provides documentation fields, provides easier access to the logging +facility and (very useful) gives you the exact location where <em>in the buildfile</em> this task instance is used.</p> <p>Oki-doki—let's us use some of these:</p> -<pre class="code"> +<pre> import org.apache.tools.ant.Task; public class HelloWorld extends Task { @@ -209,23 +210,25 @@ use: [helloworld] I am used in: C:\tmp\anttests\MyFirstTask\build.xml:23:</pre> <h2 id="accessTaskProject">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 class="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 class="code">execute()</code> is called, the Project object is +available.</p> <p>Here are two useful methods from class Project:</p> <ul> - <li><code>String getProperty(String propertyName)</code></li> - <li><code>String replaceProperties(String value)</code></li> + <li><code class="code">String getProperty(String propertyName)</code></li> + <li><code class="code">String replaceProperties(String value)</code></li> </ul> -<p>The method <code>replaceProperties()</code> is discussed further in section <a href="#NestedText">Nested Text</a>.</p> +<p>The method <code class="code">replaceProperties()</code> is discussed further in section <a href="#NestedText">Nested +Text</a>.</p> <h2 id="attributes">Attributes</h2> <p>Now we want to specify the text of our message (it seems that we are rewriting the <code><echo/></code> task -:-). First we well do that with an attribute. It is very easy—for each attribute provide a <code>public void -set<code><attributename></code>(<code><type></code> newValue)</code> method and Ant will do the rest via -reflection.</p> -<pre class="code"> +:-). First we well do that with an attribute. It is very easy—for each attribute provide +a <code class="code">public void set<i>Attributename</i>(<i>Type</i> newValue)</code> method and Ant will do the rest +via reflection.</p> +<pre> import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; @@ -244,14 +247,14 @@ public class HelloWorld extends Task { } }</pre> -<p>Oh, what's that in <code>execute()</code>? Throw a <code>BuildException</code>? Yes, that's the usual way to show Ant -that something important is missed and complete build should fail. The string provided there is written as -build-fails-message. Here it's necessary because the <code>log()</code> method can't handle a <code>null</code> value as -parameter and throws a NullPointerException. (Of course you can initialize the <var>message</var> with a default -string.)</p> +<p>Oh, what's that in <code class="code">execute()</code>? Throw a <code>BuildException</code>? Yes, that's the usual +way to show Ant that something important is missed and complete build should fail. The string provided there is written +as build-fails-message. Here it's necessary because the <code class="code">log()</code> method can't handle +a <code>null</code> value as parameter and throws a <code>NullPointerException</code>. (Of course you can initialize +the <var>message</var> with a default string.)</p> <p>After that we have to modify our buildfile:</p> -<pre class="code"> +<pre> <target name="use" description="Use the Task" depends="jar"> <taskdef name="helloworld" classname="HelloWorld" @@ -262,11 +265,12 @@ string.)</p> <p>Some background for working with attributes: Ant supports any of these datatypes as arguments of the set-method:</p> <ul> -<li>primitive data types like <code>int</code>, <code>long</code>, ...</li> -<li>their wrapper classes like <code>java.lang.Integer</code>, <code>java.lang.Long</code>, ...</li> -<li><code>java.lang.String</code></li> -<li>some other classes (e.g. <code>java.io.File</code>; see <a href="develop.html#set-magic">Manual 'Writing Your Own -Task' [3]</a>)</li> +<li>primitive data types like <code class="code">int</code>, <code class="code">long</code>, ...</li> +<li>their wrapper classes like <code class="code">java.lang.Integer</code>, <code class="code">java.lang.Long</code>, +...</li> +<li><code class="code">java.lang.String</code></li> +<li>some other classes (e.g. <code class="code">java.io.File</code>; see <a href="develop.html#set-magic">Manual +'Writing Your Own Task' [3]</a>)</li> <li>Any Java Object parsed from Ant 1.8's <a href="Tasks/propertyhelper.html">Property Helper</a></li> </ul> @@ -275,8 +279,9 @@ would not set the message string to <q>${msg}</q> if there is a property <code>m <h2 id="NestedText">Nested Text</h2> <p>Maybe you have used the <code><echo></code> task in a way like <code><echo>Hello -World</echo></code>. For that you have to provide a <code>public void addText(String text)</code> method.</p> -<pre class="code"> +World</echo></code>. For that you have to provide a <code class="code">public void addText(String text)</code> +method.</p> +<pre> ... public class HelloWorld extends Task { private String message; @@ -287,10 +292,11 @@ public class HelloWorld extends Task { ... }</pre> <p>But here properties are <strong>not</strong> resolved! For resolving properties we have to use -Project's <code>replaceProperties(String propname)</code> method which takes the property name as argument and returns -its value (or <code>${propname}</code> if not set).</p> -<p>Thus, to replace properties in the nested node text, our method <code>addText()</code> can be written as:</p> -<pre class="code"> +Project's <code class="code">replaceProperties(String propname)</code> method which takes the property name as argument +and returns its value (or <code>${propname}</code> if not set).</p> +<p>Thus, to replace properties in the nested node text, our method <code class="code">addText()</code> can be written +as:</p> +<pre> public void addText(String text) { message = getProject().replaceProperties(text); }</pre> @@ -301,12 +307,13 @@ the <a href="develop.html#nested-elements">Manual [4]</a> for other. We use the ways. There are several steps for that:</p> <ol> <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 as for the task (<code>set<i>attributename</i>()</code> methods).</li> +rules for attributes and nested elements as for the task (<code class="code">set<i>Attributename</i>()</code> +methods).</li> <li>The task holds multiple instances of this class in a list.</li> <li>A factory method instantiates an object, saves the reference in the list and returns it to Ant Core.</li> -<li>The <code>execute()</code> method iterates over the list and evaluates its values.</li> +<li>The <code class="code">execute()</code> method iterates over the list and evaluates its values.</li> </ol> -<pre class="code"> +<pre> import java.util.ArrayList; import java.util.List; ... @@ -335,9 +342,9 @@ import java.util.List; } ...</pre> <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: <code>public <i>classname</i> create<i>XML-name</i>()</code>. Therefore we -write in the buildfile</p> -<pre class="code"> +classname is defined in the factory method: <code class="code">public <i>classname</i> +create<i>XML-name</i>()</code>. Therefore we write in the buildfile</p> +<pre> <helloworld> <message msg="Nested Element 1"/> <message msg="Nested Element 2"/> @@ -347,7 +354,7 @@ as <code>static</code></p> <h2 id="complex">Our task in a little more complex version</h2> <p>For recapitulation now a little refactored buildfile:</p> -<pre class="code"> +<pre> <?xml version="1.0" encoding="UTF-8"?> <project name="MyTask" basedir="." default="use"> @@ -418,7 +425,7 @@ as <code>static</code></p> </project></pre> <p>And the code of the task:</p> -<pre class="code"> +<pre> import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; import java.util.ArrayList; @@ -438,7 +445,7 @@ public class HelloWorld extends Task { message = msg; } - /** Should the build fail? Defaults to <em>false</em>. As attribute. */ + /** Should the build fail? Defaults to <i>false</i>. As attribute. */ boolean fail = false; public void setFail(boolean b) { fail = b; @@ -542,10 +549,10 @@ C:\tmp\anttests\MyFirstTask></pre> <h2 id="TestingTasks">Test the Task</h2> <p>We have written a test already: the <q>use.*</q> targets in the buildfile. But it's difficult to test that automatically. Commonly (and in Ant) JUnit is used for that. For testing tasks Ant provides a JUnit -Rule <code>org.apache.tools.ant.BuildFileRule</code>. This class provides some for testing tasks useful methods: -initialize Ant, load a buildfile, execute targets, capture debug and run logs ...</p> +Rule <code class="code">org.apache.tools.ant.BuildFileRule</code>. This class provides some for testing tasks useful +methods: initialize Ant, load a buildfile, execute targets, capture debug and run logs ...</p> -<p>In Ant it is usual that the testcase has the same name as the task with a prepending <code>Test</code>, therefore we +<p>In Ant it is usual that the testcase has the same name as the task with a prepended <code>Test</code>, therefore we will create a file <samp>HelloWorldTest.java</samp>. Because we have a very small project we can put this file into <samp>src</samp> directory (Ant's own testclasses are in <samp>/src/testcases/...</samp>). Because we have already written our tests for "hand-test" we can use that for automatic tests, too. All test supporting classes are a part of @@ -554,7 +561,7 @@ jar file from source distro with target "test-jar". <p>For executing the test and creating a report we need the optional tasks <code><junit></code> and <code><junitreport></code>. So we add to the buildfile:</p> -<pre class="code"> +<pre> <span style="color:gray"><project name="MyTask" basedir="." </span>default="test"<span style="color:gray">></span> ... <property name="ant.test.lib" value="ant-testutil.jar"/> @@ -613,11 +620,12 @@ and <code><junitreport></code>. So we add to the buildfile:</p> ... <span style="color:gray"></project></span></pre> -<p>Back to the <samp>src/HelloWorldTest.java</samp>. We create a class with a public <code>BuildFileRule</code> field -annotated with JUnit's <code>@Rule</code> annotation. As per conventional JUnit4 tests, this class should have no -constructors, or a default no-args constructor, setup methods should be annotated with <code>@Before</code>, tear down -methods annotated with <code>@After</code> and any test method annotated with <code>@Test</code>. -<pre class="code"> +<p>Back to the <samp>src/HelloWorldTest.java</samp>. We create a class with a +public <code class="code">BuildFileRule</code> field annotated with JUnit's <code class="code">@Rule</code> +annotation. As per conventional JUnit4 tests, this class should have no constructors, nor a default no-args constructor, +setup methods should be annotated with <code class="code">@Before</code>, tear down methods annotated +with <code class="code">@After</code> and any test method annotated with <code class="code">@Test</code>. +<pre> import org.apache.tools.ant.BuildFileRule; import org.junit.Assert; import org.junit.Test; @@ -677,7 +685,7 @@ public class HelloWorldTest { } }</pre> -<p>When starting <code>ant</code> we'll get a short message to STDOUT and a nice HTML report.</p> +<p>When starting <kbd>ant</kbd> we'll get a short message to STDOUT and a nice HTML report.</p> <pre class="output"> C:\tmp\anttests\MyFirstTask>ant Buildfile: build.xml @@ -709,19 +717,20 @@ C:\tmp\anttests\MyFirstTask></pre> <h2 id="Debugging">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 <kbd>-verbose</kbd>. For more information, try flag <kbd>-debug</kbd>.</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> <ul> - <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>Initial <code class="code">main()</code> + function: <code class="code">com.apache.tools.ant.launch.Launcher.main()</code></li> + <li>Task entry point: <code class="code">com.apache.tools.ant.UnknownElement.execute()</code></li> </ul> -<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 -JVM.</p> +<p>If you need to debug when a task attribute or the text is set, begin by debugging into +method <code class="code">execute()</code> of your custom task. Then set breakpoints in other methods. This will +ensure the class bytecode has been loaded by JVM.</p> <h2 id="resources">Resources</h2> <p>This tutorial and its resources are available via <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=22570" http://git-wip-us.apache.org/repos/asf/ant/blob/14dfef58/manual/using.html ---------------------------------------------------------------------- diff --git a/manual/using.html b/manual/using.html index e66ea2b..0f357fa 100644 --- a/manual/using.html +++ b/manual/using.html @@ -48,7 +48,7 @@ the <a href="#tasks">Tasks</a> section below.)</p> <td>the default target to use when no target is supplied.</td> <td>No; however, <em>since Ant 1.6.0</em>, every project includes an implicit target that contains any and all top-level tasks and/or types. This target will always be executed as part of the project's initialization, even - when Ant is run with the <a href="running.html#options"><code>-projecthelp</code></a> option. + when Ant is run with the <a href="running.html#options"><kbd>-projecthelp</kbd></a> option. </td> </tr> <tr> @@ -180,7 +180,7 @@ and <code><taskdef></code>). When you do this they are evaluated before a will generate build failures if they are used outside of targets as they may cause infinite loops otherwise (<code><antcall></code> for example).</p> -<p>We have given some targets descriptions; this causes the <code>-projecthelp</code> invocation option to list them as +<p>We have given some targets descriptions; this causes the <kbd>-projecthelp</kbd> invocation option to list them as public targets with the descriptions; the other target is internal and not listed.</p> <p>Finally, for this target to work the source in the <samp>src</samp> subdirectory should be stored in a directory tree which matches the package names. Check the <code><javac></code> task for details.</p> @@ -424,7 +424,7 @@ deliberately assign a different meaning to <var>refid</var>.</p> <p>Don't add anything to the <code>CLASSPATH</code> environment variable—this is often the reason for very obscure errors. Use Ant's own <a href="install.html#optionalTasks">mechanisms</a> for adding libraries:</p> <ul> - <li>via command line argument <code>-lib</code></li> + <li>via command line argument <kbd>-lib</kbd></li> <li>adding to <code>${user.home}/.ant/lib</code></li> <li>adding to <code>${ant.home}/lib</code></li> </ul>