ANT- Loading Multiple Java files from Several packages - java

I have several files scattered across several packages. I need to load the file one by one and perform operations using ANT but whenever I try, only one file gets loaded. For ex. I have 2 classes - com.abc.one.One and com.bcd.two.Two . The following script print both file name but only the first file as loaded file in both loop iterations
<target name="build" description="My Task">
<for param="file">
<path>
<fileset dir="C:\workspace\AntTest1" includes="**\*.java" />
</path>
<sequential>
<echo message="#{file}" />
<loadfile property="loadedFile" srcfile="#{file}" />
<echo message="${loadedFile}" />
</sequential>
</for>
</target>
I have tried searching the documentation but could not find the concise explanation on how to use loadfile task. I suspected that this might be because ant uses immutable string but could not get workaround. I tried to split the job by creating new target but that does not help me either. Any help is highly appreciated

Ant property can only be set once, and after it is set, it is immutable.
It has been some time since my Ant days, but perhaps the following solution can work: For each file, make an antcall call, with the file name as parameter. then, in the new target, load the file and perform your task. Notice that antcall can impact severely the runtime performance.

Related

ant uppercase vs lowercase characters in path

I have an ant target that copies a file from one location to another, say it is defined in the build.xml as:
${project}/some-component-ABC/lib/whatever.jar
But on the file system the actual path is
${project}/some-component-abc/lib/whatever.jar
No uppercase ABC in some-component-abc on the fliesystem...
This path will resolve in Windows (7) but not in Linux?
Why?
I'll figure out what to do with it, just wanted some background why the functional difference.
Per the following article: https://ubuntuforums.org/showthread.php?t=1227827
Linux is written in C, which is case sensitive. It makes for faster sorting.
Ant doesn't do anything fancy with paths - it just delegates down to the underlying filesystem. Windows' filesystem is not case-sensitive, while any linux filesystem I can think of is. So, in windows, some-component-abc and some-component-ABC are the same directory, while in linux they would not be.
As others have mentioned, for the most part Ant just stores strings for everything and relies on the OS's filesystem when it actually comes time to perform filesystem operations, so you will run into differences like this when running scripts in Linux vs Windows.
However, Ant does have tasks that manipulate path-like strings, and these can be used to groom references to files prior to using them. Here's an example:
~/test $ ls -1
build.xml
FILE
build.xml:
<project>
<pathconvert property="file">
<fileset dir="${basedir}" includes="file" casesensitive="false" />
</pathconvert>
<echo message="${file}" />
</project>
Output:
[echo] /home/me/test/FILE
Alternative approach (will return a path-like string relative to the fileset's dir attribute):
<project>
<fileset dir="${basedir}" includes="file" casesensitive="false" id="filepath" />
<property name="file" refid="filepath" />
<echo message="${file}" />
</project>
Output:
[echo] FILE

Can I declare and initialize a variable in an Ant script?

In Ant, can I create a target that contains something like a variable that represents a path?
For example, something like the following pseudo target:
<target name="initPath">
Path = "${basedir}/../../myProject/Project/"
</target>
Where Path is my variable and is initializated to specific value.
How can I do this?
Ant build scripts are written in XML. To create a property has to be in XML style, so instead of this:
some_prop="some value"
It is this:
<property name="some_prop" value="some value"/>
Properties can contain periods, and I recommend using them as name separators:
<property name="some.prop" value="some value"/>
How do you declare a constant? Here:
<property name="some.prop" value="some value"/>
That's because once a property is set, it cannot be changed.
This way, you can do something like this:
<property file="${basedir}/build.properties"/>
<property name="some.prop" value="some value"/>
Let's say that the build.properties file contains this line:
some.prop="Some other value"/>
Now, when you run your Ant build file, the value of some.prop will be "Some other value", and the <property name="some.prop" value="some value"/> won't change it. I could even do this:
$ ant -Dsome.prop="A completely different value"
And this value of the some.prop property will override what I have in my build.properties file and what I have in my Ant build file.
This is a very nice feature. It allows me to set a default value that developers can override:
<property name="copy.verbose" value="false"/>
...
<copy todir="${copy.to.dir}"
verbose="${copy.verbose}">
<fileset dir="${copy.from.dir}"/>
</copy>
By default, when my copy task runs, it runs in non-verbose mode which is what I want. However, let's say I am having a few problems with my build, and I want to see exactly what is being copied, I could do this:
$ ant -Dcopy.verbose=true
And, now my copy tasks will show me all the files being copied.
A path is a way to declare something like $CLASSPATH or $PATH in the command line. You can predeclare a path with an id, and then use it later:
<javac destdir="${main.destdir}"
srcdir="${main.srcdir}">
<classpath>
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</classpath>
</javac>
Here I'm adding a classpath. This is using <fileset/> to create a classpath based upon all of the jars in my ${lib.dir} directory.
I can also do this:
<path id="main.classpath">
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</path>
<javac destdir="${main.destdir}"
srcdir="${main.srcdir}"
classpathref="main.classpath"/>
Here, I predeclare my main.classpath and then use that later in my <javac> task.
You should read up on Ant in the on line Ant Manual. There is a semi-decent introduction in the manual which might help clarify a few issues for you.
Here is how you can define a property in Ant script.
Unfortunately it is not a variable, since they are immutable. You can set a value to it, but you cannot change it during your script execution.
Here you can see an example of assigning value to a property.
Update.
You can use path task. For example:
<path id="combinedPath">
<path path="${toString:oldPath}"/>
<path path="my.jar"/>
</path>
<path id="reanamePath">
<path path="${toString:oldPath}"/>
</path>
If you change path in one target you can definitely access it in another one.
Ant has classpath-like support built-in.
In general you wouldn't use a property for this functionality.
Please consider reading the Ant documentation; this is Ant 101 and it'll be quicker in the long run if you spend some time with the docs and figuring out the Ant way of doing things.

What is the difference between the <pathelement> attributes 'path' and 'location' in Ant?

I was running Selenium unit tests in TestNG with the Ant Java task like so:
<java classpathref="runtime.classpath"
classname="org.testng.TestNG"
failonerror="false">
<arg value="-d" />
<arg value="${grid.location}/target/reports" />
<arg value="${lib.location}/testng.xml"/>
</java>
runtime.classpath is a pathlike structure that included <pathelement path="${basedir}/target/classes/" />, which I thought was needed to let TestNG know which classes to run.
<path id="runtime.classpath">
...
<!-- Target classes -->
<pathelement path="${basedir}/target/classes/" />
</path>
However, I kept seeing in the log that TestNG found 0 applicable classes.
I eventually got some help from a colleague and it appears this was the key change:
<path id="runtime.classpath">
...
<!-- path attribute changed to location -->
<pathelement location="${basedir}/target/classes/" />
</path>
This also pulls in the test classes correctly:
<java classpathref="runtime.classpath"
classname="org.testng.TestNG"
failonerror="false">
<arg value="-d" />
<arg value="${grid.location}/target/reports" />
<arg value="${lib.location}/testng.xml"/>
<classpath>
<pathelement location="${basedir}/target/classes/" />
</classpath>
</java>
What is the difference between the path and location attributes? I've looked at Writing a Simple Buildfile (specifically the Path-like Structures section), but in that manual it looks to me like location is more specific than path. That doesn't appear to be the case empirically, but I can't quite figure out why.
It looks like the difference between path and location is many entries vs one. A location is a file or directory, a path can be a list.
From the manual
The location attribute specifies a single file or directory relative
to the project's base directory (or an absolute filename), while the
path attribute accepts colon- or semicolon-separated lists of
locations. The path attribute is intended to be used with predefined
paths - in any other case, multiple elements with location attributes
should be preferred.
Note that the JVM used by ant has just about no relation to the JVM used by the java task. By default the environment of ant isn't the same as that of things started with the java task via ant. This is actually helpful when you want to use a different JVM from the one ant wants to use and makes things explicit, helping avoid surprises later on.
Check out the docs for the java task, particularly clonevm
clonevm: If set to true, then all system properties and the
bootclasspath of the forked Java Virtual Machine will be the same as
those of the Java VM running Ant. Default is "false" (ignored if fork
is disabled). since Ant 1.7

Ant task for easier deployment

We have quite a big tree of source code, parts of it are deployed as two separate jar files. We need an easy control of what goes to which jar.
So far we do this by <exclude name="" /> and <include name="" /> tags, but this is quite inconvenient. The best option would be a separate config file with all the packages listed which we could comment out when needed, say with a '#' character.
Does something similar exist or do we have to write a new ant task that reads such a file and runs a <jar> task?
The best option would bee to seperate the code into different modules which can be build on their own (of course with dependencies to each other). Doing this also makes cyclic dependencies obvious and gives you the chance to optimize your code base.
ANT includes and excludes can be managed with external files and referenced in a fileset using includesfile and excludesfile attributes.
includesfile the name of a file; each
line of this file is taken to be an
include pattern.
excludesfile the
name of a file; each line of this file
is taken to be an exclude pattern.
For example:
<jar destfile="${dist}/lib/app1.jar">
<fileset dir=".">
<includesfile name="app1.properties"/>
</fileset>
</jar>
<jar destfile="${dist}/lib/app2.jar">
<fileset dir=".">
<includesfile name="app2.properties"/>
</fileset>
</jar>

Generating a comma-delimited file list with Ant

I'm trying to create a comma-delimited list of files or directories under the current directory. For instance, suppose I have the following folder structure:
Root
-- Directory1
-- Directory2
...
I want to generate a variable or property that contain "Directory1,Directory2." I've tried iterating (using ant-contrib "for" task) over a <dirset dir="." includes="*">, but this generates absolute paths; I've then extracted the file names using the "basename" task, however that in turn generates an output property. Since properties are immutable, what I get in practice is "Directory1,Directory1,..."
Is there a saner way of doing this, or will I have to write a Java extension to do this for me?
The pathconvert task can be used to format a dirset with arbitrary separators:
<dirset id="dirs" dir="." includes="*"/>
<pathconvert dirsep="/" pathsep="," property="dirs" refid="dirs"/>
<echo message="${dirs}"/>
Just confirming Jörn's answer was exactly what I needed (as a starting point) as well.
<dirset id="dirset.sandbox" dir="${sandbox.dir}" includes="*">
<exclude name="output"/>
</dirset>
<pathconvert pathsep=" " property="dirs.sandbox" refid="dirset.sandbox">
<mapper type="flatten"/>
</pathconvert>
<echo message="[*** the sandbox dir list is ${dirs.sandbox} ***]"/>
sandbox.dir is an absolute path similar to /root/build/workspace and contains several subdirectories.
The output is a space-separated list of those directories.

Categories

Resources