Vincent Massol would love reusable Ant tasks: "For example, you may think that deleting a directory is simple. But it's not so easy. Have a look at the Delete Ant task source code. You'll find portion of code like this one: /** * Accommodate Windows bug encountered in both Sun and IBM JDKs. * Others possible. If the delete does not work, call System.gc(), * wait a little and try again. */ private boolean delete(File f) { if (!f.delete()) { if (Os.isFamily("windows")) { System.gc(); } try { Thread.sleep(DELETE_RETRY_SLEEP_MILLIS); } catch (InterruptedException ex) { // Ignore Exception } } return true; } Would you have thought about this? Probably not and you would have been right not to as this only happens in some rare occasions." I've thought of it, sure, because it's bitten me before. Repeatedly. (Here's the rant...) And it's not rare (or at least, not rare enough :). Try writing junit tests which add and remove enough directories or files between setups. Nightmare. Try doing industry standard .do/.done file weirdness and getting the support calls when the files are left lying around. Nightmare. And that system.gc() hack doesn't always work. I'm not even sure it's considered a JDK bug - Java by design is so abstracted from the actual filesystem it can't offer guaranteed side effects for file operations. So you need to treat these things as best effort. Given that gc is also best effort there's still have room to fail in the Ant code above (I think). I wrote a countdown once to repeatedly try a deletion and failing that, bail out with an email to ops. That's spinning the CPU more that a sleep() but you got more shots at deletion. These days I'd tend to the idiom which deals with files whose modification time is X milliseconds older than currentTimeMillis. Or if you must, fork a process (btw, how Ant forks processes is great; everyone should re-use that). Couldn't agree more about re-using Ant tasks however (exec being a great example): "The problem is that the Ant tasks are a bit too much linked to the execution engine (the XML scripting engine). For example reusing an Ant tasks requires you to create a Project object. This in turn drags loggers, the Ant classloader (in some cases) and possibly other objects. I know it's possible to use Ant from Java (I've been doing it for a long time now) but I'd love it be even easier to do so... I'd like to see Ant separate into 2 subprojects: one for the XML scripting engine (let's call it engine) and one for the Ant tasks (let's call it tasks). The reason for the 2 projects is to ensure there's no dependency in the direction tasks->engine." I think another reason the Tasks are tied to the Ant engine is because Ant doesn't have standard i/o (eg the way Unix pipes do). Task.execute() is void. I use a set/get/execute(in,out,err) idiom a lot for XML pipelining in Java, it was taught to me by Sean McGrath. The reason that works under those circumstances and any component in the pipeline is reusable/reorderable is because the XML in and XML out provides uniform i/o. A Uniform API might not be quite enough - you might have to ask what Ant's answer to | is. Without the i/o abstraction I don't know if you can achieve what Vincent wants in terms of depdendency management. But of course none of this stuff was the original intention of Ant. antsh: turning Java into shell scripting, task by task!...