Ant nested condition - build

I have an ant build.xml file which contains the following snippet:
<condition property="apiUrl" value="apiUrl1">
<and>
<equals arg1="${area}" arg2="area1"/>
<equals arg1="${env}" arg2="stage"/>
</and>
</condition>
<condition property="apiUrl" value="apiUrl2">
<and>
<equals arg1="${area}" arg2="area1"/>
<equals arg1="${env}" arg2="develop"/>
</and>
</condition>
As you can see from above, <equals arg1="${area}" arg2="area1"/> is checked twice, and the logic of the snippet is equivalent to the pseudo code:
if (${area} == 'area1' and ${env} == 'stage') {
apiUrl = 'apiUrl1'
}
if (${area} == 'area1' and ${env} == 'develop') {
apiUrl = 'apiUrl2'
}
How can I change build.xml so that its logic becomes the following nested condition?
if (${area} == 'area1') {
if (${env} == 'stage') {
apiUrl = 'apiUrl1'
}
if (${env} == 'develop') {
apiUrl = 'apiUrl2'
}
}
My ant version is 1.10.3.

The reason this seemingly minor change can seem so awkward in Ant is because while the conditional setting of properties is simply controlled with the condition task, the conditional flow of logic is controlled at the target level. Thus, if you want certain steps to run or be skipped depending on a condition, you'll have to create a separate target that first checks the condition and then tells your main target whether or not it should run.
<target name="setApiUrl" depends="checkArea" if="isArea1">
<condition property="apiUrl" value="apiUrl1">
<equals arg1="${env}" arg2="stage"/>
</condition>
<condition property="apiUrl" value="apiUrl2">
<equals arg1="${env}" arg2="develop"/>
</condition>
</target>
<target name="checkArea">
<condition property="isArea1">
<equals arg1="${area}" arg2="area1"/>
</condition>
</target>

you can achieve that using script instead of condition task like this:
<project default="init" name="My Project">
<property name="area" value="area1" />
<property name="env" value="develop" />
<target name="init">
<script language="javascript">
if (project.getProperty('area') == 'area1') {
if (project.getProperty('env') == 'stage') {
project.setProperty('apiUrl', 'apiUrl1');
}
if (project.getProperty('env') == 'develop') {
project.setProperty('apiUrl', 'apiUrl2');
}
}
</script>
<echo>${apiUrl}</echo>
</target>
</project>

Related

ANT compilation error on updating selenium test result on TestLink

I am trying to run the TestNG tests using ANT. ANT executes it fine and creates an xslt report. When I add code in TestNg test to update Testlink ANT compilation fails with an error:
error: cannot find symbol import org.apache.xmlrpc.XmlRpcConfig;
^
symbol: class XmlRpcConfig
location: package org.apache.xmlrpc
1 error
BUILD Failed.
If I run TestNg.xml directly it updates everything in Testlink. Already imported xmlrpc.jar,xml-apis-1.4.01.jar,xmlrpc-client-3.1.3.jar in my project LIB folder.
Snippet from Build.xml --
<property environment = "env"/>
<property name="project.dir" value="${basedir}"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="jar.dir" value="${basedir}/Lib"/>
<property name="src.dir" value="${basedir}/src"/>
<property name="ng.result" value="test-output"/>
<tstamp>
<format property="TODAY_AU" pattern="d-MMMM-yyyy" locale="en,GB"/>
</tstamp>
<target name="setClassPath">
<path id="classpath_jars">
<pathelement path="${basedir}/" />
<fileset dir="${jar.dir}">
<include name="*.jar"/>
</fileset>
</path>
<pathconvert pathsep=":" property="test.classpath" refid="classpath_jars" />
</target>
<target name="TestNg" depends="setClassPath" >
<taskdef resource="testngtasks" classpath="${test.classpath}"/>
</target>
Kindly help.

ant-contrib for loop and regex in ant scripting

