Conditional task execution in ANT Scripts - java

My requirement is pretty simple, I have an ANT task which is handling exceptions internally and not throwing any exception, instead it is throwing custom messages [these are not exceptions] to the console. A sample is shown below with the test "The workspace with the specified name does not exist".
My requirement here is, if there is any such message apart from "Build Successful", I should make sure my ANT script is failed so that it won't go further. But I am unable to do so as I don't know how do I read that custom message which was written to console.
I tried exploring on 'Record' task but I was unsuccessful as this log was written only to console and not to the file (don't know why). But even if it was written to a file I should ideally read each line of file to find out a particular text present or not.
Is there a simple way to try and read things from console which were executed before?
<target name="build">
<record name="test.txt" action="start" append="true" loglevel="verbose" />
<echo>Welcome to Apache Ant! Building the project in Cordys Middleware</echo>
<property environment="env"/>
<property name="bop.install.dir" value="${env.CORDYS_HOME}"/>
<exec executable="${bop.install.dir}/components/cws/scripts/linux/CWSPackage.sh" failonerror="true" resultproperty="output">
<env key="CLASSPATH" value="/opt/Cordys/Oracle_Jar/ojdbc6.jar"/>
<arg value="${ORG_NAME}"/>
<arg value="${WORKSPACE_NAME}"/>
<arg value="${PROJECT_NAME}"/>
</exec>
<echo>Finishing the build</echo>
<record name="test.txt" action="stop"/>
<echo>${output}</echo>
<fail>Something wrong here.</fail> <!-- I want to throw this error conditionally -->
</target>

What you're looking for is the exec task's outputproperty attribute.
You can do something like this:
<exec executable="${my.executable}" outputproperty="exec.output">
<arg value="${my.arg}" />
</exec>
<fail message="Invalid output from exec task">
<condition>
<contains string="${exec.output}" substring="The workspace with the specified string does not exist." />
</condition>
</fail>
Multiple conditions (any level of complexity in the boolean is allowed):
<fail message="Invalid output from exec task">
<condition>
<and>
<not>
<contains string="${exec.output}" substring="SUCCESS" />
</not>
<or>
<contains string="${exec.output}" substring="ERROR" />
<contains string="${exec.output}" substring="FAILED" />
<or>
</and>
</condition>
</fail>
Regex:
<fail message="Invalid output from exec task">
<condition>
<matches string="${exec.output}" pattern="The .* does not exist." />
</condition>
</fail>

<!-- * This is an ANT script to build the project in development environment.
Steps involved in this are
* Building the project
* Publishing the project
* Creating the package for the project
-->
<!--
Sample command to execute this
ant build -DORG_NAME=businessservices3 -DWORKSPACE_NAME=ConfigurationManagement -DPROJECT_NAME='ConfigurationManagement'
-->
<project name="Building Project" default="build">
<property file="${PROJECT}" />
<target name="build">
<echo>Welcome to Apache Ant! Building the project in Cordys Middleware</echo>
<property environment="env"/>
<property name="bop.install.dir" value="${env.CORDYS_HOME}"/>
<exec executable="${bop.install.dir}/components/cws/scripts/linux/CWSPackage.sh" outputproperty="exec.output">
<env key="CLASSPATH" value="/opt/Cordys/Oracle_Jar/ojdbc6.jar"/>
<arg value="${ORG_NAME}"/>
<arg value="${WORKSPACE_NAME}"/>
<arg value="${PROJECT_NAME}"/>
</exec>
<fail message="Build not successful for the project ${PROJECT_NAME}">
<condition>
<not>
<contains string="${exec.output}" substring="Operation completed successful" />
</not>
</condition>
</fail>
</target>
</project>
This worked for me after so much of trail and error methods.
Thanks Austin. Even though this is the ANT which is working, I would accept your answer only as this is a modified version of what you told :)

Related

How to read and process stdout values in ant - exec?

