Ant: How to compare timestamps? - ant

In a long running Ant script, I have a target that gets called roughly once per second. (This is probably not a good thing, but let's accept it for the moment.)
I only want it to execute if its last actual execution was at least five minutes ago.
One idea for a solution is to maintain a lastRunTimestamp property, and compare the current time to that.
Problem: How can I compare timestamps in Ant?
Another solution that would also be welcome is a means of executing the target only at specified time intervals, so that the check would not be necessary.
I am using Ant 1.7.1 and ant-contrib.
Any ideas are greatly appreciated - thanks!

Interesting question, and one which is a bit harder to answer than I originally thought.
You can use the <tstamp> task to set a time stamp that's five minutes old:
<tstamp>
<format property="time_stamp"
offset="-5"
unit="minutes"
pattern="MM/dd/yyyy hh:mm:ss aa"/>
</tstamp>
Once you have that timestamp, you can use the lastmodified condition of the <condition> task to see if a particular file has been updated since. If you don't have a file, you can use the <touch> task to create one.
<condition property="has.been.modified">
<islastmodified dateTime="${time_stamp}" mode="after">
<file file="${touch.file}"/>
</islastmodified>
</condition>
The only issue is that default properties are immutable. Once set, you can't change them. Fortunately you're using ant-contrib and ant-contrib allows you to change that via the variable task.

Related

Replace a file in zip using Ant despite of timestamp

I want to replace 1-2 files in a huge archive using zip task (or any other ANT task that can do this). I know passing update=true parameter can do it but it is only if new file has grater timestamp than old file. I want to make sure that the file gets replaced even though it has old timestamp as compared to the file in existing archive.
I have gone through several posts where they suggest unzip-replace-rezip thing. However I want to avoid this if possible because my archive is huge (in GBs). Is there any other way which has minimum performance impact?
Other way I found was using zipfileset task as follows:
<zip destfile="tmp.jar">
<zipfileset src="src.jar">
<exclude name="abc.class" />
</zipfileset>
<zipfileset dir="${basedir}/myclasses" includes="abc.class" />
</zip>
<move file="tmp.jar" tofile="src.jar" />
Does this task do the same as unzip-delete-add-rezip for entire archive? Or is it more efficient in terms of time?

Ant - Verify if two binaries (jar) are strictly equals

I am using Ant 1.9.4.
I have two jar files and I would like to know if they are strictly equals.
Of course not only the name but every file in it.
My guess would be to have like a MD5 checker on something like that but I don't know if it is possible via ant.
Thank you for your help,
Regards
Ant core provides a checksum task :
Generates checksum for files. This task can also be used to perform checksum verifications.
May be used with conditon to make your build fail if binaries are not equal, f.e. :
<checksum file="path/to/foo.jar" property="fooMD5"/>
<fail message="Binaries not equal !!">
<condition>
<not>
<checksum file="path/to/fooo.jar" property="${fooMD5}"/>
</not>
</condition>
</fail>
There are also filesmatch and resourcesmatch conditions for file compare, see ant manual conditions.

Need Ant condition example

Can someone please explain me with Example of Ant condition property with "if", "and", "not" and "istrue" with the code??
I'm new to Ant and need help on this.
Basically i need to download file using FTP. I have code to download it. but there are few condition i need to check before downloading.
Before downloading check the Downloadstatusvariable value (usually its true or false value")
check whether file is already downloaded or available in the path
if both the conditions fails then exec the FTP download code.
Thanks in advance.
ant-contrib is widely-used library and the if/else/for/foreach tasks will not only make it easier to write complex ant scripts, they'll make your ant scripts much more readable.
But, since you insist :)
The way I've handled this in the past is to set up a task A that only executes if property X is set, and make task A depend on some task B that checks the conditions and sets property X if they are true. For example:
<target name="get-ftp-file" depends="check-need-ftp-file" if="ftp.call.required">
<ftp ... />
</target>
<target name="check-need-ftp-file">
<condition property="ftp.call.required">
<and>
<not>
<!-- Checks if Downloadstatusvariable variable is true -->
<istrue value="${Downloadstatusvariable}"/>
</not>
<not>
<!-- Checks if file is present in filesystem -->
<available file="${my.file}"/>
</not>
</and>
</condition>
</target>
EDIT:
coolgokul, the <and> and <not> tasks are standard logical operators. The <available> condition in the example above evaluates to true if the file exists on the local machine. But we want to download the file only if the file does NOT exist on the local machine, so we wrap it up in the <not> task. Similar for the ${Downloadstatusvariable} check--we want to make sure it is not true, so we use <istrue> and then wrap it up in <not>.
Finally, we want to make sure that that the variable is not true AND the file does not exist, so we wrap up both those conditions in <and>. Translated to English, we're asking "Is Downloadstatusvariable not true, and is the downloaded file not available?"
Recommend you read more about conditional operators # http://ant.apache.org/manual/Tasks/conditions.html
Hope that helps.
The standard Ant does not have an "if" task, but you can do pretty much any conditional logic you need to by using the "condition' task. See http://ant.apache.org/manual/Tasks/condition.html for some examples.
There is a set of additional tasks including an "if" task in the ant-contrib library, but I'd advise against using this unless you really need to, due to the complexity it will add to your build environment.
Are you trying out using Ant Contrib Task?. If you click on the links over there, the document explains with example what you might want to achieve through each of the tasks
Some relevant examples might be here: Steve J's Blog

Valid <property> names in Ant

I'd like to set some properties in my ant build file, the names of which, are based on ant's build in properties. In particular, I'd like to set a property like:
<property name="${ant.project.name}.compiled" value="true" />
However, when I tried this the ${ant.project.home} portion was not expanded.
Is it possible to use the value of properties as the names of other properties, and if so, how?
<property name="name.holder" value="iamholder" />
<property name="${name.holder}.flag" value="true" />
<echoproperties></echoproperties>
result:
[echoproperties] iamholder.flag=true
this is definitely valid ant code and the property iamholder.flag gets the value of true.
If ${name.holder} does not get expanded, it means it has not been set yet (like if the first line in my sample was missing).
Anyways, this still does not quite solve your problem, as you have pretty much no means of getting the value of this property as you don't know it's name and you can't do a nested resolve in pure ant. Depending on what you are trying to do it could still be useful to you though. This one would work (keep in mind, that until 1.8 the value is irrelevant as long as the property is set):
<target name="compile_stuff" unless="${name.holder}.flag">
<echo>compiling...</echo>
</target>
To really get the value of such a property you have to use ant-contrib's propertycopy as suggested in one of the answers. That way you can get the value in a property whose name you know. Just make sure to do the trick just before use and set the override parameter to true (your post implies that you would be setting more properties like these, but without override your final property could not be changed). Another option for working with such properties is to use ant macros.
I think the only way is to echo your values to a .properties file and then load them back.
However, you should ask yourself if you really need it; when I last used ant I tried to do the same thing but concluded I didn't really need to.
Is
$ant.project.home.compiled
not just as useful?
It can be done, a bit ugly, though. You need the < propertycopy > task from ant-contrib for this. The following shows an example
<property name="projectNameCompiled" value="${ant.project.name}.compiled" />
<property name="${projectNameCompiled}" value="true" />
<propertycopy property="final" from="${ant.project.name}.compiled" />
The property final contains the value true.
There are several ways to achieve that, see Ant FAQ
One possible solution via macrodef simulates the antcontrib / propertycopy task but doesn't need any external library.

Reasons for using Ant Properties files over "Properties Tasks"

I'm currently working with some developers who like to set up Ant tasks that define environment specific variables rather than using properties files. It seems they prefer to do this because it's easier to type:
ant <environment task> dist
Than it is to type:
ant -propertyfile <environment property file> dist
So for example:
<project name="whatever" default="dist">
<target name="local">
<property name="webXml" value="WebContent/WEB-INF/web-local.xml"/>
</target>
<target name="remote">
<property name="webXml" value="WebContent/WEB-INF/web-remote.xml"/>
</target>
<target name="build">
<!-- build tasks here --->
</target>
<target name="dist" depends="build">
<war destfile="/dist/foo.war" webxml="${webXml}">
<!-- rest of war tasks here -->
</war>
</target>
I am finding it hard to convince them that properties files are they right way to go. I believe properties files are better because:
They provides more flexibility - if you need a new environment just add a new properties file
It's clearer what's going on - You have to know about this little "trick" to realize what they're accomplishing
Doesn't provide default values and the ability to use overrides - if they used property files they could provide defaults at the top of the project but have the ability to override them with a file
Script won't break if an environment task isn't supplied on command line
Of course all they hear is that they need to change their Ant script and have to type more on the command line.
Can you provide any additional arguments in favor of properties files over "property tasks"?
Properties tasks tightly couple the build file to environments. If your fellow developers are arguing that they "have to change their ant script" with your suggestions, why aren't they arguing about changing it every time they have to deploy to a new environment? :)
Perhaps you can convince them to allow both properties file and command-line configuration. I set up my Ant builds so that if a build.properties exists in the same directory as the build.xml, it reads it in. Otherwise it uses a set of default properties hard-coded into the build. This is very flexible.
<project name="example">
<property file="build.properties"/>
<property name="foo.property" value="foo"/>
<property name="bar.property" value="bar"/>
...
</project>
I don't provide a build.properties with the project (i.e. build.properties is not versioned in SCM). This way developers aren't forced to use the property file. I do provide a build.properties.example file that developers can reference.
Since Ant properties, once set, are immutable, the build file will use properties defined in this order:
Properties provided with -D or -propertyfile via the command line
Properties loaded from build.properties
Default properties within build.xml
Advantages of this approach:
The build file is smaller and therefore more maintainable, less bug-prone
Developers that just can't get away from setting properties at the command line can still use them.
Properties files can be used, but aren't required
The arguments you have are already pretty compelling. If those arguments haven't worked, then arguing isn't going to solve the problem. In fact, nothing is going to solve the problem. Don't assume that people are rational and will do the most practical thing. Their egos are involved.
Stop arguing. Even if you win, the resentment and irritation you create will not be worth it. Winning an argument can be worse than losing.
Make your case, then let it go. It's possible that after a while they will decide to switch to your way (because it actually is better). If that happens, they will act like it was their own idea. There will be no mention of your having proposed it.
On the other hand, they may never switch.
The only solution is to work towards a position of authority, where you can say how things are to be done.
The problem with the first solution (using ant property) is basically hardcoding.
It can be convenient when you start a project for yourself but quickly you have to remove that bad habit.
I'm using a property file close to what said robhruska except that I have committed the build.properties file directly. This way you have a default one.
In other hand, I understand I could add those default values in the build.xml. (I will probably try that in the next hours/days ;-) ).
Anyway, I really don't like the first approach and I would force those guys to follow the second one ...

Resources