I have a requirement using ant, that the target should extract the two parameters passed as comma separated in a long list of similar pair of parameters passed which are semicolon separated. Currently I am doing something like this:
<?xml version="1.0"?>
<project name="" basedir="." default="test" xmlns:ac="antlib:net.sf.antcontrib">
<target name="test" >
<echo message="Hey There I am using What's App" />
<ac:for list="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu" delimiter=";" param="val">
<ac:sequential>
<ac:propertyregex property="param1"
input="#{val}"
regexp="([^\.]*)\,.*"
select="\1"
casesensitive="true" />
<ac:propertyregex property="param2"
input="#{val}"
regexp=".*,([^\.]*)"
select="\1"
casesensitive="true" />
<echo message = "val = ${param1}"/>
<echo message = "value = ${param2}"/>
</ac:sequential>
</ac:for>
</target>
</project>
But I am getting the output as:
Buildfile: /tmp/Manish/build.xml
test:
[echo] Hey There I am using What's App
[echo] val = asdfg
[echo] value = dasfdf
[echo] val = asdfg
[echo] value = dasfdf
[echo] val = asdfg
[echo] value = dasfdf
So this is getting looped 3 times(correct) but by only the first value passed in the for loop parameter. Is there some obvious mistake I am making?
Thanks,
Manish Joshi
Try using foreach instead of for and put the propertyregex into a separate target. Here is an example from my ant script, it basically does the same thing.
<target name="loadTestStatic" depends="setTargetEnv,setPassword">
<loadfile property="controlFile" srcFile="${projectDir}/test/config/static/controlFile.txt"/>
<foreach list="${controlFile}" delimiter="${line.separator}" param="descriptor" target="loadConfig"/>
</target>
<target name="loadConfig">
<if>
<matches string="${descriptor}" pattern="^camTool:"/>
<then>
<propertyregex property="camToolFile"
input="${descriptor}"
regexp="camTool:(.*)"
select="\1"
casesensitive="false" />
<echo message="Got cam tool file ${camToolFile}"/>
<camTool file="${camToolFile}"/>
</then>
<else>
<!-- todo: add CM Tool, SQL as required -->
<echo message="Unexpected config ${descriptor} ignored"/>
</else>
</if>
</target>
An alternative approach is to use a scripting language like groovy.
<groovy>
<arg value="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu"/>
args[0].tokenize(";").each {
def m = it.tokenize(",")
println "val = ${m[0]}"
println "value = ${m[1]}"
}
</groovy>
Alternatively use Ant addon Flaka, f.e. :
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- with cvs property -->
<property name="foobar" value="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu"/>
<fl:for var="item" in="split('${foobar}', ';')">
<fl:let>
param1 ::= split(item, ',')[0]
param2 ::= split(item, ',')[1]
</fl:let>
<echo>
$${param1} => ${param1}
$${param2} => ${param2}
</echo>
</fl:for>
<!-- with list inline -->
<fl:for var="item" in="split('asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu', ';')">
<fl:let>
param1 ::= split(item, ',')[0]
param2 ::= split(item, ',')[1]
</fl:let>
<echo>
$${param1} => ${param1}
$${param2} => ${param2}
</echo>
</fl:for>
</project>
Notice the double '::' in param1 ::= split(item, ',')[0]
means overriding any (also userproperties, defined via -Dkey=value as commandline arguments) existing property
whereas ':=' creates a property but won't overwrite if property already exists.
<target name="myTarget">
<ac:propertyregex property="param1"
input="${myValue}"
regexp="([^\.]*)\,.*"
select="\1"
casesensitive="true" />
<ac:propertyregex property="param2"
input="${myValue}"
regexp=".*,([^\.]*)"
select="\1"
casesensitive="true" />
<echo message = "val = ${param1}"/>
<echo message = "value = ${param2}"/>
</target>
<ac:for list="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu" delimiter=";" param="val">
<ac:sequential>
<antcall target="myTarget">
<param name="myValue" value="#{val}" />
</antcall>
</ac:sequential>
</ac:for>
Properties in Ant are immutable. You will need to use the variable task from ant-contrib (although it is discouraged) to unset the properties:
<ac:for list="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu" delimiter=";" param="val">
<ac:sequential>
<ac:propertyregex property="param1"
input="#{val}"
regexp="([^\.]*)\,.*"
select="\1"
casesensitive="true" />
<ac:propertyregex property="param2"
input="#{val}"
regexp=".*,([^\.]*)"
select="\1"
casesensitive="true" />
<echo message = "val = ${param1}"/>
<echo message = "value = ${param2}"/>
<ac:var name="param1" unset="true"/>
<ac:var name="param2" unset="true"/>
</ac:sequential>
</ac:for>

Nant wont recognize namespace.Properties

I'm trying to use nant to build a solution for a c# project however I am having an issue specifying resources in my build file. I get the error code:
CS0234: The type or namespace name 'Properties' does not exists in the namespace 'Darkside'. How can I modify my build file to remove the error?
Here is one of the snippets of code in my source files that is causing the issue:
Image enemyImage = DarkSide.Properties.Resources.DarkSide_Asteroid_Medium_Gray;
where Darkside is the namespace of the project, and the rest accesses the resources
Here is a snippet of my build file:
<target name="build" depends="init" description="compiles the source code">
<property name="build.dir" value="${project::get-base-directory()}/${project::get-name()}/bin/release/${project.version}${basedir.suffix}"/>
<mkdir dir="${build.dir}"/>
<csc target="exe" output="${build.dir}/Darkside.exe" debug="${build.debug}">
<sources>
<include name="Darkside/*.cs"/>
</sources>
<resources >
<include name="${project::get-base-directory()}/${project::get-name()}/Properties/**" />
</resources>
</csc>
</target>
You should probably define the prefix for the resources tag (with dynamicprefix="true").
<target name="build" depends="init" description="compiles the source code">
<property name="build.dir" value="${project::get-base-directory()}/${project::get-name()}/bin/release/${project.version}${basedir.suffix}"/>
<mkdir dir="${build.dir}"/>
<csc target="exe" output="${build.dir}/Darkside.exe" debug="${build.debug}">
<sources>
<include name="Darkside/*.cs"/>
</sources>
<resources dynamicprefix="true" prefix="DarkSide">
<include name="${project::get-base-directory()}/${project::get-name()}/Properties/**" />
</resources>
</csc>
</target>
Indeed the csc task's documentation states:
Note: In order to have <csc> task generate manifest resource names that match those generated by Microsoft Visual Studio.NET, the value of the prefix attribute of the <resources> element should match the "Default Namespace" of the C# project, and the value of the dynamicprefix attribute should be set to "true".