To validate a file with an executable.
I have ant script target as:
<target name="xtest" depends="xyz" description="Additional check">
<exec executable="${xtest.exe}" failonerror="true" resultproperty="retVal">
<arg value="${inputfile.dat}" />
</exec>
<echo>Returned: ${retVal}</echo>
</target>
Output on console:
xtest:
[exec] Errors: 3
[exec] Warnings: 1
[exec] Infos: 0
[exec] Total: 4
[echo] Returned: 0
The exit code (${retVal}) of executable is 0 even if it detects error.
I want to terminate the process if Errors are more than 0.
How can I read first output line ([exec] Errors: 3) and parse the value which is 3 in above example and terminate the process?
Worked exactly with code below. Thanks!
<target name="xtest" depends="xyz" description="Additional check">
<exec executable="${xtest.exe}" failonerror="true" resultproperty="retVal" output="output.txt">
<arg value="${inputfile.dat}" />
</exec>
<echo>Returned: ${retVal}</echo>
<property file="output.txt" prefix="xtestoutput"/>
<fail>
<condition>
<not>
<equals arg1="${xtestoutput.Errors}" arg2="0" />
</not>
</condition>
</fail>
</target>
using resultproperty you can redirect output of your executable to a file.
Then, since the output matches property file format you can read that output file and use the properties in it like:
<target name="xtest" depends="xyz" description="Additional check">
<exec executable="${xtest.exe}" failonerror="true" resultproperty="retVal" output="output.txt">
<arg value="${inputfile.dat}" />
</exec>
<echo>Returned: ${retVal}</echo>
<property file="output.txt" prefix="xtestoutput"/>
<fail>
<condition>
<not>
<equals arg1="${xtestoutput.Errors}" arg2="0" />
</not>
</condition>
</fail>
</target>

Netbeans ant build error 'unsupported element customize'

I updated to Netbeans 8.0.1 from 7.0.1 and my java program compiles fine if 'Web Start' is disabled. As soon as 'Web Start' is enabled I get the following error:
C:\NetBeansProjects\SearchCriteriaEditor\nbproject\jnlp-impl.xml:480:
unsupported element customize
in this section of the jnlp-impl.xml file:
<target name="-do-jar-jnlp-application" depends="-init-filename,-test-jnlp-type,-init-macrodef-copylibs" if="is.application+mkdist.available">
<j2seproject3:copylibs manifest="${tmp.manifest.file}">
<customize>
<attribute name="Main-Class" value="${main.class}"/>
</customize>
</j2seproject3:copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${jnlp.dest.dir}/${jnlp.file}" name="jnlp.file.resolved"/>
<echo>javaws "${jnlp.file.resolved}"</echo>
</target>
The fix, as I understand it is to: 'add following to customized junit macro definition:'
<attribute default="" name="testmethods"/>
<element name="customize" optional="true"/>
<customize/>
Trouble is I have no idea where that is, nor have I modified my ant file in any way...can anyone give me a bit more information? I assume the fix goes somewhere in the jnlp-impl.xml file; I just have no idea where to put it.
Edit update: added all sections with references to 'copylibs' in the jnlp-impl.xml file-
<target name="-test-jnlp-type" depends="-test-jnlp-enabled" if="is.jnlp.enabled">
<condition property="is.applet">
<equals arg1="${jnlp.descriptor}" arg2="applet" trim="true"/>
</condition>
<condition property="is.application">
<equals arg1="${jnlp.descriptor}" arg2="application" trim="true"/>
</condition>
<condition property="is.component">
<equals arg1="${jnlp.descriptor}" arg2="component" trim="true"/>
</condition>
<condition property="is.applet+mkdist.available">
<and>
<isset property="libs.CopyLibs.classpath"/>
<istrue value="${is.applet}"/>
</and>
</condition>
<condition property="is.application+mkdist.available">
<and>
<isset property="libs.CopyLibs.classpath"/>
<istrue value="${is.application}"/>
</and>
</condition>
<condition property="is.component+mkdist.available">
<and>
<isset property="libs.CopyLibs.classpath"/>
<istrue value="${is.component}"/>
</and>
</condition>
</target>
......
<target name="-do-jar-jnlp-application" depends="-init-filename,-test-jnlp-type,-init-macrodef-copylibs" if="is.application+mkdist.available">
<j2seproject3:copylibs manifest="${tmp.manifest.file}">
<customize>
<attribute name="Main-Class" value="${main.class}"/>
</customize>
</j2seproject3:copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${jnlp.dest.dir}/${jnlp.file}" name="jnlp.file.resolved"/>
<echo>javaws "${jnlp.file.resolved}"</echo>
</target>
<target name="-do-jar-jnlp-component" depends="-test-jnlp-type,-init-macrodef-copylibs" if="is.component+mkdist.available">
<j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
</target>
Thanks in advance.
<j2seproject3:copylibs invokes the macrodef copylibs with the namespace prefix j2seproject3. There should be a place in the buildfile where the copylibs macro is defined, in a way similar (but not necessarily exact) to:
<macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
The above line should logically exist inside the -init-macrodef-copylibs target, and this is where the customize element should be defined as well. Below is the snippet based on a sample NetBeans project I have. The content will probably not match exactly the one you have, so take my answer with a grain of salt:
<macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
... <!-- some attributes may be defined here first -->
<element name="customize" optional="true"/> <!-- customize should be defined here -->
<sequential>
...
<!-- somewhere in the macrodef -->
<copylibs compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Class-Path" value="${jar.classpath}"/>
<customize/> <!-- this is where customize is used -->
</manifest>
</copylibs>
...
</sequential>
</macrodef>

