Checksum task in Ant not working as expected - ant

I am struggling with a small ant file/target that is as follows:
<project name="test" default="test" basedir=".">
<property name="out.dir" value="${basedir}/out/"/>
<property name="apidoc.path" value="${out.dir}test.zip"/>
<property name="apidoc.input" value="${basedir}/../source//apidocs"/>
<property name="apidoc.sha" value="TODO"/>
<target name="test">
<echo message="Starting target APIDOC"/>
<zip destfile="${apidoc.path}" basedir="${apidoc.input}" update="no"/>
<echo message="${apidoc.path}"/>
<checksum file="${apidoc.path}" algorithm="SHA-256" property="apidoc.sha"/>
<echo message="Hash wert ist ${apidoc.sha}"/>
</target>
</project>
The target should create a zip file from a doc folder (it does) and then store the hash value of the zip file into a property for further use. However, the hash value is not stored in the property. I get the output as follow:
test:
[echo] Starting target APIDOC
[echo] /Users/user1/git/project/out/test.zip
[echo] Hash wert ist TODO
BUILD SUCCESSFUL
Does anybody have and idea, what is going wrong here?

Properties in Ant are immutable. This line
<property name="apidoc.sha" value="TODO"/>
sets the value, and after that it can't be changed.
If you run ant with the -v command-line option you should see a message like
Override ignored for property "apidoc.sha"
indicating that the attempt to alter the property value in the <checksum> task is being ignored.

Related

Force Ant to substitue a substitution variable

I use a software (Drops) based on ant script.
I try to dynamically generate the destination path of a file that I want to copy. To do this I execute a linux command line.
In my application, I have this properties :
environment.props.environment_name=recette
application.props.target.gmao=/opt/${environment.props.environment_name}/gmao-ws
I expected Ant to replace ${environment.props.environment_name} by its value at runtime. But it doesn't.
Here is the Ant script that I wrote :
<project xmlns:drops="antlib:com.arcadsoftware.mmk.anttasks" name="deployJar" basedir="." default="main">
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<taskdef resource="com/dropssoftware/drops/ant/antlib.xml"/>
<loadDropsContext/>
<target name="main">
<!-- get the value of the property "application.props.target.gmao" -->
<propertycopy name="target.dir" from="application.props.target.gmao"/>
<!-- I expect this to print target.dir=/opt/recette/gmao-ws but it print target.dir=/opt/${environment.props.environment_name}/gmao-ws -->
<echoproperties />
<!-- Supposed to copy from /opt/drops/storage/afile.jar to /opt/recette/gmao-ws but the property "target.dir" is wrong -->
<exec executable="sudo">
<arg value="/bin/cp"/>
<arg value="${param.artifacts.root}/${param.jar.root}"/>
<arg value="${target.dir}"/>
</exec>
</target>
</project>
With this input :
param.env=gmao
param.artifacts.root=/opt/drops/storage/
It is supposed to copy a file from the artifacts directory to the /opt/recette/gmao-ws directory. But Ant tried to copy it to /opt/${environment.props.environment_name}/gmao-ws.
I don't understand why Ant doesn't replace ${environment.props.environment_name} by its value.
Is it possible to force Ant to replace the substitution variable by its value ?
Not entirely clear what you're trying to do. The propertycopy task is not part of normal Ant, coming from a 3rd party extension called ant-contrib
I suspect what you're trying to do can be done with normal property substitution. I have provided an example.
Example
A simple example of how to pass in parameters to a build file by setting properties:
$ ant -Dparam.from=AAA -Dparam.to=BBB
build:
[echo]
[echo] sudo
[echo] /bin/cp
[echo] /opt/drops/storage/AAA
[echo] /opt/drops/storage/BBB
[echo]
build.xml
Note the 3 properties declared at the top? These are effectively the default values available for override.
<project name="demo" default="build">
<property name="param.artifacts.root" value="/opt/drops/storage"/>
<property name="param.from" value="fromDir"/>
<property name="param.to" value="toDir"/>
<target name="build">
<echo>
sudo
/bin/cp
${param.artifacts.root}/${param.from}
${param.artifacts.root}/${param.to}
</echo>
</target>
</project>
I think that I find the answer to my question in ant document :
https://ant.apache.org/manual/properties.html
Normally property values can not be changed, once a property is set, most tasks will not allow its value to be modified.
In the case of the software that I use : Drops, it loaded the application properties BEFORE the environment properties.
So application.props.target.gmao is set BEFORE environment.props.environment_name and the ${environment.props.environment_name} cannot be replace.
The answer to my question is seems to be NO, it's not possible to force Ant to replace the substitution variable by its value.
It's done automatically if the variables are loaded in the good order.

