How to identify if a file is copied from a particular archive? - ant

I am new to ANT.
I have a very specific scenario to handle in this:
STEP-1: I need to look for the pattern of filenames in certain ear files. If the pattern matches then I need to extract those files.
STEP-2: And if any file is extracted from a certain ear (similar to zip-file) file, then I need to search for another set of files, and copy those set of files too.
The case to handle is "How to identify if a file is copied from a particular archive" if found then proceed to step 2, else move to next archive.
I have achieved STEP-1 but no idea how to achieve step-2.
STEP-1
<!-- Set via arguments passed -->
<patternset id="pattern.needtocopy" includes="${needtocopyfile.pattern}" excludes="${ignore.pattern}">
</patternset>
<target name="get-binaries-from-baseline">
<for param="binary">
<path>
<fileset dir="${baseline.dir}/target/aaa/bbb/ccc" includes="*.ear" />
</path>
<sequential>
<basename file="#{binary}" property="#{binary}.basename" />
<unzip src="#{binary}" dest="${baseline.dir}">
<patternset refid="pattern.needtocopy" />
<mapper type="flatten" />
</unzip>
</sequential>
</for>
</target>
STEP-2:
????
Need help in this.
Thanks.

Well I resolved the same, using a groovy script based on the resources I could find.
<target name="findJars">
<zipfileset id="found" src="${ear-name}">
<patternset refid="${patternsetref}" />
</zipfileset>
<groovy>
project.references.found.each {
println it.name
println project.properties.'ear-name'
println project.properties.'dest.dir'
}
</groovy>
</target>
And then I added another task which takes this filename and ear-file-name as input and extracts the related jars based on file to search pattern.

Related

displaying ant task/target in recorder log

I am using the ant task <record> to create a log file of the output and activity of my ant build script. The problem is:
i am not seeing the names of the targets that are being executed.
For instance: When my target called cleanFW is being executed, i only see the stuff being done inside the target and NOT the name of the target it self. Since this is happening, i have no way of telling when cleanFW began in the log file.
Is there a way to get this cleanFW target name to appear? It was appearing when i was using the flag -logfile. But i had to switch to <record> because i want to record log file and see the output in console.
Using Ant 1.8.2
simple solution
My simple solution to this is to just put an echo in each one of the targets. Just wondering if there was a better way.
sample code where it is not working
<project name="foobar">
<record name="test.txt" action="start" append="true" loglevel="verbose" />
... lots of property stuff here ...
<target name="cleanFW">
<record name="test.txtaction="start" append="true" loglevel="verbose"/>
<mkdir dir="${FOOBAR_OUTPUT}"/>
<mkdir dir="${FOOBAR_GEN}"/>
<delete includeemptydirs="true">
<fileset dir="${FOOBAR_BIN}" includes="**/*"/>
<fileset dir="${FOOBAR_GENERATED}" includes="**/*"/>
<fileset dir="${FOOBAR_NODES}" includes="**/*"/>
<fileset dir="${FOOBAR_GEN}" includes="**/*"/>
</delete>
<mkdir dir="${FOOBAR_OUTPUT}"/>
<record name="test.txt" action="stop"/>
</target>
<record name="test.txt" action="stop"/>
</project>
The reason why i have the first record name="test.txt" action="start" append="true" loglevel="verbose" /> at the top, is because i want all of the statements and stuff that are before the targets to be displayed too. Like my property sets and all that jazz. I left that junk out because it is not important.
I'm at a bit of a loss to explain why exactly, but I think you need to omit the last record 'stop' task - the one that is outside of a target.
Having said that, you can probably omit all of the record tasks except the first 'start', and get the result you want.

Macrodef and "local properties"

I am trying to move a file (specified by a pattern) to a given location in an Ant macrodef:
<macrodef name="extract">
<attribute name="package"/>
<sequential>
<!-- the path will contain the unique file in extracted regardless of the name -->
<path id="source_refid">
<dirset dir="${dep}/lib/#{package}/extracted/">
<include name="#{package}-*"/>
</dirset>
</path>
<!-- this is not working: properties are immutable -->
<property name="source_name" refid="source_refid"/>
<move
file="${source_name}"
tofile="${dep}/#{package}/"
overwrite="true"
/>
</sequential>
</macrodef>
This will work just once as ${source_name} is immutable.
An option would be to use the variable task but I didn't find a way to assign a refid to a var.
Is there a way to have something similar to local variable in a macrodef? Or (XY problem) is there a better way to solve my problem?
Since Ant 1.8 you can use the local task for this. For example:
<local name="source_name"/>
<property name="source_name" refid="source_refid"/>
Your example is just the sort of thing local is for!

Exporting zipfilesets