Only generate source files if definitions have changed ant

I run a script that generates some java code based on definition files. I want to avoid running this task if the definition files have not changed.
<target name="generate" depends="init">
<exec executable="${codeGenTool-path}">
<arg value="${definitionFolder}" />
<arg value="${generatedFolder}" />
</exec>
</target>
I looked at http://ant.apache.org/manual/Tasks/uptodate.html but It seems like I must have a single target file to compare to. The code generation tool creates a folder containing many source files.
This is a good use case for the outofdate task from ant-contrib:
<outofdate>
<sourcefiles>
<fileset dir="${definitionFolder}" />
</sourcefiles>
<targetfiles>
<fileset dir="${generatedFolder}" />
</targetfiles>
<sequential>
<exec executable="${codeGenTool-path}">
<arg value="${definitionFolder}" />
<arg value="${generatedFolder}" />
</exec>
</sequential>
</outofdate>
This will check every file under the definitionFolder against every file under the generatedFolder - you might want to constrain the filesets more tightly, e.g. with includes="**/*.def" or whatever is the relevant file extension.
Alternatively, if you want to avoid "third party" tasks then you could use a dependset task to check the target files against the source ones.
<target name="generate" depends="check.generate, do.generate" />
<target name="check.generate">
<dependset>
<srcfileset dir="${definitionFolder}" />
<targetfileset dir="${generatedFolder}" />
</dependset>
<condition property="gen.required">
<resourcecount count="0" when="equal">
<fileset dir="${generatedFolder}" />
</resourcecount>
</condition>
</target>
<target name="do.generate" if="gen.required">
<exec ....>
</target>
The dependset task deletes all the target files if any of them are older than any of the source files, so we can make do.generate conditional - it will run if there are no files in the generatedFolder, which will be the case when either it's never been run before, or the generated files were out of date.

Ant, NetBeans Platform project - how to pass command line arguments and access via System.getProperties?

