I am looking for help as I am unable to pass values among ant script.
The job of my ant script is to compile the source code and later zip all the files into one folder and name it such as - compile-2.0.0.0.zip.
I have been reading the number "2.0.0.0" from a properties file. My ant script structure looks like this..
Base directory "A":
build-common.xml
--> reads the property file and assign value in one variable. code looks like this -
<propertyfile file="./build.properties" >
<entry key="VERSION_NUMBER" type="string" default="2.0.0.0"/>
</propertyfile>
Same Base directory "A": buildA.xml
message="* GENERATING EXE S{VERSION_NUMBER}************" />
Directory "B": (buildB.xml called by buildA.xml)
message="* GENERATING EXE S{VERSION_NUMBER}************" />
The problem is - I cannot access ${VERSION_NUMBER} in buildB.xml. Am I doing anything wrong here?
Code to call buildB.xml from buildA.xml..
<antcall target="antCall" >
<param name="antDir" value="${pathB}"/>
</antcall>
Any help will be highly appreciated.
That how the value gets passed to another ant script in different directory !
<antcall target="antCall" >
<param name="antDir" value="${pathB}"/>
<param name="VERSION_NUMBER" value="${VERSION_NUMBER}" />
</antcall>
Related
I have jar file having some properties files in it like log4j.properties and config.properties. Following is my ant script for yguard. Everything else is working but the properties file updation.
<target name="yguard">
<taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" classpath="lib/yguard.jar" />
<yguard>
<inoutpairs resources="none">
<fileset dir="${basedir}">
<include name="MyApp.jar" />
</fileset>
<mapper type="glob" from="MyApp.jar" to="MyAppObs.jar" />
</inoutpairs>
<externalclasses>
<pathelement location="lib/log4j-1.2.17.jar" />
</externalclasses>
<rename conservemanifest="true" mainclass="com.amit.Application" >
<adjust replaceContent="true" >
<include name="**/*.properties" />
</adjust>
</rename>
</yguard>
</target>
config.properties file
com.amit.Application.param1 = something
I found some question in stackoverflow but they didn't help. One place it was mentioned that the file (like jsp, xml, properties) should be in the jar file which I already have. But my yguard obfuscated file just get the files copied as it is.
I tried many combinations with rename & adjust tags but nothing worked for me.
Following post I already visited
Is it possible to manage logs through Obfuscation with yGuard?
How to include obfuscated jar file into a war file
Apparently you want yGuard to obfuscate the name of the field param1, because com.amit.Application is obviously your entry point and yGuard excludes the given main class automatically. So basically you want the outcome to be something like
com.amit.Application.AÖÜF = something
This isn't possible, because yGuard can only adjust class names in property files, as state here: yGuard Manual
We have a Java applet project and we generate the wrapper HTML using Ant, it looks a bit like this:
<target name="build-applet" description="Build web applet" depends="set-build-properties, set-properties">
<antcall target="clean" />
<antcall target="clean-applet" />
<antcall target="set-version" />
<antcall target="compile" />
<antcall target="jar" />
<antcall target="applet" />
</target>
<target name="applet">
<replace file="${applet.dir}/${applet.html.file}">
<replacefilter token="#jar.file#" value="${applet.jar.file}"/>
<replacefilter token="#assets.file#" value="${applet.assets.file}"/>
<replacefilter token="#codebase#" value="${applet.codebase}"/>
</target>
Note that ${applet.codebase} has to be the URL where the applet is loaded from e.g mysite.com/game. It's set in a properties file.
Now I want to be able to build this applet to two different locations, part of a live/test setup. e.g one is accessed at mysite.com/game and the other at mysite.com/test. I have it almost working, except for ${applet.codebase} because this needs to be different in each case. I thought I could have ${applet.codebase} and ${applet.codebase_test} but I don't know how to do this. Maybe there's a way to pass a flag into the applet target from build-applet, and add two top-level targets build-applet-live and build-applet-test which just call build-applet with the parameter.
Why not simply ant -Dapplet.codebase=whatever build.xml, means set ${applet_codebase} as userproperty (= those properties set via -Dkey=value) ?
here is what am trying to do, I want to replace name and address from my large number of property files during build, but unfortunately I cant do this, is there a better way of doing this without having to copy paste the foreach twice. can someone help?
<target name="replace" >
<foreach target="replace.name,replace.address" param="foreach.file" inheritall="true">
<path>
<fileset dir="${build.tmp.dir}/resource">
<!-- some complicated conditions go here -->
</path>
</foreach>
</target>
<target name="replace.address">
<echo>replacing #Address# for ${foreach.file}</echo>
<replace file="${foreach.file}" token="#Address#" value="${address}" />
</target>
<target name="replace.name">
<echo>replacing #Name# for ${foreach.file}</echo>
<replace file="${foreach.file}" token="#Name#" value="${Name}" />
</target>
.properties file looks like
name=#Name#
address=#Address#
target of foreach is not designed to take more than one target name. It only iterates through the provided list, not the provided targets.
To make the implementation more DRY, you may
use a for loop instead of foreach with two antcalls;
use macrodef with for loop -- macrodef can pack several ant xml code into a task-like thing
Actually, for the two targets -- replace.address and replace.name, are you sure that you want to call them from the commandline?
If not, name them -replace.address and -replace.name or use macrodef -- exposing the iteration body of foreach is not a good practice.
I have an XSL style sheet that merges external documents, this way
<xsl:copy-of select="document('snippets.xml')/snippets/xxxx/form"/>
I would like that the XSLT Ant build task rebuilds if the file or any of its dependencies changed.
The current Ant task looks like this
<xslt basedir="xxxx/pages/${doc.locale}"
destdir="xxxx/dir/${doc.locale}"
includes="*.xml"
excludes="snippets.xml"
style="build/xxxx/${doc.locale}/myStyle.xsl">
<param name="lang" expression="${doc.locale}"/>
<xmlcatalog refid="docDTDs"/>
Basically I would like to rebuild if the snippets.xml document is changed.
Ant has the uptodate task to check if a target is up-to-date, file modtime-wise, from a set of source files. I'm not completely clear on what your dependency is since the XSLT task could create multiple files (resulting in multiple targets), or if it creates a single file. One of your comments imply a single file.
The following is one way to use uptodate. You basically use the task to set a property that can then be put in the unless attribute of a target:
<property name="file.that.depends.on.snippets"
location="some/path"/>
<property name="snippets.file"
location="xxxx/pages/${doc.locale}/snippets.xml"/>
<target name="process-snippets"
unless="snippets.uptodate"
depends="snippets-uptodate-check">
<xslt basedir="xxxx/pages/${doc.locale}"
destdir="xxxx/dir/${doc.locale}"
includes="*.xml"
excludes="snippets.xml"
style="build/xxxx/${doc.locale}/myStyle.xsl">
<param name="lang" expression="${doc.locale}"/>
<xmlcatalog refid="docDTDs"/>
</xslt>
</target>
<target name="snippets-uptodate-check">
<uptodate property="snippets.uptodate"
targetfile="$file.that.depends.on.snippets">
<srcfiles dir="xxxx/pages/${doc.locale}"
includes="*.xml"
excludes="snippets.xml"/>
</uptodate>
</target>
The XSLT task should do this for you by default. It has an optional "force" attribute
Recreate target files, even if they
are newer than their corresponding
source files or the stylesheet
which is false by default. So by default, unless you override with the "force" attribute, dependencies are checked by the XSLT task.
Dear, I currently face some problem to retrieve the value of a property setted in a foreach loop. Maybe one of you could help me...
The purpose is to check if one file of a folder has been modified since the corresponding jar has been generated. This way I know if I have to generate the jar again.
What I do is to go through the folder with a foreach loop and if one file match my test, set a property to true.
The problem is that my variable doesn't seems to exist after my loop... Here is a simplified code example that has the same problem:
<target name="target">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
<foreach target="setVar" param="var" list="a,b"/>
<echo>myreturn in target: ${env.myreturn}</echo>
<property name="env.myreturn" value="c"/>
<echo>myreturn in second: ${env.myreturn}</echo>
</target>
<target name="setVar">
<property name="env.myreturn" value="${var}"/>
<echo>myreturn in setVar: ${env.myreturn}</echo>
</target>
The result of this code is:
target:
setVar:
[echo] myreturn in setVar: a
setVar:
[echo] myreturn in setVar: b
[echo] myreturn in target: ${env.myreturn}
[echo] myreturn in second: c
BUILD SUCCESSFUL
It seems that the variable is correctly set as it could be printed in the "setVar" target but no way to retrieve value from the calling target.
I also know it's not possible to assign a value to a property twice. But the problem doesn't even occurs... When it'll be the case I could add a check on the value of the property before to assign it to be sure it is not already initialized...
Do you have a clue on the way I can solve my problem ???
Many thanks in advance for your help :)
Try <for> task from ant-contrib instead of <foreach>. The <for> task takes advantage of Ant macro facility that came later. It works faster and is more flexible than the older <foreach> task. You are in the same project context when using <for>. That means properties set in the loop will be visible outside of the loop. Of course, normal rules for properties apply... you only get to set it once... unless you use <var> task from ant-contrib to overwrite or unset previously set properties.
Ah the joys of Ant hacking.
Not sure about your foreach problem, but can you not use the uptodate task for your requirement?
Even if I don't need it anymore thanks to sudocode, I found a solution for my question. Maybe it could be useful for someone else...
A collegue talked about the "antcallback" target of ant-contrib: it allows to return a result from a called target to the calling one. With a combination of "for" target and "antcallback" it is possible to do what I wanted to do:
<target name="target">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
<for param="file">
<path>
<fileset dir="../myDirectory" includes="**/*" />
</path>
<sequential>
<antcallback target="setVar" return="retValue">
<param name="file" value="#{file}"/>
</antcallback>
</sequential>
</for>
<echo>result: ${retValue}</echo>
</target>
<target name="setVar">
<property name="retValue" value="${file}"/>
</target>
"file" contains the name of the file in the directory. It is given to the called target as parameter with value "#{file}" ('#' necessary due to "for" target implementation).
At the end of the main target, ${retValue} contains the first value setted by the "setVar" target. No error is thrown when trying to set it multiple times, so it's not necessary to check if variable has already been instantiated before to set it in "setVar" target.
The <foreach> task uses the same logic as <antcall> under the covers, and any proprrties set inside a target invoked by <antcall> do not have scope beyond the execution of that target.
In other words, the env.myreturn property that you define in the setVar target is lost as soon as execution of that target completes.
This sort of scripting really isn't what Ant is designed for. The Ant-contrib library tries to patch up the holes, but it's still bending it way out of shape.
If you need to write such scripts, and want to use Ant tasks to achieve them, have a look at Gradle instead. It's a rather lovely blend of Groovy (for scripting) and Ant (for the tasks).
The other approaches here (<for>, <var>, <groovy>properties.put(....)</groovy>, <property>, <antcallback>) did not work with ANT 1.9.4, so I used the file system similar to this (pseudocode):
<target name="outer">
<for> <antcall target="inner" /> </for>
<loadproperties srcfile="tmpfile.properties" />
<echo message="${outerprop}" />
</target>
<target name="inner">
<!-- did not work: -->
<!--
<property name="outerprop" value="true" />
<var name="outerprop" value="true" />
<groovy>properties.put('outerprop','true')</groovy>
<antcallback target="setouterprop" />
-->
<echo message="outerprop=true" file="tmpfile.properties" />
</target>
Maybe the other approaches did not work because of my <antcall>, but I need it here. (outerprop is initially unset)