Return-Path: Delivered-To: apmail-ant-user-archive@www.apache.org Received: (qmail 54743 invoked from network); 4 Oct 2004 14:18:34 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 4 Oct 2004 14:18:34 -0000 Received: (qmail 26120 invoked by uid 500); 4 Oct 2004 14:18:18 -0000 Delivered-To: apmail-ant-user-archive@ant.apache.org Received: (qmail 25981 invoked by uid 500); 4 Oct 2004 14:18:16 -0000 Mailing-List: contact user-help@ant.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Ant Users List" Reply-To: "Ant Users List" Delivered-To: mailing list user@ant.apache.org Received: (qmail 25962 invoked by uid 99); 4 Oct 2004 14:18:16 -0000 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests= X-Spam-Check-By: apache.org Received-SPF: pass (hermes.apache.org: local policy) Received: from [160.83.52.98] (HELO loninmrp6.uk.db.com) (160.83.52.98) by apache.org (qpsmtpd/0.28) with ESMTP; Mon, 04 Oct 2004 07:18:15 -0700 Received: from sdbo1003.db.com by loninmrp6.uk.db.com id i94EIB4Q002574; Mon, 4 Oct 2004 15:18:12 +0100 To: user@ant.apache.org Subject: Thinking in Ant... MIME-Version: 1.0 X-Mailer: Lotus Notes Release 5.0.11 July 24, 2002 Message-ID: From: "Richard Russell" Date: Mon, 4 Oct 2004 15:18:06 +0100 X-MIMETrack: Serialize by Router on sdbo1003/DMGUK/DeuBaInt/DeuBa(5013aHF19 | July 26, 2004) at 04/10/2004 03:18:12 PM, Serialize complete at 04/10/2004 03:18:12 PM Content-Type: text/plain; charset="us-ascii" X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Hi all, Firstly, please excuse the crufty formatting of this email -- my employer makes me use Notes. If people would prefer, I can paste this into a public Twiki somewhere... Just let me know the general preference. Secondly, I'm hoping that this email does not come across overly critical or negative -- I'm not having a go at ant, I honestly just want to get my head around these problems better. Finally, thanks for your patience if you manage to read the whole email. I wanted to keep it short, but decided that the length was necessary to illustrate the problem that I've been having. Those interested, but pressed for time could just read the first part, up to the example... 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 include: 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: 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} done ---- 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 example. 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; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.FileList; import org.apache.tools.ant.taskdefs.Concat; import java.io.File; 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 File(destDir+System.getProperty("file.separator")+srcFile.getName()); 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 super.toString()+"\ntoDir="+destDir+"\nfromFile="+srcFile+"\n"; } 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 disallowed"); } public void setAppend(boolean append) throws BuildException { throw new BuildException("AppendCopy: Append attribute disallowed"); } 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: ---- ... ---- 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: ---- ---- 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 (http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/Copy.java?rev=1.66.2.6&view=markup), 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 screwdriver? Cheers, 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: user-unsubscribe@ant.apache.org For additional commands, e-mail: user-help@ant.apache.org