ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Wascally Wabbit <>
Subject Re: Thinking in Ant...
Date Mon, 04 Oct 2004 14:55:59 GMT
At 10:18 AM 10/4/2004, you wrote:

Philosophical discussions of the "Why and Why-Nots of Ant" aside, there
are a few Ant extensions that make it easier (than your listed
solutions) to do mostly what you want. This group likes Ant-contrib,
but I've found lots of other (well supported) extensions that help
(which I think is good -- I'd rather not like Ant to grow into some
giant kitchen-sink product; there's lots for the Ant developers to
refactor and streamline with the code base they've got.)

I work with AntXtras. With 0.5b2, your listed problem would be solved
mostly with:

    <listdir torefid="thelist" path="${dir1}" onlyfiles="yes"/>
    <foreach i="file" items="thelist" mode="local">
         <copy todir="${dir2}" file="${file}" filtering="yes">
            <filterset .../>

Not so bad. Not as compact as a three line shell loop, but not bad. You
might also try using a open source tool like Jelly with Ant and its
(newish) macro and preset support.

>Hi all,
>OK, now to the actual content:
>I'm having ongoing problems getting along with Ant. I keep wanting to do
>things that it appears that Ant can't do, despite trying to use what I
>would consider fairly basic constructs. I run into these issues so
>regularly that I cannot help but assume that I am simply not 'thinking in
>Ant', and am therefore fighting against its design rather than working
>with it. I occasionally come across snippets of documentation that seem to
>confirm this. Specific examples of things I keep butting my head against
>properties being "immutable" (except in some cases -- see propertycopy)
>not being able to double-dereference properties (eg ${${propertyname}}),
>or use arrays (not comma-separated lists -- indexable arrays)
>lack of 'if', 'for' and similar logic constructs (yes, I am aware of
>ant-contrib, but much documentation seems to indicate that this is a
>concession rather than an ideal)
>inflexibility of certain tasks/containers etc -- eg below, I want to set
>up a bunch of filters, and would like to use a construct like this within
>a loop:
>                 <filterchain id="${filtername}">
>                         <replacetokens>
>                                 <for param="propertyname"
>                                         <propertycopy name="propertyvalue"
>                                         <token key="@{propertyname}"
>                                 </for>
>                         </replacetokens>
>                 </filterchain>
>As you can see, this illustrates a couple of my problems -- I'm using
>propertycopy to get around the lack of double-dereferencing, and also
>taking advantage of the way propertycopy can mutate values of "immutable"
>properties. Then, I'm using a for loop (which requires mutable properties)
>to set up multiple tokens in the replacetokens filter (actually, I can't
>do this, as replacetokens doesn't support the nested 'for' element).
>Another example of this is the (to my mind) strange duplication between
>filterchains and filtersets. They seem to do basically the same thing, but
>in different places and with different limitations.
>My frustration here is because Ant isn't procedural. Or perhaps it's
>because I think of my build process in a procedural manner (hence why I
>call it a build *process* and not a build *declaration*). Perhaps this is
>because I've always used make, but I'm not sure how else to think about
>it, at least at the low level. Eventually, I have battled through, and
>have created new tasks, macros, or used other people's libraries to make
>it all happen, but no matter what, it all takes so long, and I don't see
>life getting much better as I grow in familiarity with it.
>Here's a longer example of something that I would normally consider
>simple. I want to append each of the files in one directory to the
>same-named file in another directory, filtering some tokens as I go. It's
>possibly expressed simplest as a shell script:
>for file in `ls ${dir1}/*.DAT`; do
>   cat ${dir1}/${file} | sed -e 's/@parameter@/value/' >> ${dir2}/${file}
>As an aside, I wrote that particular line in about two minutes, including
>fixing the one error I made in the sed script (I missed the trailing /).
>Obviously, there would be more sed parts for the different tokens, and
>it's not exactly an elegant solution. But the point is that it took me two
>minutes, didn't require me consulting any API documentation, and doesn't
>require compilation. I'm sure there's more elegant, perhaps easier ways of
>doing it, in Perl, or even still in shell, but this is just a trivial
>Now, to do the same in Ant, I first tried to combine the for and concat
>tasks, with a filter, in the obvious (to me) manner. For various reasons
>this wouldn't work -- mostly to do with immutable properties, and not
>being able to separate the filename from the directoryname in a fileset
>and so on. If anyone knows of a way to replicate this functionality
>without writing a new Task, let me know.  As it was, I had to create the
>following Task:
>package mypackage;
>public class AppendCopy extends Concat
>         private String destDir=null;
>         private File srcFile=null;
>         public void execute() throws BuildException
>         {
>                 if (destDir==null)
>                         throw new BuildException("AppendCopy: destdir
>attribute not set");
>                 if (srcFile==null)
>                         throw new BuildException("AppendCopy: srcfile
>attribute not set");
>                 try
>                 {
>                         File destinationFile=new
>                         super.setDestfile(destinationFile);
>                         FileSet sourceFileSet=new FileSet();
>                         sourceFileSet.setFile(srcFile);
>                         super.addFileset(sourceFileSet);
>                         super.setAppend(true);
>                         super.execute();
>                 }
>                 catch (Exception exception)
>                 {
>                         throw new BuildException("AppendCopy: something
>went wrong\n" + exception);
>                 }
>         }
>         public String toString() {
>                 return
>         }
>         public void setDestdir(String string)
>         {
>                 destDir=string;
>         }
>         public void setSrcfile(File file)
>         {
>                 srcFile=file;
>         }
>         public void setDestfile(File destinationFile) throws
>BuildException {
>                 throw new BuildException("AppendCopy: destFile attribute
>         }
>         public void setAppend(boolean append) throws BuildException {
>                 throw new BuildException("AppendCopy: Append attribute
>         }
>         public void addFileset(FileSet set) throws BuildException {
>                 throw new BuildException("AppendCopy: Nested FileSet
>element disallowed");
>         }
>         public void addFilelist(FileList list) throws BuildException {
>                 throw new BuildException("AppendCopy: Nested FileList
>element disallowed");
>         }
>And then, I use it in my build.xml like this:
><taskdef name="appendcopy" classname="mypackage.AppendCopy"/>
><for param="filename">
>         <fileset dir="${dir1}/" includes="*.DAT"/>
>         <sequential>
>                 <appendcopy srcfile="@{filename}" destdir="${dir2}"
>                         <filterchain refid="myfilter"/>
>                 </appendcopy>
>         </sequential>
>Plus, of course, the setting up of the filterchain "myfilter".
>Now, when I look at the result, it's far from elegant, and without knowing
>what appendcopy really did, I would be hard pressed to understand what the
>ant snippet did. I could remove the for loop, and create a task that did
>the whole operation, and was called like this:
><appendcopydirectory todir="${dir2}">
>         <fileset dir="${dir1}/" includes="*.DAT"/>
>         <filterchain refid="myfilter"/>
>But I suspect that would be even more work. It's also (to my mind) less
>clear and less re-usable (though I could name it
>appendcopyeachfileinfilesettosamenamedfileintodir, but that's got its own
>problems). I could subclass copy, adding an "append" attribute, but,
>having read the source to Copy

>I decided that discretion was the better part of valour, and there had to
>be an easier way. Note that while I can code Java, I'm not a developer,
>and have no desire to become one. Certainly, I challenge even a top
>developer to come up with some sort of append attribute for Copy in the
>time it took me to write the equivalent shell script above.
>So, what is it that I'm doing wrong here? Why am I always battling against
>Ant, and finding that the things I wish to do, things which I find simple
>to express in english, in psuedocode, or in shell, are so darned complex
>to do in Ant? Am I just not getting it? Am I driving in nails with a
>Richard Russell
>Deutsche Bank AG London
>Global Markets Customer Solutions
>Office: +44 (0)20 7545 8060
>Mobile: +44 (0)79 0661 2237
>To unsubscribe, e-mail:
>For additional commands, e-mail:

The Wabbit 

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message