ANT How to use the lexically scoped properties in Ant 1.8? - scripting

I have script that dosn't work becouse property once set became unwritable
<target name="test" >
<fileset id="dir1" dir="./dir1"/>
<fileset id="dir2" dir="./dir2"/>
<pathconvert property="path.converted" refid="dir1"/>
<echo message="${path.converted}"/>
<property name="path.converted" value="set this property manually"/>
<echo>${path.converted}</echo>
<pathconvert property="path.converted" refid="dir2"/>
<echo message="${path.converted}"/>
</target>
always echoed the same result, but I want that echoes was different
I read in Apache Ant 1.8.0 release, that
Lexically scoped local properties,
i.e. properties that are only defined
inside a target, sequential block or
similar environment. This is very
useful inside of s where a
macro can now define a temporary
property that will disappear once the
task has finished.
How to use them?

I found solution. Use local task
<target name="direct" depends="">
<fileset id="dir1" dir="./dir1"/>
<fileset id="dir2" dir="./dir2"/>
<!--<property name="path.converted" value="0"/>-->
<local name="path.converted"/>
<pathconvert property="path.converted" refid="dir1"/>
<echo message="${path.converted}"/>
<local name="path.converted"/>
<property name="path.converted" value="0"/>
<echo>${path.converted}</echo>
<local name="path.converted"/>
<pathconvert property="path.converted" refid="dir2"/>
<echo message="${path.converted}"/>
</target>

I would simply use different names for path.converted for the example above.
path.converted.1, path.converted.2 etc.
If you would have created a macrodef you should definitely use the local task to make the property local.

Related

Sonar Integration Tests Coverage not show + Selenium + Jboss +Jacoco