All,
I have a NetBeans Platform project (not just a project I wrote in NetBeans, but one using the rich client framework provided by NetBeans). I can run the project via an ant run command. Now, I want to pass in an argument that will work its way through ant to be accessible via the System.getProperty method.
I understand that I need to use a <sysproperty> node to actually inject the key/value pair into the runtime environment, but for the life of me I cannot figure out how to get this to work with the convoluted build tree that NetBeans creates for you (build.xml depends on build-impl.xml, which in turn depends on ${harness.dir}/suite.xml, which in turn depends on ${harness.dir}/run.xml)
The simplest example I've found is
<target name="run" depends="compile">
<java classname="prop"
fork="true">
<sysproperty key="test.property"
value="blue"
/>
</java>
</target>
but the problem is that none of my xml files have an easily accessible <java> node like that. I think I've managed to trace the execution flow to where something is actually invoked (in ${harness.dir}/run.xml)
<target name="run" depends="-prepare-as-app,-prepare-as-platform">
<touch file="${cluster}/.lastModified"/> <!-- #138427 -->
<property name="run.args" value=""/>
<property name="run.args.ide" value=""/>
<property name="run.args.extra" value=""/>
<condition property="run.args.mac" value="-J-Xdock:name=${app.name}" else="">
<os family="mac"/>
</condition>
<exec osfamily="windows" executable="${run.exe}" failonerror="no" resultproperty="result.prop">
<arg value="--jdkhome"/>
<arg file="${run.jdkhome}"/>
<arg line="${run.args.common}"/>
<arg line="${run.args.prepared}"/>
<arg line="${run.args}"/>
<arg line="${run.args.ide}"/>
<arg line="${run.args.extra}"/>
</exec>
<exec osfamily="unix" dir="." executable="sh"
failonerror="no" resultproperty="result.prop">
<arg value="${run.sh}"/>
<arg value="--jdkhome"/>
<arg file="${run.jdkhome}"/>
<arg line="${run.args.common}"/>
<arg line="${run.args.prepared}"/>
<arg line="${run.args}"/>
<arg line="${run.args.ide}"/>
<arg line="${run.args.extra}"/>
<arg line="${run.args.mac}"/>
</exec>
<fail>
The application is already running within the test user directory.
You must shut it down before trying to run it again.
<condition>
<and>
<isset property="result.prop" />
<or>
<!-- unknown option exit code as returned from IDE by org.netbeans.api.sendopts.CommandLine -->
<equals arg1="${result.prop}" arg2="50346" />
<!-- unknown option exit code as returned from platform app by org.netbeans.CLIHandler -->
<equals arg1="${result.prop}" arg2="2" />
</or>
</and>
</condition>
</fail>
</target>
As you can see, there is no <java> node underneath which I can put my custom sysproperty. Furthermore, it seems like a very wrong thing to do to have to muck around with harness xml files to inject a property that only affects one of my projects, not all of them. So what's the correct way to ensure that a command line property I pass to ant run ends up within a NetBeans Platform project?
There is a folder etc in the distribution of your RCP app and in that folder is file yourapp.conf i think there is an answer you seek. For example from one of mine NB RCP app:
# ${HOME} will be replaced by user home directory according to platform
default_userdir="${HOME}/.${APPNAME}/dev"
default_mac_userdir="${HOME}/Library/Application Support/${APPNAME}/dev"
# options used by the launcher by default, can be overridden by explicit
# command line switches
default_options="--laf Metal --branding xmled -J-Xms24m -J-Xmx64m"
# for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea
# default location of JDK/JRE, can be overridden by using --jdkhome <dir> switch
#jdkhome="/path/to/jdk"
# clusters' paths separated by path.separator (semicolon on Windows, colon on Unices)
#extra_clusters=

How to determine build architecture (32bit / 64bit) with ant?