If there is no properties file declared, what does the $ do in an Ant build file?

Essentially, I am wondering how ant knows that $ means to pull from the properties file.. what if there was no properties file named?
Take example this build file
<?xml version="1.0" encoding="UTF-8"?>
<project name="Hello World Project" default="info">
<property file="build.properties"/>
<fileset dir="${build.dir}" >
<include name="**/*.java"/>
</fileset>
<target name="info">
<echo>${src}</echo>
</target>
</project>
I know that the $ sign is referencing a property in the build.properties file, however what if there is no properties file, what does the $ sign do in a regular Ant compilation?
Ant leaves references to non-existent properties unchanged. For example, the following Ant script...
<project name="ant-echo-missing-property" default="run">
<target name="run">
<property file="non-existent-file.properties"/>
<echo>${missing-property}</echo>
</target>
</project>
...outputs...
run:
[echo] ${missing-property}

How to specify oracle odbjc.jar in Liquibase ant configuration

I have following ant configuration:
<project name="pcebuild" basedir="." default="updateDatabase" xmlns:liquibase="antlib:liquibase.integration.ant" >
<taskdef resource="liquibase/integration/ant/antlib.xml" uri="antlib:liquibase.integration.ant">
<classpath path="c:\Users\artur.skrzydlo\Documents\liquibase-3.3.2-bin\liquibase.jar"/>
</taskdef>
<property name="liquiChangeLogFile" value="${basedir}/liquibase/db.changelog-master.xml"/>
<property name="db.driver" value="oracle.jdbc.OracleDriver"/>
<property name="db.url" value="jdbc:oracle:thin:#websph:1521:XE"/>
<target name="updateDatabase" description="Updates database with new changes using Liquibase">
<liquibase:updateDatabase changeLogFile="${liquiChangeLogFile}" >
<liquibase:database driver="${db.driver}" url="${db.url}" user="${db.user}" password="${db.pasword}"/>
</liquibase:updateDatabase>
</target>
</project>
After running this task I get an error :
Class not found: oracle.jdbc.OracleDriver
According to documentation :
driver The fully qualified class name of the JDBC driver.
I suppose that this error may rise because there is no place where I place classpath to my ojdbc.jar file. I am able to run this update command from command line, however there I can specify "classpath" argument which point to my ojdbc.jar file. And I don's see any place in this ant task definition where could i place it such a path. How can I do this ? What am I doing wrong ?
In your <liquibase:updateDatabase> tag you can have a classpathref attribute. So I have something like this:
<path id="driver.classpath">
<filelist files="${classpath}" />
</path>
...
<liquibase:updateDatabase
databaseref="main-schema"
changelogfile="${changeLogFile}"
classpathref="driver.classpath"
logLevel="debug"
>
...
And ${classpath} is an Ant property, set in a properties file:
classpath: /Users/me/place/lib/classes12.jar

ANT targets that depends on environment variables