I use Sonar 4.1.1, Jboss 6.x, Jacoco 0.6.4, execute tasks with Ant I am not allowed to use Maven. In an eclipse workspace, I have two projects, one is the web application another is selenium test.
I am able to get unit test and code coverage for unit test. But sonar is not able to read the integration test file created by Jacoco. I think there might be something wrong with the way I create jacoco-it.exec file so sonar can't read it. Because sonar does read my jacoco-ut.exec file. And I am able to have both reportPath and itReportPath to read my jacoco-ut.exec file with no problem. Also thinking maybe is something wrong in my build file. I did a lot of research and tried many different ways to create the jacoco-it.exec file, different Jacoco settings and followed different examples from sonar, jacoco, other blogs but still doesn't work. I must be missing something Help!! Thanks!!
I have VM arguments for Jboss like this
-javaagent:/path to jar/jacocoagent.jar=destfile=/path for create/jacoco-it.exec
When I run selenium, the above code create a file with some data, size about 1.3MB
Here is the part of build relate to this issue
<property name="sonar.sourceEncoding" value="UTF-8" />
<property name="sonar.java.coveragePlugin" value="jacoco" />
<property name="sonar.core.codeCoveragePlugin" value="jacoco" />
<property name="sonar.dynamicAnalysis" value="reuseReports" />
<property name="sonar.jacoco.reportsPath" value="${reports.dir}/junit" />
<property name="sonar.jacoco.itReportPath" value="${reports.dir}/jacoco-it.exec" />
<property name="sonar.jacoco.reportPath" value="${reports.dir}/jacoco-ut.exec" />
<target name="unitTest" depends="compile">
<taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
<classpath>
<path refid="classpath"/>
</classpath>
</taskdef>
<!-- Import the JaCoCo Ant Task -->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath refid="classpath"/>
</taskdef>
<!-- Run your unit tests, adding the JaCoCo agent -->
<jacoco:coverage destfile="reports/jacoco-ut.exec" xmlns:jacoco="antlib:org.jacoco.ant">
<junit printsummary="yes" haltonfailure="yes" forkmode="once" fork="true" dir="${basedir}" failureProperty="test.failed">
<classpath location="${classes.dir}" />
<classpath refid="classpath"/>
<formatter type="plain" />
<formatter type="xml" />
<batchtest fork="true" todir="${reports.junit.xml.dir}">
<fileset dir="src">
<include name="**/*TestAdd.java" />
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
</target>
<target name="coverageTest" depends="compile">
<taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
<classpath>
<path refid="classpath"/>
</classpath>
</taskdef>
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath refid="classpath"/>
</taskdef>
<!--Run your unit tests, adding the JaCoCo agent-->
<jacoco:coverage xmlns:jacoco="antlib:org.jacoco.ant" dumponexit="true" >
<junit printsummary="yes" haltonfailure="yes" forkmode="once" fork="true" dir="${basedir}" failureProperty="test.failed">
<classpath location="${classes.dir}"/>
<classpath refid="classpath"/>
<formatter type="plain" />
<formatter type="xml" />
<formatter type="plain" usefile="false"/>
<batchtest todir="${reports.junit.xml.dir}">
<fileset dir="../HelloAppTest/src">
<include name="**/answerTest.java"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
</target>
The reason for that is, may be you are NOT attaching Jacocoagent.jar file to the "TARGET" (ex: JBoss / Tomcat) JVM's scope and stopping it so that it can flush the final code coverage data to the jacoco it exec file.
Once you do that (instead of using Maven/ANT's JVM scope), run your non-Unit (IT) tests and then STOP the target JVM.
After the target JVM is stopped, you'll get the final jacoco .exec file genreated for the IT tests. Use that file for sonar.jacoco.itReportPath variable and it'll work.
For ex: I pass/have this variable to the Tomcat's startup.sh script and while starting tomcat (target JVM), I use this variable within the Tomcat's actual start command.
PROJ_EXTRA_JVM_OPTS=-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/IT/jacocoIT.exec,append=false

dependent target getting excecute multiple times in a parallel target call

i want to run few targets of ANT build in parallel. here is the code i tried
<project name="cis" default="release">
<property name="Run_excecuted" value="false"/>
<target name="run_main">
<sequential>
<parallel>
<antcall target="dashboard" />
<antcall target="remTraces" />
<param name="Run_excecuted" value="true"/>
</parallel>
</sequential>
</target>
I have set a property Run_excecuted in the build and have added the condition unless="Run_excecuted" in the required targets
<target name="dashboard" depends="prepare" unless="Run_excecuted">
<target name="remTraces" depends="prepare" unless="Run_excecuted">
what is happening is the antcalls are getting invoked in separate instances parallely and the dependencies are getting calculated again. Because of this target "prepare" is running multiple times. i dont want this to happen.How can i do this? property Run_excecuted being set is not helping.

Creating DDL scripts from JPA/Hibernate Annotation Classes Using ANT

I would like to generate SQL DDL scripts from Hibernate/JPA Annotation Classes using ANT.
Below is the ANT script that I wrote based on Hibernate Dev Docs URL: http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/
<project name="yourmarketnet" default="all" basedir=".">
<target name="ddl_generation">
<!-- paths to required jars -->
<path location="web/WEB-INF/lib/hibernate-annotations.jar" />
<path location="web/WEB-INF/lib/ejb3-persistence.jar" />
<path location="web/WEB-INF/lib/hibernate-entitymanager.jar" />
<path location="web/WEB-INF/lib/javaassist.jar" />
<path location="web/WEB-INF/lib/hibernate-tools.jar"/>
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask.jar">
<classpath path="${build.dir}/web/WEB-INF/lib/hibernate-tools.jar"/>
</taskdef>
<!-- output destination -->
<hibernatetool destdir="${build.dir}">
<!-- were the annotation beans files are located-->
<classpath>
<path location="${build.dir}/web/WEB-INF/classes/com/yourmarketnet/beans" />
</classpath>
<!-- list exporters here -->
<hbm2ddl
export="false"
update="false"
drop="true"
create="true"
outputfilename="myApps.ddl"
delimiter=";"
format="false"
haltonerror="true"/>
</hibernatetool>
</target>
</project>
Im getting ERROR taskdef class org.hibernate.tool.ant.HibernateToolTask cannot be found
using the classloader AntClassLoader[]
I also checked to see if hibernate-tools.jar was actually in the path and it was (C:\Users\naim\Documents\NetBeansProjects\yourmarketnet\build\web\WEB-INF\lib\hibernate-tools.jar)
Can someone please tell me step by step how to fix/debug this issue , thanks.
Error message clearly tells you that ant can't find your tools. When you declare
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" >
<classpath path="${build.dir}/web/WEB-INF/lib"/>
</taskdef>
it's already wrong because tool classes are not in directory but in jar. Secondly, your intent seems to be to use ${build.dir} as output location, so why would it contain tool classes? Anyway, you didn't even define this directory.
So if you really have your hibernate-tools.jar in web/WEB-INF/lib, you probably want something like
<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" >
<classpath path="web/WEB-INF/lib/hibernate-tools.jar"/>
</taskdef>
Note that it's relative to your project directory.

How to do OpenJPA enhancement with Ant + IntelliJ IDEA

This is driving me crazy and I'm shocked that official documentation is absolutely useles.
Here is what I have:
IntelliJ IDEA 11
OpenJPA 2.1.1
Since openjpa is added into list of used libraries I already had classpath to OpenJPA which looks like this
<path id="library.openjpa.classpath">
<fileset dir="${basedir}/lib/openjpa">
<patternset refid="library.patterns"/>
</fileset>
</path>
According to official documentation I added following target
<target name="enhance">
<copy includeemptydirs="false" todir="${basedir}/lib/openjpa">
<fileset dir="src" excludes="**/*.launch, **/*.java"/>
</copy>
<taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask">
<classpath refid="library.openjpa.classpath"/>
</taskdef>
<openjpac>
<classpath refid="library.openjpa.classpath"/>
</openjpac>
</target>
It gives me exception
C:\work\prj\build.xml:283: org.apache.openjpa.util.MetaDataException:
MetaDataFactory could not be configured
(conf.newMetaDataFactoryInstance() returned null). This might mean
that no configuration properties were found. Ensure that you have a
META-INF/persistence.xml file, that it is available in your classpath,
or that the properties file you are using for configuration is
available. If you are using Ant, please see the or
attributes of the task's nested element.
This can also occur if your OpenJPA distribution jars are corrupt, or
if your security policy is overly strict.
I tested with Process Monitor and can see that it opens and reads persistence.xml.
Some person filed bug having problems I have and the answer he got was that finding persistence.xml is not a source of problem.
Questions are:
What can I do to make it work ?
Can I make it work by skipping need for persistence.xml and just specifying pattern for .class files I want to be enhanced ?
It's more Ant question. How can I make OpenJPA enhancer to look for persistence.xml in directory other than where openjpa-2.1.1.jar resides ?
So I couldn't make it work without undocumented propertiesFile. Here is version that works for me. Also specifying persistence-unit via # makes it fail with NullReferenceException.
<target name="enhance">
<taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask">
<classpath refid="library.openjpa.classpath"/>
</taskdef>
<openjpac>
<classpath refid="library.openjpa.classpath"/>
<classpath location="${reporting.output.dir}"/>
<config propertiesFile = "${basedir}/src/META-INF/persistence.xml"/>
</openjpac>
</target>
It appears that you might have missed an important part from the documentation. Your library.openjpa.classpath is missing a reference to your Entities, and the location of the persistence.xml file. Try adding that and see how it goes.
<path id="jpa.enhancement.classpath">
<pathelement location="bin"/> <!-- add something like this -->
<!-- lib contains all of the jars that came with the OpenJPA binary download -->
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>

Do I have a way to check the existence of a directory in Ant (not a file)?

How do I check for the existence of a folder using Ant?
We can check the existence of a file, but can we do the same for a folder as well?
You use the available task with type set to "dir".
For example:
<available file="${dir}" type="dir"/>
The standard way to do conditional processing is with the condition task. In the example below, running doFoo will echo a message if the directory exists, whereas running doBar will echo a message unless the directory exists.
The dir.check target is required by both doFoo and doBar, it sets the dir.exists property to true or false depending on the result of the available task. The doFoo target will only run if that propery is set to true and doBar will only run if it is not set or set to false.
<?xml version="1.0"?>
<project name="test" default="doFoo" basedir=".">
<property name="directory" value="c:\test\directory"/>
<target name="doFoo" depends="dir.check" if="dir.exists">
<echo>${directory} exists</echo>
</target>
<target name="doBar" depends="dir.check" unless="dir.exists">
<echo>${directory} missing"</echo>
</target>
<target name="dir.check">
<condition property="dir.exists">
<available file="${directory}" type="dir"/>
</condition>
</target>
</project>
Antelope provides additional tasks, including an If task that can make the processing simpler (and to me, more intuitive), you can download the Antelope tasks from the download page.
Here's a small example incorporating the available element into an if test.
<!-- Test if a directory called "my_directory" is present -->
<if>
<available file="my_directory" type="dir" />
<then>
<echo message="Directory exists" />
</then>
<else>
<echo message="Directory does not exist" />
</else>
</if>
Warning: you need ant-contrib.jar in your ANT_HOME\lib directory otherwise you won't have access to the if elements, and your script will fail with this error:
Problem: failed to create task or type if
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
Here's my solution, which doesn't require setting properties and using targets with 'if' or 'unless':
Macro:
<macrodef name="assertDirAvailable">
<attribute name="dir" />
<sequential>
<fail message="The directory '#{dir}' was expected to be available but is not">
<condition>
<not>
<available file="#{dir}" type="dir" />
</not>
</condition>
</fail>
</sequential>
</macrodef>
Usage:
<assertDirAvailable dir="${dirToCheck}" />
My solution using ANT 1.8 version, older versions may not work due if/unless not supporting ${evalTrueOrFalse} syntax.
<?xml version="1.0" encoding="UTF-8"?>
<project name="DoMagic" default="build" basedir=".">
<property environment="env" />
<property name="name" value="Do the ANT Magic" />
<property name="somedir" value="./must_exist_folder"/>
<tstamp><format property="TODAY" pattern="yyyy-MM-dd HH:mm:ss" /></tstamp>
<target name="doMagic" if="${dir.exists}">
<echo message="Do the magic stuff" />
</target>
<target name="doUsage" unless="${dir.exists}">
<echo message="Do usage and help" />
</target>
<target name="build">
<echo message="Do the magic" />
<condition property="dir.exists" else="false"><available file="${somedir}" type="dir" /></condition>
<echo message="Folder found: ${dir.exists}" />
<antcall target="doCustomize"></antcall>
<antcall target="doUsage"></antcall>
</target>
</project>
ANT 1.6 or early ANT 1.7 does not work, upgrade to ANT 1.8 release.
Target attributes if and unless evaluates ${var} syntax to true/false
Condition attribute else value is set to property if available condition was false, without it variable is not set. NotSet value is not same as an explicit false value.
call any target but if/unless attribute defines whether its actually run
http://ant.apache.org/manual/properties.html#if+unless
[If/Unless] In Ant 1.7.1 and earlier, these attributes could only be property names. As of Ant 1.8.0, you may instead use property expansion. Compared to the older style, this gives you additional flexibility.
Here is another approach, allows to call just one task without using ant-contrib.jar.
<target name="my-task" depends="dir-check">
<antcall target="my-task-install"/>
<antcall target="my-task-update"/>
</target>
<target name="my-task-install" unless="dir.exists" >
{some task}
</target>
<target name="my-task-update" if="dir.exists" >
{another task}
</target>
<target name="dir-check">
<condition property="dir.exists">
<available file="my-dir" type="dir" />
</condition>
</target>
Here is another example involving for loop. Fail if a directory does not exist.
<for list="dir1/, dir2/, dir3/" param="local.dir" >
<sequential>
<fail message="Directory #{local.dir} does not exist">
<condition>
<not>
<available file="#{local.dir}" type="dir" />
</not>
</condition>
</fail>
</sequential>
</for>