aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/manual/develop.html
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/manual/develop.html')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/manual/develop.html544
1 files changed, 544 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/manual/develop.html b/framework/src/ant/apache-ant-1.9.6/manual/develop.html
new file mode 100644
index 00000000..ed06d301
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/manual/develop.html
@@ -0,0 +1,544 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<link rel="stylesheet" type="text/css" href="stylesheets/style.css">
+<title>Writing Your Own Task</title>
+</head>
+
+<body>
+<h1>Developing with Apache Ant</h1>
+
+<h2><a name="writingowntask">Writing Your Own Task</a></h2>
+<p>It is very easy to write your own task:</p>
+<ol>
+ <li>Create a Java class that extends <code>org.apache.tools.ant.Task</code>
+ or <a href="base_task_classes.html">another class</a> that was designed to be extended.</li>
+
+ <li>For each attribute, write a <i>setter</i> method. The setter method must be a
+ <code>public void</code> method that takes a single argument. The
+ name of the method must begin with <code>set</code>, followed by the
+ attribute name, with the first character of the name in uppercase, and the rest in
+ lowercase<a href="#footnote-1"><sup>*</sup></a>. That is, to support an attribute named
+ <code>file</code> you create a method <code>setFile</code>.
+ Depending on the type of the argument, Ant will perform some
+ conversions for you, see <a href="#set-magic">below</a>.</li>
+
+ <li>If your task shall contain other tasks as nested elements (like
+ <a href="Tasks/parallel.html"><code>parallel</code></a>), your
+ class must implement the interface
+ <code>org.apache.tools.ant.TaskContainer</code>. If you do so, your
+ task can not support any other nested elements. See
+ <a href="#taskcontainer">below</a>.</li>
+
+ <li>If the task should support character data (text nested between the
+ start end end tags), write a <code>public void addText(String)</code>
+ method. Note that Ant does <strong>not</strong> expand properties on
+ the text it passes to the task.</li>
+
+ <li>For each nested element, write a <i>create</i>, <i>add</i> or
+ <i>addConfigured</i> method. A create method must be a
+ <code>public</code> method that takes no arguments and returns an
+ <code>Object</code> type. The name of the create method must begin
+ with <code>create</code>, followed by the element name. An add (or
+ addConfigured) method must be a <code>public void</code> method that
+ takes a single argument of an <code>Object</code> type with a
+ no-argument constructor. The name of the add (addConfigured) method
+ must begin with <code>add</code> (<code>addConfigured</code>),
+ followed by the element name. For a more complete discussion see
+ <a href="#nested-elements">below</a>.</li>
+
+ <li>Write a <code>public void execute</code> method, with no arguments, that
+ throws a <code>BuildException</code>. This method implements the task
+ itself.</li>
+</ol>
+
+<hr>
+<p><a name="footnote-1">*</a> Actually the case of the letters after
+the first one doesn't really matter to Ant, using all lower case is a
+good convention, though.</p>
+
+<h3>The Life-cycle of a Task</h3>
+<ol>
+ <li>
+ The xml element that contains the tag corresponding to the
+ task gets converted to an UnknownElement at parser time.
+ This UnknownElement gets placed in a list within a target
+ object, or recursively within another UnknownElement.
+ </li>
+ <li>
+ When the target is executed, each UnknownElement is invoked
+ using an <code>perform()</code> method. This instantiates
+ the task. This means that tasks only gets
+ instantiated at run time.
+ </li>
+
+ <li>The task gets references to its project and location inside the
+ buildfile via its inherited <code>project</code> and
+ <code>location</code> variables.</li>
+
+ <li>If the user specified an <code>id</code> attribute to this task,
+ the project
+ registers a reference to this newly created task, at run
+ time.</li>
+
+ <li>The task gets a reference to the target it belongs to via its
+ inherited <code>target</code> variable.</li>
+
+ <li><code>init()</code> is called at run time.</li>
+
+ <li>All child elements of the XML element corresponding to this task
+ are created via this task's <code>createXXX()</code> methods or
+ instantiated and added to this task via its <code>addXXX()</code>
+ methods, at run time. Child elements corresponding
+ to <code>addConfiguredXXX()</code> are created at this point but
+ the actual <code>addCondifgired</code> method is not called.</li>
+
+ <li>All attributes of this task get set via their corresponding
+ <code>setXXX</code> methods, at runtime.</li>
+
+ <li>The content character data sections inside the XML element
+ corresponding to this task is added to the task via its
+ <code>addText</code> method, at runtime.</li>
+
+ <li>All attributes of all child elements get set via their corresponding
+ <code>setXXX</code> methods, at runtime.</li>
+
+ <li>If child elements of the XML element corresponding to this task
+ have been created for <code>addConfiguredXXX()</code> methods,
+ those methods get invoked now.</li>
+
+ <li><a name="execute"><code>execute()</code></a> is called at runtime.
+ If <code>target1</code> and <code>target2</code> both depend
+ on <code>target3</code>, then running
+ <code>'ant target1 target2'</code> will run all tasks in
+ <code>target3</code> twice.</li>
+</ol>
+
+<h3><a name="set-magic">Conversions Ant will perform for attributes</a></h3>
+
+<p>Ant will always expand properties before it passes the value of an
+attribute to the corresponding setter method. <b>Since Ant 1.8</b>, it is
+possible to <a href="Tasks/propertyhelper.html">extend Ant's property handling</a>
+such that a non-string Object may be the result of the evaluation of a string
+containing a single property reference. These will be assigned directly via
+setter methods of matching type. Since it requires some beyond-the-basics
+intervention to enable this behavior, it may be a good idea to flag attributes
+intended to permit this usage paradigm.
+</p>
+
+<p>The most common way to write an attribute setter is to use a
+<code>java.lang.String</code> argument. In this case Ant will pass
+the literal value (after property expansion) to your task. But there
+is more! If the argument of you setter method is</p>
+
+<ul>
+
+ <li><code>boolean</code>, your method will be passed the value
+ <i>true</i> if the value specified in the build file is one of
+ <code>true</code>, <code>yes</code>, or <code>on</code> and
+ <i>false</i> otherwise.</li>
+
+ <li><code>char</code> or <code>java.lang.Character</code>, your
+ method will be passed the first character of the value specified in
+ the build file.</li>
+
+ <li>any other primitive type (<code>int</code>, <code>short</code>
+ and so on), Ant will convert the value of the attribute into this
+ type, thus making sure that you'll never receive input that is not a
+ number for that attribute.</li>
+
+ <li><code>java.io.File</code>, Ant will first determine whether the
+ value given in the build file represents an absolute path name. If
+ not, Ant will interpret the value as a path name relative to the
+ project's basedir.</li>
+
+ <li><code>org.apache.tools.ant.types.Resource</code>
+ <code>org.apache.tools.ant.types.Resource</code>, Ant will
+ resolve the string as a <code>java.io.File</code> as above, then
+ pass in as a <code>org.apache.tools.ant.types.resources.FileResource</code>.
+ <b>Since Ant 1.8</b>
+ </li>
+
+ <li><code>org.apache.tools.ant.types.Path</code>, Ant will tokenize
+ the value specified in the build file, accepting <code>:</code> and
+ <code>;</code> as path separators. Relative path names will be
+ interpreted as relative to the project's basedir.</li>
+
+ <li><code>java.lang.Class</code>, Ant will interpret the value
+ given in the build file as a Java class name and load the named
+ class from the system class loader.</li>
+
+ <li>any other type that has a constructor with a single
+ <code>String</code> argument, Ant will use this constructor to
+ create a new instance from the value given in the build file.</li>
+
+ <li>A subclass of
+ <code>org.apache.tools.ant.types.EnumeratedAttribute</code>, Ant
+ will invoke this classes <code>setValue</code> method. Use this if
+ your task should support enumerated attributes (attributes with
+ values that must be part of a predefined set of values). See
+ <code>org/apache/tools/ant/taskdefs/FixCRLF.java</code> and the
+ inner <code>AddAsisRemove</code> class used in <code>setCr</code>
+ for an example.</li>
+
+ <li>A (Java 5) enumeration. Ant will call the setter with the enum constant
+ matching the value given in the build file. This is easier than using
+ <code>EnumeratedAttribute</code> and can result in cleaner code, but of course
+ your task will not run on JDK 1.4 or earlier. Note that any override of
+ <code>toString()</code> in the enumeration is ignored; the build file must use
+ the declared name (see <code>Enum.getName()</code>). You may wish to use lowercase
+ enum constant names, in contrast to usual Java style, to look better in build files.
+ <em>As of Ant 1.7.0.</em></li>
+
+</ul>
+
+<p>What happens if more than one setter method is present for a given
+attribute? A method taking a <code>String</code> argument will always
+lose against the more specific methods. If there are still more
+setters Ant could chose from, only one of them will be called, but we
+don't know which, this depends on the implementation of your Java
+virtual machine.</p>
+
+<h3><a name="nested-elements">Supporting nested elements</a></h3>
+
+<p>Let's assume your task shall support nested elements with the name
+<code>inner</code>. First of all, you need a class that represents
+this nested element. Often you simply want to use one of Ant's
+classes like <code>org.apache.tools.ant.types.FileSet</code> to
+support nested <code>fileset</code> elements.</p>
+
+<p>Attributes of the nested elements or nested child elements of them
+will be handled using the same mechanism used for tasks (i.e. setter
+methods for attributes, addText for nested text and
+create/add/addConfigured methods for child elements).</p>
+
+<p>Now you have a class <code>NestedElement</code> that is supposed to
+be used for your nested <code>&lt;inner&gt;</code> elements, you have
+three options:</p>
+
+<ol>
+ <li><code>public NestedElement createInner()</code></li>
+ <li><code>public void addInner(NestedElement anInner)</code></li>
+ <li><code>public void addConfiguredInner(NestedElement anInner)</code></li>
+</ol>
+
+<p>What is the difference?</p>
+
+<p>Option 1 makes the task create the instance of
+<code>NestedElement</code>, there are no restrictions on the type.
+For the options 2 and 3, Ant has to create an instance of
+<code>NestedInner</code> before it can pass it to the task, this
+means, <code>NestedInner</code> must have a <code>public</code> no-arg
+ constructor or a <code>public</code> one-arg constructor
+ taking a Project class as a parameter.
+This is the only difference between options 1 and 2.</p>
+
+<p>The difference between 2 and 3 is what Ant has done to the object
+before it passes it to the method. <code>addInner</code> will receive
+an object directly after the constructor has been called, while
+<code>addConfiguredInner</code> gets the object <em>after</em> the
+attributes and nested children for this new object have been
+handled.</p>
+
+<p>What happens if you use more than one of the options? Only one of
+the methods will be called, but we don't know which, this depends on
+the implementation of your Java virtual machine.</p>
+
+<h3><a name="nestedtype">Nested Types</a></h3>
+If your task needs to nest an arbitrary type that has been defined
+ using <code>&lt;typedef&gt;</code> you have two options.
+ <ol>
+ <li><code>public void add(Type type)</code></li>
+ <li><code>public void addConfigured(Type type)</code></li>
+ </ol>
+ The difference between 1 and 2 is the same as between 2 and 3 in the
+ previous section.
+ <p>
+ For example suppose one wanted to handle objects object of type
+ org.apache.tools.ant.taskdefs.condition.Condition, one may
+ have a class:
+ </p>
+ <blockquote>
+ <pre>
+public class MyTask extends Task {
+ private List conditions = new ArrayList();
+ public void add(Condition c) {
+ conditions.add(c);
+ }
+ public void execute() {
+ // iterator over the conditions
+ }
+}
+ </pre>
+ </blockquote>
+ <p>
+ One may define and use this class like this:
+ </p>
+ <blockquote>
+ <pre>
+&lt;taskdef name="mytask" classname="MyTask" classpath="classes"/&gt;
+&lt;typedef name="condition.equals"
+ classname="org.apache.tools.ant.taskdefs.conditions.Equals"/&gt;
+&lt;mytask&gt;
+ &lt;condition.equals arg1="${debug}" arg2="true"/&gt;
+&lt;/mytask&gt;
+ </pre>
+ </blockquote>
+ <p>
+ A more complicated example follows:
+ </p>
+ <blockquote>
+ <pre>
+public class Sample {
+ public static class MyFileSelector implements FileSelector {
+ public void setAttrA(int a) {}
+ public void setAttrB(int b) {}
+ public void add(Path path) {}
+ public boolean isSelected(File basedir, String filename, File file) {
+ return true;
+ }
+ }
+
+ interface MyInterface {
+ void setVerbose(boolean val);
+ }
+
+ public static class BuildPath extends Path {
+ public BuildPath(Project project) {
+ super(project);
+ }
+
+ public void add(MyInterface inter) {}
+ public void setUrl(String url) {}
+ }
+
+ public static class XInterface implements MyInterface {
+ public void setVerbose(boolean x) {}
+ public void setCount(int c) {}
+ }
+}
+ </pre>
+ </blockquote>
+ <p>
+ This class defines a number of static classes that implement/extend
+ Path, MyFileSelector and MyInterface. These may be defined and used
+ as follows:
+ </p>
+ <pre>
+ <blockquote>
+&lt;typedef name="myfileselector" classname="Sample$MyFileSelector"
+ classpath="classes" loaderref="classes"/&gt;
+&lt;typedef name="buildpath" classname="Sample$BuildPath"
+ classpath="classes" loaderref="classes"/&gt;
+&lt;typedef name="xinterface" classname="Sample$XInterface"
+ classpath="classes" loaderref="classes"/&gt;
+
+&lt;copy todir="copy-classes"&gt;
+ &lt;fileset dir="classes"&gt;
+ &lt;myfileselector attra="10" attrB="-10"&gt;
+ &lt;buildpath path="." url="abc"&gt;
+ &lt;xinterface count="4"/&gt;
+ &lt;/buildpath&gt;
+ &lt;/myfileselector&gt;
+ &lt;/fileset&gt;
+&lt;/copy&gt;
+ </blockquote>
+ </pre>
+
+<h3><a name="taskcontainer">TaskContainer</a></h3>
+
+<p>The <code>TaskContainer</code> consists of a single method,
+<code>addTask</code> that basically is the same as an <a
+href="#nested-elements">add method</a> for nested elements. The task
+instances will be configured (their attributes and nested elements
+have been handled) when your task's <code>execute</code> method gets
+invoked, but not before that.</p>
+
+<p>When we <a href="#execute">said</a> <code>execute</code> would be
+called, we lied ;-). In fact, Ant will call the <code>perform</code>
+method in <code>org.apache.tools.ant.Task</code>, which in turn calls
+<code>execute</code>. This method makes sure that <a
+href="#buildevents">Build Events</a> will be triggered. If you
+execute the task instances nested into your task, you should also
+invoke <code>perform</code> on these instances instead of
+<code>execute</code>.</p>
+
+<h3>Example</h3>
+<p>Let's write our own task, which prints a message on the
+<code>System.out</code> stream.
+The task has one attribute, called <code>message</code>.</p>
+<blockquote>
+<pre>
+package com.mydomain;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+public class MyVeryOwnTask extends Task {
+ private String msg;
+
+ // The method executing the task
+ public void execute() throws BuildException {
+ System.out.println(msg);
+ }
+
+ // The setter for the &quot;message&quot; attribute
+ public void setMessage(String msg) {
+ this.msg = msg;
+ }
+}
+</pre>
+</blockquote>
+<p>It's really this simple ;-)</p>
+<p>Adding your task to the system is rather simple too:</p>
+<ol>
+ <li>Make sure the class that implements your task is in the classpath when
+ starting Ant.</li>
+ <li>Add a <code>&lt;taskdef&gt;</code> element to your project.
+ This actually adds your task to the system.</li>
+ <li>Use your task in the rest of the buildfile.</li>
+</ol>
+
+<h3>Example</h3>
+<blockquote>
+<pre>
+&lt;?xml version=&quot;1.0&quot;?&gt;
+
+&lt;project name=&quot;OwnTaskExample&quot; default=&quot;main&quot; basedir=&quot;.&quot;&gt;
+ &lt;taskdef name=&quot;mytask&quot; classname=&quot;com.mydomain.MyVeryOwnTask&quot;/&gt;
+
+ &lt;target name=&quot;main&quot;&gt;
+ &lt;mytask message=&quot;Hello World! MyVeryOwnTask works!&quot;/&gt;
+ &lt;/target&gt;
+&lt;/project&gt;
+</pre>
+</blockquote>
+
+<h3>Example 2</h3>
+To use a task directly from the buildfile which created it, place the
+<code>&lt;taskdef&gt;</code> declaration inside a target
+<i>after the compilation</i>. Use the <code>classpath</code> attribute of
+<code>&lt;taskdef&gt;</code> to point to where the code has just been
+compiled.
+<blockquote>
+<pre>
+&lt;?xml version=&quot;1.0&quot;?&gt;
+
+&lt;project name=&quot;OwnTaskExample2&quot; default=&quot;main&quot; basedir=&quot;.&quot;&gt;
+
+ &lt;target name=&quot;build&quot; &gt;
+ &lt;mkdir dir=&quot;build&quot;/&gt;
+ &lt;javac srcdir=&quot;source&quot; destdir=&quot;build&quot;/&gt;
+ &lt;/target&gt;
+
+ &lt;target name=&quot;declare&quot; depends=&quot;build&quot;&gt;
+ &lt;taskdef name=&quot;mytask&quot;
+ classname=&quot;com.mydomain.MyVeryOwnTask&quot;
+ classpath=&quot;build&quot;/&gt;
+ &lt;/target&gt;
+
+ &lt;target name=&quot;main&quot; depends=&quot;declare&quot;&gt;
+ &lt;mytask message=&quot;Hello World! MyVeryOwnTask works!&quot;/&gt;
+ &lt;/target&gt;
+&lt;/project&gt;
+</pre>
+</blockquote>
+
+<p>Another way to add a task (more permanently), is to add the task name and
+implementing class name to the <code>default.properties</code> file in the
+<code>org.apache.tools.ant.taskdefs</code>
+package. Then you can use it as if it were a built-in task.</p>
+
+<hr>
+<h2><a name="buildevents">Build Events</a></h2>
+<p>Ant is capable of generating build events as it performs the tasks necessary to build a project.
+Listeners can be attached to Ant to receive these events. This capability could be used, for example,
+to connect Ant to a GUI or to integrate Ant with an IDE.
+</p>
+<p>To use build events you need to create an ant <code>Project</code> object. You can then call the
+<code>addBuildListener</code> method to add your listener to the project. Your listener must implement
+the <code>org.apache.tools.antBuildListener</code> interface. The listener will receive BuildEvents
+for the following events</p>
+<ul>
+ <li>Build started</li>
+ <li>Build finished</li>
+ <li>Target started</li>
+ <li>Target finished</li>
+ <li>Task started</li>
+ <li>Task finished</li>
+ <li>Message logged</li>
+</ul>
+
+<p>If the build file invokes another build file via
+<a href="Tasks/ant.html"><code>&lt;ant&gt;</code></a> or
+<a href="Tasks/subant.html"><code>&lt;subant&gt;</code></a> or uses
+<a href="Tasks/antcall.html"><code>&lt;antcall&gt;</code></a>, you are creating a
+new Ant "project" that will send target and task level events of its
+own but never sends build started/finished events. Ant 1.6.2
+introduces an extension of the BuildListener interface named
+SubBuildListener that will receive two new events for</p>
+<ul>
+ <li>SubBuild started</li>
+ <li>SubBuild finished</li>
+</ul>
+<p>If you are interested in those events, all you need to do is to
+implement the new interface instead of BuildListener (and register the
+listener, of course).</p>
+
+<p>If you wish to attach a listener from the command line you may use the
+<code>-listener</code> option. For example:</p>
+<blockquote>
+ <pre>ant -listener org.apache.tools.ant.XmlLogger</pre>
+</blockquote>
+<p>will run Ant with a listener that generates an XML representation of the build progress. This
+listener is included with Ant, as is the default listener, which generates the logging to standard output.</p>
+
+<p><b>Note: </b>A listener must not access System.out and System.err directly since output on
+these streams is redirected by Ant's core to the build event system. Accessing these
+streams can cause an infinite loop in Ant. Depending on the version of Ant, this will
+either cause the build to terminate or the Java VM to run out of Stack space. A logger, also, may
+not access System.out and System.err directly. It must use the streams with which it has
+been configured.</p>
+
+<p><b>Note2:</b> All methods of a BuildListener except for the "Build
+ Started" and "Build Finished" events may occur on several threads
+ simultaneously - for example while Ant is executing
+ a <code>&lt;parallel&gt;</code> task.</p>
+
+<hr>
+<h2><a name="integration">Source code integration</a></h2>
+
+<p>The other way to extend Ant through Java is to make changes to existing tasks, which is positively encouraged.
+Both changes to the existing source and new tasks can be incorporated back into the Ant codebase, which
+benefits all users and spreads the maintenance load around.</p>
+
+<p>Please consult the
+<a href="http://www.apache.org/foundation/getinvolved.html">Getting Involved</a> pages on the Apache web site
+for details on how to fetch the latest source and how to submit changes for reincorporation into the
+source tree.</p>
+
+<p>Ant also has some
+<a href="http://ant.apache.org/ant_task_guidelines.html">task guidelines</a>
+which provides some advice to people developing and testing tasks. Even if you intend to
+keep your tasks to yourself, you should still read this as it should be informative.</p>
+
+</body>
+</html>
+