My code:
<property environment="env"/>
<target name="detectTomcatFromEnv" unless="${env.CATALINA_HOME}">
<echo message="${env.CATALINA_HOME}"/>
</target>
I defined CATALINA_HOME and as I understand, target should not run.
But my result is:
detectTomcatFromEnv:
[echo] c:\apache-tomcat-7.0.21\
BUILD SUCCESSFUL
How it can be???
You need to remove the ${...} from unless:
<property environment="env"/>
<target name="detectTomcatFromEnv" unless="env.CATALINA_HOME">
<echo message="${env.CATALINA_HOME}"/>
</target>
See https://ant.apache.org/manual/targets.html:
unless: the name of the property that must not be set in order for
this target to execute, or something evaluating to false.

How to pass multiple parameters to a target in Ant?

I have this dummy target:
<mkdir dir="${project.stage}/release
<war destfile="${project.stage}/release/sigma.war">
...
...
</war>
What I want to do is provide two parameters say "abc" & "xyz" which will replace the word release with the values of abc and xyz parameters respectively.
For the first parameter say abc="test", the code above will create a test directory and put the war inside it.Similarly for xyz="production" it will create a folder production and put the war file inside it.
I tried this by using
<antcall target="create.war">
<param name="test" value="${test.param.name}"/>
<param name="production" value="${prod.param.name}"/>
</antcall>
in the target which depends on the dummy target provided above.
Is this the right way to do this.I guess there must be some way to pass multiple parameters and then loop through the parameters one at a time.
unfortunately ant doesn't support iteration like for or foreach loops unless you are refering to files. There is however the ant contrib tasks which solve most if not all of your iteration problems.
You will have to install the .jar first by following the instructions here : http://ant-contrib.sourceforge.net/#install
This should take about 10 seconds. After you can simply use the foreach task to iterate through you custom list. As an example you can follow the below build.xml file :
<project name="test" default="build">
<!--Needed for antcontrib-->
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<target name="build">
<property name="test" value="value_1"/>
<property name="production" value="value_2"/>
<!--Iterate through every token and call target with parameter dir-->
<foreach list="${test},${production}" param="dir" target="create.war"/>
</target>
<target name="create.war">
<echo message="My path is : ${dir}"/>
</target>
</project>
Output :
build:
create.war:
[echo] My path is : value_1
create.war:
[echo] My path is : value_2
BUILD SUCCESSFUL
Total time: 0 seconds
I hope it helps :)
Second solution without using ant contrib. You could encapsulate all your logic into a macrodef and simply call it twice. In any case you would need to write the two parameters at some point in your build file. I don't think there is any way to iterate through properties without using external .jars or BSF languages.
<project name="test" default="build">
<!--Needed for antcontrib-->
<macrodef name="build.war">
<attribute name="dir"/>
<attribute name="target"/>
<sequential>
<antcall target="#{target}">
<param name="path" value="#{dir}"/>
</antcall>
</sequential>
</macrodef>
<target name="build">
<property name="test" value="value_1"/>
<property name="production" value="value_2"/>
<build.war dir="${test}" target="create.war"/>
<build.war dir="${production}" target="create.war"/>
</target>
<target name="create.war">
<echo message="My path is : ${path}"/>
</target>
</project>
I admit that I don't understand the question in detail. Is ${project.stage} the same as the xyz and abc parameters? And why are there two parameters xyz and abc mentioned, when only the word "release" should be replaced?
What I know is, that macrodef (docu) is something very versatile and that it might be of good use here:
<project name="Foo" default="create.wars">
<macrodef name="createwar">
<attribute name="stage" />
<sequential>
<echo message="mkdir dir=#{stage}/release " />
<echo message="war destfile=#{stage}/release/sigma.war" />
</sequential>
</macrodef>
<target name="create.wars">
<createwar stage="test" />
<createwar stage="production" />
</target>
</project>
The output will be:
create.wars:
[echo] mkdir dir=test/release
[echo] war destfile=test/release/sigma.war
[echo] mkdir dir=production/release
[echo] war destfile=production/release/sigma.war
Perhaps we can start from here and adapt this example as required.

Resources