We are currently generating a zip file using multiple targets as follows.
<zipfile>
<zipfileset dir="alpha" prefix="alpha" />
<zipfileset dir="beta" prefix="alpha" excludes="*.bar" />
<zipfileset dir="gamma/G" prefix="gamma" />
</zipfile>
A requirement has come up in that we need to generate (and include) a list of the included files and their corresponding MD5 checksum values.
If we use a <fileset>/<patternset>/<pathconvert> combination, I can get a text file containing all the files, and generate from there. However, I can't seem to find a way to do this with <zipfileset /> targets.
Is there a way to do a 'dry-run' and obtain a list of the targets that will be included? Or is there a (simple) method of extracting the required information from the generated ZIP itself?
If you have already generated file (with checksum) you can just add it with help of another fileset.
The sample:
<target name="ziptest">
<zip destfile="${src}\output.zip">
<fileset dir="${src}">
<include name="dir1\*"/>
<include name="dir2\fileprefix*"/>
</fileset>
<fileset dir="${src}">
<!-- You have property with filename: file.name.checksum-->
<include name="${file.name.checksum}"/>
</fileset>
</zip>
</target>

[ANT]Property and Classpathref inherit broken in "foreach"

To explain it briefly, here is an example:
In build.xml, local-db.xml is imported. And in local-db.xml, there is a target named "warmup" which calls one target of the third file -- local-gr.xml using task.
All the common properties and classpath defs are imported and set in build.xml.
in project.properties:
dest-dir=./destination
in build.xml:
<path id="gr-classpath"> ... </path>
<import file="local-db.xml" />
in local-db.xml:
<ant antfile="local-gr.xml" target="deploy" inheritAll="true" inheritRefs="true" />
In local-gr.xml, there are two targets like this:
<target name="deploy">
<tar ....../>
<foreach list="${list1}" delimiter="," parallel="true" trim="true" param="item" target="deploy-single" />
</target>
<target name="deploy-single">
something using property ${dest-dir} and path "gr-classpath"
</target>
Now here is the problem:
The property ${dest-dir} and path "gr-classpath" can be used in "deploy" because I set inheritAll and inheritRefs, but it can't be used directly in "deploy-single". "inherit" doesn't when the target is called by foreach?
I managed to pass ${dest-dir} to "deploy-single" with the help of the , but I didn't find any way to pass the classpathref "gr-classpath" to "deploy-single".
What I did to work around it was to claim the again in "deploy-single", but I don't like it at all.
Why this happens? What can I do to make it more elegant?
The ant-contrib foreach task doesn't by default propagate all properties and references to it's target. But it does have inheritall and inheritrefs attributes that you can use to make that happen.
<foreach list="${list1}" delimiter="," parallel="true" trim="true"
param="item" target="deploy-single"
inheritall="true" inheritrefs="true"
/>

passing properties defined inside antcall target back to calling target

I'm rather new to Ant but I have experienced it's quite good pattern to create generic ant targets which are to be called with antcall task with varying parameters.
My example is compile target, which compiles multiple systems using complex build command which is a bit different for each system. By using pattern described above it's possible not to create copy paste code for that compile command.
My problem here is, that I'm not aware of any way to pass return value (for example the return value of compiler) back to target which called the antcall task. So is my approach pathological and it's simply not possible to return value from antcall task or do you know any workaround?
Thanks,
Use antcallback from the ant-contrib jar instead of antcall
<target name="testCallback">
<antcallback target="capitalize2" return="myKey">
</antcallback>
<echo>a = ${myKey}</echo>
</target>
<target name="capitalize2">
<property name="myKey" value="it works"/>
</target>
Output:
testCallback:
capitalize2:
[echo] a = it works
BUILD SUCCESSFUL
One approach is to write out a property to a temp file using "echo file= ...." or PropertyFile task. Then read the property back in where required. Kludge but works.
Ant tasks are all about stuff goes in, side effect happens. So trying to program in terms of functions (stuff goes in, stuff comes out) is going to be messy.
That said what you can do is generate a property name per invocation and store the result value in that property. You would need to pass in a indentifier so you do not end up trying to create copies of the same property. Something like this:
<target name="default">
<property name="key" value="world"/>
<antcall target="doSomethingElse">
<param name="param1" value="${key}"/>
</antcall>
<echo>${result-${key}}</echo>
</target>
<target name="doSomethingElse">
<property name="hello-${param1}" value="it works?"/>
</target>
But I believe the more typical approach -instead of antcalls- is to use macros. http://ant.apache.org/manual/Tasks/macrodef.html
Antcall can be used from the ant-contrib jar task.
You can get a similar behaviour with the keyword "depends".
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" default="main">
<target name="main">
<antcall target="build-system-with-depends" />
<!-- wait for different results -->
<waitfor checkevery="1000" checkeveryunit="millisecond" maxwaitunit="millisecond" maxwait="2000">
<available file="dummy.not.present.file" classname="" property=""></available>
</waitfor>
<antcall target="build-system-with-depends" />
</target>
<target name="build-system-with-depends" depends="do-compiler-stuff">
<echo>$${compiler.result}=${compiler.result}</echo>
</target>
<target name="do-compiler-stuff">
<!-- simulate different return states -->
<tstamp>
<format pattern="yyyyMMddHHmmss" property="compiler.result" />
</tstamp>
</target>
</project>

Resources