After a long time of not-writing I have finished my (German) article about Ant 1.8.0. It is now published on JaxCenter: Der ANTwickler – Das neue Majorrelease
Posted tagged ‘Ant’
Ant Article online
24. März 2010Ant: Use optional dependencies in JavaDoc
19. November 2009If you create your Javadocs you sometimes get unresolved reference warnings: package xy does not exist or cannot find symbol
If you define the path with these dependencies outside of the target you could reference that path using the classpathref attribute.
But if the path definition is done in an other target and you don’t want to have a dependency on that (e.g. many dependencies are downloaded there, e.g. using Ivy), using the classpathref would throw a BuildException because the path is not defined: Reference my-path.reference not found.
You could do a little hack: use a classpath attribute and use a special PropertyEvaluator for using that path: classpathref=“${toString:my-path.reference}“. If your defining target is executed before, the toString: resolves that into a usable path-string. If the target is not executed before, the resulting string toString:my-path.reference is just ignored by the javadoc task.
Let Ant tasks choose the attribute values by themself
30. Oktober 2009For a long time an idea travelled in my head. But now it arrived.
In my several Ant build files I have constructs like
<javac source=”${javac.source}” debug=”${javac.debug}” target=”${javac.target}” …
and the according properties defined in an external file. Now have a compile run for the source code and the test code and you have doubled this amount of configuration. And I thought that just writing a <javac> and starting with an -autoconf option would be easier.
The idea is: apply the properties directly before the task execution.
So I could implement a method call in oata.Task.perform() direclty before calling the execute() method.
Hhm …. I don’t want to change the Ant core that deeply because so many external tasks exist and I don’t want to (maybe) break their build.
Another idea is using an AOP framework like AspectJ for jumping in: before <? extends Task>.execute() : applyAttributeValues()
(I am not familiar with AspectJ but you get the idea.)
But then I would depend on the AOP library. That’s nothing for the Core. And Ant options should not depend on any further libraries.
I could implement it as a task:
<project><autoconf/><javac/></project>
Better. But I have to learn AspectJ … so not for now…
On the Hudson dev-mailinglist I heard from the Hudson Clover Plugin. It gatheres code coverage from Ant jobs WITHOUT configuring the job itself.-It adds a BuildListener which stores the srcdir and destdir values from <javac> tasks.
Nice idea …. use the Listeners taskStarted(event) and taskFinished(event) methods for doing AOP-stuff.
This results in the <autoconf> task, currently in the sandbox and feedback is welcome.
The goal:
- apply attribute values from properties
- do not overwrite user specified values
- switch on/off the behaviour
- support name prefix for using different values for different targets
While the last two points are easily to implement (add/remove the listener, use a prefix for property search) the first two are difficult.
apply attribute values from properties / which attributes are supported by a given task?
Why is this difficult? Just ask mytask.getClass() for declared setters ….
The problem is that you don’t get the task object. Due lazy instantiation/configuration the only thing you get from the BuildEvent is an UnknownElement. And therefore you cannot just ask getClass() for the class object you need.
I saw three different strategies according to that value:
- if it is a <macrodef> I could ask it directly for its <attribute>s
- if it is a normal task I ask the class object
- if it is a <presetdef> I ask the class object from preset.getTypeClass()
do not overwrite user specified values
I could ask an object for its values, but which are set by the user and which are just implementation defaults? From the Java perspective you cannot distinguish between them…
My strategy is using a “clean” object (I called it template object) and compare its values with the values from the given object.
I found an overview article …
28. Dezember 2008On JavaWorld John Ferguson Smart wrote a nice article about some of the most interesting Java evolutions in 2008. He discovers tools for Build automatisation (Hudson, Bamboo, Maven, Ant, Grant, Gradle, Subversion), Testing tools (JBehave, easyb, Selenium, WebTest) and IDEs (Eclipse, NetBeans). Conclusion: a very nice read.
Ant + JavaFront: start Ant tasks from the command line (2)
11. November 2008In my last blog I wrote about a new AntLib in Ants sandbox: javafront with which you have the ability to start tasks directly from the command line – without any buildfile. With that I was able to do the pom2ivy conversion Torsten Curdt asked for:
task.bat -lib path-to-ivy.jar -xmlns:jar antlib:org.apache.ivy.ant ivy:convertpom pomFile my.pom ivyFile ivy.xml
Ant + JavaFront: start Ant tasks from the command line
7. November 2008Reading the blog Converting maven pom to ivy I asked myself, why it should not be possible to start Ant tasks from the command line.
Stefan on the other side was bored always to here that Ant relies on XML and he presented a way for writing Buildfiles in plain (annotated) Java using JavaFront, a library in Ants sandbox.
Ant provides a way to override the class to start by providing an implementation of AntStart and specifying that class by -main option. So I wrote a new start class which parses the command line parameters and executes that task. The first parameter is the taskname and following parameters are attributes with their values. (There is no support for nested elements yet.)
public class TaskExec implements AntMain {
public void startAnt(String[] args, Properties additionalUserProperties, ClassLoader coreLoader) {
Map
// Analyzing the command line arguments Other examples are in the launcher script.
String taskname = args[0];
for(int i=1; i
Ant: catching all marked lines in text files for creating a changes document
17. Oktober 2008MartianSoftware has released (a long time ago) two Ant task: <snip> and <rundoc>. While I am not sure about the benefits of <rundoc> (as I dont know docbook really well) <snip> seems to be a nice task. Extracting parts of a file with Ant on board utilities is not that easy.
Using the snip task extracting is a few-liner. Just think we have a class
/** * This is normal JavaDoc comment. * @@snip:changes@@ * This is a comment which should be in the changes.txt! * @@endSnip@@ * @author Jan Materne */ public class MyProgram { }
Ant I want to generate the document containing this line
This is a comment which should be in the changes.txt!
<project> <property name="build.dir" value="build"/> <target name="clean"> <delete dir="${build.dir}"/> </target> <target name="snip"> <!-- Getting snip task --> <mkdir dir="${build.dir}"/> <get src="http://www.martiansoftware.com/lab/snip/snip-0.11.jar" dest="${build.dir}/snip.jar"/> <taskdef name="snip" classname="com.martiansoftware.snip.Snip" classpath="${build.dir}/snip.jar"/> <!-- Collecting the information --> <snip> <fileset dir="src" includes="**/*.java" /> </snip> <!-- Use these informaion --> <echo file="${build.dir}/changes.txt"> Changes ----------------------------------------------------------------- ${snip.changes} </echo> <!-- For easier test: output the file --> <concat><fileset file="${build.dir}/changes.txt"/></concat> </target> </project>
I can see, that the information is gathered:
..>ant snip Buildfile: build.xml snip: [get] Getting: http://www.martiansoftware.com/lab/snip/snip-0.11.jar [get] To: ...\build\snip.jar [concat] [concat] Changes [concat] ----------------------------------------------------------------- [concat] [concat] * This is a comment which should be in the changes.txt! [concat] BUILD SUCCESSFUL
Fine, let’s try having more information with a second class:
/** * This is normal JavaDoc comment. * @@snip:changes@@ * This is another comment which should be in the changes.txt! * @@endSnip@@ * * @author Jan Materne * * @@snip:changes@@ * Maybe another line in the comments. * @@endSnip@@ */ public class Class2 { }
And I want to get:
...>ant snip Buildfile: build.xml snip: [get] Getting: http://www.martiansoftware.com/lab/snip/snip-0.11.jar [get] To: ...\build\snip.jar [concat] [concat] Changes [concat] ----------------------------------------------------------------- [concat] [concat] * This is a comment which should be in the changes.txt! [concat] * This is another comment which should be in the changes.txt! [concat] * Maybe another line in the comments. [concat] BUILD SUCCESSFUL
But the result doesnt change. Thats because <snip> sets properties directly when getting the @@endSnip@@ mark. And – as Ant properties are immutable – once set a property cant be extended.
It would be better to extend <snip> for first collecting all values and then storing the values into Ant properties.
I thought I could start collecting these lines with Ant built-in facilities could be done like
<target name="ant" depends="clean"> <mkdir dir="${build.dir}"/> <!-- Collecting and using the information --> <concat destfile="${build.dir}/changes.txt"> <header> Changes ----------------------------------------------------------------- </header> <fileset dir="src" includes="**/*.java" /> <filterchain> <!-- Something special here --> </filterchain> </concat> <!-- For easier test: output the file --> <concat><fileset file="${build.dir}/changes.txt"/></concat> </target>
But I couldnt get one file after the next in that filterchain. By default I get one line after the next and then I have troubles for storing the current state (in @@snip-@@endSnip section or out). When using a <tokenfilter><filetokenizer/> I’ll get not only one whole file – I’ll get one token containing ALL catched files including the specified headers. And I dont want to run THAT on a larger codebase …
Ok, it is difficult to gather all content BETWEEN two special markers. But it is very easy to catch all lines with a PREPENDING marker:
<target name="ant"> <mkdir dir="${build.dir}"/> <!-- Collecting and using the information --> <echo file="${build.dir}/changes.txt"> Changes ----------------------------------------------------------------- </echo> <concat destfile="${build.dir}/changes.txt" append="true"> <fileset dir="src" includes="**/*.java" /> <filterchain> <linecontainsregexp> <regexp pattern="^[ \*]*CHANGES:"/> </linecontainsregexp> <replaceregex pattern="^[ \*]*CHANGES: *" replace=""/> </filterchain> </concat> <!-- For easier test: output the file --> <concat><fileset file="${build.dir}/changes.txt"/></concat> </target>
/** * This is normal JavaDoc comment. * CHANGES: This is a comment which should be in the changes.txt! * @author Jan Materne */ public class MyProgram { }
Links for 2008-10-16
16. Oktober 2008According to this German article (relies on an article by ComputerWorld Australia)Australia plans to filter all internet traffic in AUS. There are two blacklists: one for illegal content (which should be blocked) and one for content for adults.
Trustin Lee has released Ant2IDE. Basically this is a BuildListener that collects (almost) all data required for generating Eclipse settings.
Ant: Deleting files from ZIP
14. Oktober 2008A common problem is deleting single files from a ZIP. An old workaround is „unzip+zip“. This snippet implements a macro. The <selectors/> statement in line 21 together with the <element> definition in line 14 is the placeholder for all selectors you pass in.
<project default="test"> <target name="prepare"> <mkdir dir="zip"/> <echo file="zip/one.txt" message="one"/> <echo file="zip/two.txt" message="two"/> <echo file="zip/three.txt" message="three"/> <zip destfile="zip.zip" basedir="zip"/> <delete dir="zip"/> </target> <macrodef name="delFromZip"> <attribute name="zip"/> <element name="selectors" implicit="true" optional="true"/> <sequential> <mkdir dir="__tmp__"/> <unzip dest="__tmp__" src="@{zip}"/> <delete file="@{zip}"/> <delete> <fileset dir="__tmp__"> <selectors/> </fileset> </delete> <zip destfile="@{zip}" basedir="__tmp__"/> <delete dir="__tmp__"/> </sequential> </macrodef> <target name="test"> <delFromZip zip="zip.zip"> <include name="two.*"/> </delFromZip> </target> </project>
GUI-Output from Apache ant
14. Oktober 2008This is the first of my Ant snippets. I think I will post more in the future. Most of these snippets are written during discussions on the dev@ant and user@ant mailing lists for showing possibilities or solutions to problems. Sometimes I only played with something …
With <echo> you can print log messages to Ant’s output. I tried to make a „popup“, so you will be informed if a „background“ Ant process has something important to say.
<project> <scriptdef name="alert" language="beanshell"> <attribute name="message"/> <attribute name="title"/> <![CDATA[ title = attributes.get("title"); message = attributes.get("message"); if (title==null) { title = "Ant Alert!"; } import javax.swing.*; JOptionPane.showMessageDialog( null, message, title, JOptionPane.ERROR_MESSAGE); ]]> </scriptdef> <alert message="A long and boring message"/> <alert message="A long and boring message" title="Danger Danger"/> </project>