wso2 esb sequence DB update

I have a problem with the DBreport mediator which output a syntax error, but I can't see any error in the SQL statement
<sequence xmlns="http://ws.apache.org/ns/synapse" name="_dbcount">
<dblookup>
<connection>
<pool>
<password>1234</password>
<user>root</user>
<url>jdbc:mysql://localhost:3306/new_db</url>
<driver>com.mysql.jdbc.Driver</driver>
</pool>
</connection>
<statement>
<sql>
<![CDATA[ select * from consume where username= ? and id_api+ ?]]></sql>
<parameter value="riccardo" type="VARCHAR" />
<parameter value="1" type="INTEGER" />
<result name="result_use" column="use" />
<result name="result_user" column="username" />
</statement>
</dblookup>
<dbreport>
<connection>
<pool>
<password>1234</password>
<user>root</user>
<url>jdbc:mysql://localhost:3306/new_db</url>
<driver>com.mysql.jdbc.Driver</driver>
<property name="autocommit" value="false" />
</pool>
</connection>
<statement>
<sql>
<![CDATA[UPDATE consume SET use=21 WHERE username='riccardo' AND id_api='1']]></sql>
</statement>
</dbreport>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="result for client" expression="get-property('result_user')" />
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="result for use" expression="get-property('result_use')" />
</log>
</sequence>
The first DB lookup works fine but the second SQL statement in the DBreport cannot update the value:
ERROR - DBReportMediator Error execuring insert statem
ent : UPDATE consume SET use='21' WHERE username='riccardo' AND id_api='1' again
st DataSource : jdbc:mysql://localhost:3306/new_db
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in
your SQL syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'use='21' WHERE username='riccardo' AND id_api=
'1'' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)...
My tables are as follows:
consume (int id, varchar username, int id_api, int use)
users (int id, varchar username, varchar password)
many thanks
EDIT I think there are major issues with DBREPORT AND DBLOOKUP mediators when writing on a Mysql DB, reading is fine, but Update and Insert just don't work...
tell me if I am wrong
Nuvio,
I think this issue arises not because of something wrong in the DBReport mediator. While going through the reported stack trace and the sequence configuration I can see you have defined "use" as a column name. I'm not quite sure how you created a database column with the term "use" because it is a MySQL keyword and MySQL query compiler should throw a SQLException whenever you have a keyword as a column or any other user defined attribute in your SQL query. Having a non-keyword name for in place of the column "use" would fix your problem.
Cheers,
Prabath

Email notification on success/failed build using ant target

my current code(build.xml) enables me to send email on successful build, but when failed, nothing happens. The targets are called from a build.bat file through command similar to " ........ -DrepositoryAddress=%1 -DbuildResultUUID=%2 startPublish " (for all targets, in order startActivity->startPublish->mailer->startActivity).
Now, I also want email notification when the build fails.I guess trycatch will help me get the task done, but HOW? Not sure about it, where/how to place it(edit it?)? I kind of used trycatch, it gave me something like " Problem: failed to create task or type trycatch" . What modifications are required in current script/xml file to enable this functionality of sending email indicating status of build (successful or failed). Please guide/help.Thanks so much.
'
<target name="startActivity">
<fail message="Missing repositoryAddress" unless="repositoryAddress"/>
<fail message="Missing buildResultUUID" unless="buildResultUUID"/>
<fail message="Missing activityLabel" unless="activityLabel"/>
<!-- Replace ADMIN with your real credentials. -->
<startBuildActivity
buildResultUUID="${buildResultUUID}"
label="${activityLabel}"
autoComplete="true"
repositoryAddress="${repositoryAddress}"
userId="BuildAdmin"
password="Abc1234"/>
</target>
<target name="startPublish">
<sleep seconds="10"/>
<fail message="Missing repositoryAddress" unless="repositoryAddress"/>
<fail message="Missing buildResultUUID" unless="buildResultUUID"/>
<artifactfilePublisher repositoryAddress="${repositoryAddress}"
userId="BuildAdmin"
password="Abc1234"
buildResultUUID="${buildResultUUID}"
filePath="E:\Setup.msi"
label="Installer" />
</target>
<target name="mailer">
<property name="report" value="E:\Report.html"/>
<mail from="dmin#company.com" messagemimetype="text/html" charset="ISO-7779-1" messagefile="${report}" mailhost="HMMMM.company.com" mailport="25" tolist="admin#company.com" subject="Build status" />
</target>
<taskdef name="startBuildActivity"
classname="com.ibm.team.build.ant.task.StartBuildActivityTask" />
<taskdef name="artifactfilePublisher"
classname="com.ibm.team.build.ant.task.ArtifactFilePublisherTask" />
</project>'
you can implement a BuildListener that sends the email as described in the ant FAQ