I need to write an Ant target that appends together (comma-delimited) a list of '.jar' file names from a folder into a variable, which is later used as input to an outside utility.
I am running into barriers of scope and immutability. I have access to ant-contrib, but unfortunately the version I am stuck with does not have access to the 'for' task. Here's what I have so far:
<target name="getPrependJars">
<var name="prependJars" value="" />
<foreach param="file" target="appendJarPath">
<path>
<fileset dir="${project.name}/hotfixes">
<include name="*.jar"/>
</fileset>
</path>
</foreach>
<echo message="result ${prependJars}" />
</target>
<target name="appendJarPath">
<if>
<equals arg1="${prependJars}" arg2="" />
<then>
<var name="prependJars" value="-prependJars ${file}" />
</then>
<else>
<var name="prependJars" value="${prependJars},${file}" />
</else>
</if>
</target>
It seems that 'appendJarPath' only modifies 'prependJars' within its own scope. As a test, I tried using 'antcallback' which works for a single target call, but does not help me very much with my list of files.
I realize that I am working somewhat against the grain, and lexical scope is desirable in the vast majority of instances, but i really would like to get this working one way or another. Does anybody have any creative ideas to solve this problem?
You might be able to use the pathconvert task, which allows you to specify the separator character as comma.
<target name="getPrependJars">
<fileset id="appendJars" dir="${project.name}/hotfixes">
<include name="*.jar" />
</fileset>
<pathconvert property="prependJars" refid="appendJars" pathsep="," />
<echo message="prependJars: ${prependJars}" />
</target>
I'd simply write a custom task in Java that (1) takes the folder name, (2) assembles the result string and (3) stores it to the ${prependJars} property.
In ant you just define the task (taskdef) and use like all other tasks afterwards.
I did it once when I was faced with a simliar problem and found that it was very, very easy.
Here's the tutorial.
If a system path format is useful to you, you can use the following:
<target name="getPrependJars">
<path id="prepend.jars.path">
<fileset dir="${project.name}/hotfixes">
<include name="*.jar"/>
</fileset>
</path>
<property name="prependJars" value="${toString:prepend.jars.path}" />
<echo message="result ${prependJars}" />
</target>
Related
I am signing my jars using following ant commands.
<signjar alias="${alias}" keypass="${keypass}"
storepass="${storepass}"
keystore="${keystorefile}"
signedjar="${dist.dir}/${jar.signed.fileName}"
lazy="true">
<fileset dir="${dist.dir}">
<include name="*.jar" />
<include name="lib/*.jar" />
</fileset>
</signjar>
For single file it is fine that I can change the name of the jars file after signing it,
but when I have multiple jars the above line is not useful, what i am trying to accomplish is ,
for example
If the unsigned jar file name is ab.jar after signing it I want to prependSigned_to it's name likeSigned_ab.jar` and so on for all the jars i have in my fileset.
Can anyone tell me how to do that ?
You can use the ant jar command/task like below in your build script :
<jar basedir="bin" destfile="Signed_${jar-name}.jar">
btw, you missed to type the command you're using, in your question.
The signjar task can take a mapper defining how to translate the input file name into an output file name:
<signjar alias="${alias}" keypass="${keypass}"
storepass="${storepass}"
keystore="${keystorefile}"
destdir="${dist.dir}"
lazy="true">
<fileset dir="${dist.dir}">
<include name="*.jar" />
<include name="lib/*.jar" />
<!-- since we're dumping signed JARs in the same dir as the source
ones, we need to prevent already-signed JARs from being signed
again. A better approach might be to put the Signed_* JARs in
a different directory -->
<exclude name="**/Signed_*" />
</fileset>
<regexpmapper handledirsep="yes"
from="^(.*?)/([^/]*)$$" to="\1/Signed_\2" />
</signjar>
May be you can write couple of macros & call 'signJarsParallel' macro once for every directory for which you want to sign jars.
This is not tested code. You can give it a try. It makes use running tasks parallely & hence increasing speed & signs to temporary-prefixed name you want :
<macrodef name="signMyJars">
<element name="myJar" implicit="true"/>
<sequential>
<signjar alias="${alias}" keypass="${keypass}"
storepass="${storepass}"
keystore="${keystorefile}"
lazy="true">
<myJar/>
</signjar>
</sequential>
</macrodef>
Call only below macro inside your ant target.
<macrodef name="signJarsParallel">
<attribute name="dirName"/>
<sequential>
<for param="file" parallel="true" threadCount="5">
<path>
<fileset dir="#{dirName}">
<include name="*.jar"/>
<include name="lib/*.jar"/>
</fileset>
</path>
<signMyJars>
<fileset file="Signed_#{file}.jar"/>
</signMyJars>
</for>
</sequential>
</macrodef>
I am looping list of files inside base directory using for of Ant-Contrib library. I want to get the part of file path after base directory but without filename.
For example my base Directory is : C:\projects\Dev\Main\Sample Game\js
I have lot of js scripts and inside this folder and subfolders name like
C:\projects\Dev\Main\Sample Game\js\simple\welcome\ss.js
C:\projects\Dev\Main\Sample Game\js\hard\welcome\cc.js
C:\projects\Dev\Main\Sample Game\js\easy\welcome\ee.js
I want to get only \simple\welcome\. I am using the below code.
http://pastebin.com/TpqXBb27
<for param="filename">
<path id="project.fileset">
<fileset dir="${basedir}/js" includes="/*">
<include name="**/*.js" />
</fileset>
</path>
<sequential>
<basename property="file.#{filename}" file="#{filename}"/>
<propertyregex property="currentdirectory"
input="#{filename}"
regexp="${basedir}/js//([^//]*)//${file.#{filename}}"
select="\1"
casesensitive="false"
override="true" />
<echo message="FullPath:#{filename}" />
<echo message="Directory:${currentdirectory}" />
</sequential>
</for>
I don't know what regex I should provide there... I tried with regex ${basedir}/js//([^//]*)//${file.#{filename}}, but getting the below error
java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence near index 3
C:\projects\Dev\Main\Sample Game\js\simple\welcome\ss.js
Please give some suggestion for this regex
This sounds like more of a job for pathconvert rather than propertyregex
<for param="filename">
<path id="project.fileset">
<fileset dir="${basedir}/js" includes="/*">
<include name="**/*.js" />
</fileset>
</path>
<sequential>
<basename property="file.#{filename}" file="#{filename}"/>
<!-- dirname strips off the trailing file name, leaving the full dir -->
<dirname property="dir.#{filename}" file="#{filename}"/>
<pathconvert property="currentdirectory.#{filename}">
<file file="${dir.#{filename}}" />
<!-- pathconvert strips off the leading ${basedir}/js -->
<map from="${basedir}/js" to="" />
</pathconvert>
<echo message="FullPath:#{filename}" />
<echo message="Directory:${currentdirectory.#{filename}}" />
</sequential>
</for>
The problem is that you are on a PC, and when you use ${basedir}, it's giving you the ${basedir} with backward Windows slashes for directory separators. The <fileset/> is doing the same.
I ran into this very same situation, and I had to first do a regexreplace on my path, then do my substitution. Here's the code directly from my project:
<var name="dest.name" unset="true"/>
<var name="file.lastmodified" unset="true"/>
<var name="file.type" unset="true"/>
<file.mdate file="#{file}"
property="file.lastmodified"/>
<propertyregex property="file"
input="#{file}"
regexp="\\"
replace="/"
override="true"
defaultvalue="#{file}"/>
<propertyregex property="dest.name"
input="${file}"
regexp="^${fileset}/"
replace=""
override="true"/>
Note that I now have to use <var/> to unset the properties, so I can use them over and over in my <for> loop:
The first regexreplace will change
C:\projects\Dev\Main\Sample Game\js\simple\welcome\ss.js
to
C:/projects/Dev/Main/Sample Game/js/simple/welcome/ss.js
From there, you can use the basedir task to remove the script. Then, you just need to for the /js/ directory.
<regexreplace property="currentdirectory"
file="#{file}"
regex=".*/js/(.*)"
select="\1"
override="true"/>
How can I create a dynamic list of files in Ant, then save this list for later use in the build process? What I am thinking of is something like an immutable Fileset. Filelist won't work since it doesn't accept wildcards.
In other words, I want to create a list of files based on include/excludes wildcards that does not change once it's created. That is, even if more files are added later that pass the inclusion/exclusion rules -- I want to preserve the initial Fileset result (specifically for deletion later in the build process). Is this possible?
Well, here's what I came up with. Store fileset to property using pathconvert. Then iterate over files later in the build, doing whatever you need to with them. In my case, deleting them.
<macrodef name="storeBuildState">
<sequential>
<fileset dir="${build.dir}" id="current.fileset">
<include name="**/*.jar" />
</fileset>
<pathconvert pathsep="," property="current.fileset.prop" refid="current.fileset"/>
</sequential>
</macrodef>
<macrodef name="deleteStoredBuildState">
<sequential>
<for list="${current.fileset.prop}" param="file">
<sequential>
<delete file="#{file}" verbose="true" />
</sequential>
</for>
</sequential>
</macrodef>
I am trying to write a build script for a REST service which sits on top of our existing business logic layer, however, I only want to include the minimal amount of sources to keep the service small and only contain what it absolutely needs.
Below is my current compile target. I am able to either include everything or nothing. I assume I am making a simple mistake I can't seem to spot or find online.
<target name="compile">
<mkdir dir="${build.classes.dir}"/>
<javac source="1.6"
target="1.6"
encoding="UTF-8"
debug="true"
debuglevel="lines,vars,source"
srcdir="${basedir}"
destdir="${build.classes.dir}"
includeAntRuntime="false">
<src>
<dirset dir="${src.eai.dir}" errorOnMissingDir="true">
<include name="common/vo/MyPojo.java"/>
<include name="common/SomeException.java"/>
</dirset>
<dirset dir="${src.ets.dir}" errorOnMissingDir="true">
<include name="common/vo/AnotherPojo.java" />
<include name="price/vo/YetAnotherPojo.java" />
<include name="price/vo/OneMorePojo.java" />
</dirset>
<dirset dir="${src.java.dir}" errorOnMissingDir="true">
<include name="java"/>
</dirset>
</src>
<!-- this line ignores everything, without it it includes everything -->
<exclude name="**/*.java"/>
<classpath refid="classpath"/>
</javac>
</target>
Is there a way to only include the files specified above?
In place of exclude, try include and list your java files separated with comma(,) e.g:
<include name="common/vo/MyPojo.java,common/SomeException.java,common/vo/AnotherPojo.java,price/vo/YetAnotherPojo.java" />
Don't set both the srcdir attribute and the nested <src> element, as I imagine Ant is simply combining the two.
I have a target which has several copy tasks; It basically copies the common jars to our set of applications from a centralized location to the lib folder of the application.
Seeing as this is a regular copy task a jar will be copied only if it is newer than the one currently in the lib folder.
This is the relevant part in the build.xml:
<target name="libs"/>
<copy file=... />
<copy file=... />
<copy file=... />
<antcall target="clean_compiled_classes"/>
</target>
<target name="clean_compiled_classes" if="anyOfTheLibsWereCopied">
<delete .../>
</target>
I'm looking for a way to set the anyOfTheLibsWereCopied property before the ant call in the libs target based on whether or not any of the files has been actually changed.
Thanks,
Ittai
I would advise having a look at the Uptodate task. I have never used it before but I guess what you are trying to do will be implemented along the following lines:
<target name="libs"/>
<uptodate property="isUpToDate">
<srcfiles dir="${source.dir}" includes="**/*.jar"/>
<globmapper from="${source.dir}/*.jar" to="${destination.dir}/*.jar"/>
</uptodate>
<!-- tasks below will only be executed if
there were libs that needed an update -->
<antcall target="copy_libs"/>
<antcall target="clean_compiled_classes"/>
</target>
<target name="copy_libs" unless="isUpToDate">
<copy file=... />
<copy file=... />
<copy file=... />
</target>
<target name="clean_compiled_classes" unless="isUpToDate">
<delete .../>
</target>
Your other option would be to implement your own ant task that does what you want. This would require a bit more work though.