We have inherited an ant build file but now need to deploy to both 32bit and 64bit systems.
The non-Java bits are done with GNUMakefiles where we just call "uname" to get the info. Is there a similar or even easier way to mimic this with ant?
Late to the party, but what the heck...
${os.arch} only tells you if the JVM is 32/64bit. You may be running the 32bit JVM on a 64bit OS. Try this:
<var name ="os.bitness" value ="unknown"/>
<if>
<os family="windows"/>
<then>
<exec dir="." executable="cmd" outputproperty="command.ouput">
<arg line="/c SET ProgramFiles(x86)"/>
</exec>
<if>
<contains string="${command.ouput}" substring="Program Files (x86)"/>
<then>
<var name ="os.bitness" value ="64"/>
</then>
<else>
<var name ="os.bitness" value ="32"/>
</else>
</if>
</then>
<elseif>
<os family="unix"/>
<then>
<exec dir="." executable="/bin/sh" outputproperty="command.ouput">
<arg line="/c uname -m"/>
</exec>
<if>
<contains string="${command.ouput}" substring="_64"/>
<then>
<var name ="os.bitness" value ="64"/>
</then>
<else>
<var name ="os.bitness" value ="32"/>
</else>
</if>
</then>
</elseif>
</if>
<echo>OS bitness: ${os.bitness}</echo>
EDIT:
As #GreenieMeanie pointed out, this requires the ant-contrib library from ant-contrib.sourceforge.net
you can get at the java system properties (http://java.sun.com/javase/6/docs/api/java/lang/System.html#getProperties()) from ant with ${os.arch}. other properties of interest might be os.name, os.version, sun.cpu.endian, and sun.arch.data.model.
Here is an answer that works (I tested on Kubuntu 64, Debian 32, Windows 2000 and Windows XP) without the need of external or optional ANT dependencies. It was based on #phatypus's answer.
<project name="FindArchitecture" default="check-architecture" basedir=".">
<!-- Properties set: unix-like (if it is unix or linux), x64 (if it is 64-bits),
register- size (32 or 64) -->
<target name="check-architecture" depends="check-family,check-register" >
<echo>Register size: ${register-size}</echo>
<echo>OS Family: ${os-family}</echo>
</target>
<target name="check-family" >
<condition property="os-family" value="unix" else="windows">
<os family="unix" />
</condition>
<condition property="unix">
<os family="unix" />
</condition>
</target>
<target name="check-register" depends="reg-unix,reg-windows">
</target>
<!-- Test under GNU/Linux -->
<target name="reg-unix" if="unix">
<exec dir="." executable="uname" outputproperty="result">
<arg line="-m"/>
</exec>
<!-- String ends in 64 -->
<condition property="x64">
<matches string="${result}" pattern="^.*64$"/>
</condition>
<condition property="register-size" value="64" else="32">
<isset property="x64"/>
</condition>
</target>
<!-- Test under MS/Windows-->
<target name="reg-windows" unless="unix">
<!-- 64 bit Windows versions have the variable "ProgramFiles(x86)" -->
<exec dir="." executable="cmd" outputproperty="result">
<arg line="/c SET ProgramFiles(x86)"/>
</exec>
<!-- String ends in "Program Files (x86)" -->
<condition property="x64">
<matches string="${result}" pattern="^.*=.*Program Files \(x86\)"/>
</condition>
<condition property="register-size" value="64" else="32">
<isset property="x64"/>
</condition>
</target>
</project>
You can just pass a parameter into the build file with the value you want. For example, if your target is dist:
ant -Dbuild.target=32 dist
or
ant -Dbuild.target=64 dist
and then in your Ant build script, take different actions depending on the value of the ${build.target} property (you can also use conditions to set a default value for the property if it is not set).
Or, you can check the value of the built-in system properties, such as ${os.arch}.
os.arch does not work very well, another approach is asking the JVM, for example:
~$ java -d32 test
Mon Jun 04 07:05:00 CEST 2007
~$ echo $?
0
~$ java -d64 test
Running a 64-bit JVM is not supported on this platform.
~$ echo $?
1
That'd have to be in a script or a wrapper.
BTW, the os.arch (arch property of the os tag) I got for 64-bit Linux was amd64.
Assuming you are using ANT for building Java Application, Why would you need to know if it is a 32 bit arch or 64-bit? We can always pass parameters to ant tasks. A cleaner way would be to programmaticaly emit the system properties file used by Ant before calling the actual build. There is this interesting post http://forums.sun.com/thread.jspa?threadID=5306174.

Categories

Resources