Conditional ivysettings file in Ant - ant

I am trying to adapt an Ant build.xml script to be able to work in both our local office network and within AWS. As such, I have to use a different ivysettings.xml file depending on where the build is happening. In both cases the build is kicked off in Jenkins. My idea was to inject a property 'aws=true' when kicked off from AWS and have the property absent otherwise. We are using Ant 1.7.1 local and a newer version in AWS but I'm not able to see which one right now, build.xml should be able to run on both so 1.7.1 is the limit. I could get this upgraded if necessary.
Can someone help me with the syntax required to adapt this piece of the build.xml file for this purpose?
<!-- Resolve dependencies -->
<target name="resolve" description="retrieve dependencies with ivy">
<ivy:settings file="ivysettings.xml"/>
<ivy:retrieve sync="true"/>
</target>
If aws=true I want to use a file called ivysettings_aws.xml, else ivysettings.xml.
Thank you.

I figured this out using ant_contrib.
<!-- Resolve dependencies -->
<target name="resolve" description="retrieve dependencies with ivy">
<if>
<equals arg1="${aws}" arg2="true" />
<then>
<ivy:settings file="ivysettings_aws.xml"/>
</then>
<else>
<ivy:settings file="ivysettings.xml"/>
</else>
</if>
<ivy:retrieve sync="true"/>
</target>
Works.

Would the following be simpler?
<property name="ivy.settings" value="ivysettings.xml"/>
<target name="resolve" description="retrieve dependencies with ivy">
<ivy:settings file="${ivy.settings}"/>
..
</target>
Alternate settings files are then specified as follows:
ant -Divy.settings=ivysettings_aws.xml ..

You should use the new if/unless feature introduced with Ant 1.9.1 to get rid of an additional dependency to antcontrib, which is out of service btw., latest release 1.0b3 nearly 10 years ago.
Something like :
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<!-- Resolve dependencies -->
<target name="resolve" description="retrieve dependencies with ivy">
<ivy:settings file="ivysettings_aws.xml" if:true="${aws}"/>
<ivy:settings file="ivysettings.xml" unless:true="${aws}"/>
<ivy:retrieve sync="true" />
</target>
</project>
Alternatively use the solution proposed by Mark O' Connor, but you need to remember changing the -Divy.settings=... parameter to meet your needs.

Related

Minimum config to use Ivy to set a path in an Ant build?

I want to use an Ant task that is defined in an artifact. The artifact exists in the main Maven repositories and has some dependencies.
I want to use Ivy and Ant to:
Declare the dependency on that artifact and its transitive dependencies, so that they are resolved when the script is run.
Retrieve all the jar files as an Ant path, that I can feed into Ant's taskdef.
Refer to that set of resolved jar files in some other part of the build script.
So far, the documentation I have found does not optimize for this use case. Instead, it suggests to write the files ivy.xml, ivysettings.xml; I don't like that, the dependencies are small enough that I would like to fit everything in a single build script.
Any ideas?
The ivy cachepath task is a resolve task that can be used to create an ANT path. What is perhaps not well known is that this resolving task can also be used inline, in other words, you can specify the dependencies directly without an ivy file.
<ivy:cachepath pathid="tasks.path">
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.4.7" conf="default"/>
</ivy:cachepath>
For a related answer that utilizes an ivy file to manage multiple classpaths:
ivy:retrieve select which ivy.xml file to use
Example
The following example is a little contrived by demonstrates ivy downloading the jar associated with the groovy task. I have also included a utility target that I use to install the ivy jar as well.
build.xml
<project name="demo" default="build" xmlns:ivy="antlib:org.apache.ivy.ant">
<available classname="org.apache.ivy.Main" property="ivy.installed"/>
<!--
============
Main targets
============
-->
<target name="resolve" depends="install-ivy">
<ivy:cachepath pathid="tasks.path">
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.4.7" conf="default"/>
</ivy:cachepath>
</target>
<target name="build" depends="resolve">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="tasks.path"/>
<groovy>
ant.echo "Hello world"
</groovy>
</target>
<!--
==================
Supporting targets
==================
-->
<target name="install-ivy" description="Install ivy" unless="ivy.installed">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.4.0/ivy-2.4.0.jar"/>
<fail message="Ivy has been installed. Run the build again"/>
</target>
<target name="clean" description="Cleanup build files">
<delete dir="${build.dir}"/>
</target>
<target name="clean-all" depends="clean" description="Additionally purge ivy cache">
<ivy:cleancache/>
</target>
</project>

Maven-Ant dependency problem

I am trying to make a build file for a Java project in eclipse using Maven and Ant. However, I can't make the maven-ant-tasks dependency work. Can anybody help me on what to do with this? Maybe my URL and file is wrong. Here it is:
<property name="maven.ant.dir" value="http://apache.hoxt.com/maven/binaries"/>
<property name="maven.ant.file" value="http://apache.hoxt.com/maven/binaries/maven-ant-tasks-2.1.3.jar"/>
Here's how the Maven ANT task works
<project .. xmlns:artifact="antlib:org.apache.maven.artifact.ant">
..
<target name="retrieve" description="Retrieve dependencies using Maven">
<artifact:dependencies filesetId="compile.fileset" useScope="compile">
<pom file="${pom.dir}/pom.xml"/>
</artifact:dependencies>
<copy todir="${retrieve.dir}/compile">
<fileset refid="compile.fileset" />
<mapper type="flatten" />
</copy>
..
Documentation is here

Creating an ear-File with ant

I am new to ant i referred many sites , i need to build.xml for my project which consists
of two modules i have application.xml file which represents corresponding war file
so my question is it sufficient to add the application.xml file
<ear destfile="${dist.dir}/${ant.project.name}.ear" appxml="${conf.dir}/application.xml">
<metainf dir="${build.dir}/META-INF"/>
<fileset dir="${dist.dir}" includes="*.jar,*.war"/>
</ear>
whether this will refer the corresponding war files or i need to compile the whole scenario please let me know. how solve this.
I'm not 100% sure what you're asking.
In order to use the <ear> task, you already need to have compiled the required jars and wars.
If those jars and wars have already been built, you simply refer to them in your <ear> task as you did in your example. The application.xml must already exist before you build your ear. The application.xml doesn't build the jars and wars, you have to do that.
If you haven't already built the wars and jars, you need to do that first. A general outline of a build.xml looks something like this:
<project name="foo" basedir="." default="package">
<!-- Some standard properties you've defined -->
<property name="target.dir" value="${basedir}/target"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<property name="xxx" value="yyy"/>
<!-- Compile properties that allow overrides -->
<property name="javac.nowarn" value="false"/>
<property name="javac.listfiles" value="false"/>
<property name="javac.srcdir" value="source"/>
<property name="javac.distdir" value="${target.dir}/classes"/>
<target name="clean"
description="cleans everything nice and shiny">
<delete dir="${target.dir}"/>
</target>
<target name="compile"
description="Compiles everything">
<mkdir dir="${javac.distdir}"/>
<javac srcdir="${javac.srcdir}"
destdir="${javac.destdir}"
[...]
[...]/>
</target>
<target name="package.jar"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package.jar2"
depends="compile"
description="Package jarfile">
<jar destfile="${target.dir}/jarname2.jar"
[...]
[...]/>
</target>
<target name="package.war"
depends="compile"
description="Package jarfile">
<war destfile="${target.dir}/jarname.jar"
[...]
[...]/>
</target>
<target name="package"
depends="package.jar"
description="Make the ear">
<ear destfile="${target.dir}/earfile.ear"
[...]/>
</target>
</project>
Basically, it consists of a bunch of targets and each target does one task. You can have targets depend upon other targets. For example, this particular build.xml will automatically run the package task. The package task depends upon the package.jar task which depends upon the compile task. Thus, the build.xml file will first call compile, then package.jar, then package.
The important thing to remember is that you don't specify the order of the events. You let Ant figure that out, and you let Ant figure out what you need to do. Let's say you've modified a java source file. Ant knows that it has to recompile only that one file. It also knows that it might have to rebuild the jarfile that contains that classfile. And, it then knows it has to rebuild the ear. Most tasks can figure it out on their own, and you don't do a clean for each build. (You notice that the clean target isn't called by package or compile. You have to call it manually).
The only other thing I recommend is that you try to keep your work area clean. Any files you create should be put into the ${target.dir} directory. That way, when you do a clean, you only have to delete that one directory.
I hope this answer your question.

Location of xsd for ant ivy lib "antlib:org.apache.ivy.ant" for IDE autocomplete with xsd?

I want create Ivy Ant tasks in xml editor in IDE (Intellij iDEA) with autocomplete based on xsd , but I cannot find xsd for register XML namespace xmlns:ivy="antlib:org.apache.ivy.ant"
Where I can find it?
I just copied the ivy jar to INTELLIJ_HOME/lib/ant and now intellij can resolve the ivy tasks.
Or import this ant file to your ant project, its actually the first ivy example in ivy documentation, make sure to always depend on install-ivy target, add your ant file to idea in the ant build window and you dont even have to install ivy and idea recognizes ivy tasks.
<property name="ivy.jar.dir" value="${user.home}/.ivy2/jars" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<property name="ivy.install.version" value="2.2.0" />
<target name="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<available property="INTERN-ivy.jar.exists" file="${ivy.jar.file}"/>
</target>
<target name="download-ivy" depends="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<echo message="downloading and installing ivy"/>
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
<echo message="ivy installed"/>
</target>
<!-- =================================
target: install-ivy
this target is not necessary if you put ivy.jar in your ant lib directory
if you already have ivy in your ant lib, you can simply remove this
target and the dependency the 'go' target has on it
================================= -->
<target name="install-ivy" depends="download-ivy" description="--> install ivy">
<!-- try to load ivy here from local ivy dir, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<echo message="Installing ivy"/>
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
To complete Shalom's answer, the location where to add the ivy.jar for the IntelliJ IDEA Community Edition is INTELLIJ_HOME/lib/ant/lib (one more folder to go).
Maybe it also apply to the full version.
might be, there was no xsd in the past time this discussion started, but at least since may 2011 the ivy scheme is well documented at
http://ant.apache.org/ivy/schemas/ivy.xsd
which is linked right from the documentation in http://ant.apache.org/ivy/
so, to start over using the scheme, you just need:
<?xml version="1.0" encoding="UTF-8"?>
<project name="yourproject"
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
>
<!-- … -->
I guess this discussion might help you. It appears that there is no xsd for the ivy ant tasks, but Eclipse does autocomplete.
yes, no xsd for ivy ant tasks avialable. but i found the way to make autocomplete in Intellij IDEA
in ant build file need to define additional task:
<property name="ivy.jar.dir" value="C:/Apache/apache-ivy-2.2.0/"/>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant">
<classpath>
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</classpath>
</taskdef>
XML plugin for jEdit defines AntCompleteTask (ant task) that produces an xml file called ant-complete.xml. The resulting file looks as follows:
<element-list>
<!-- ... -->
<element name="classpath"
content="(fileset|dirset|extdirs|existing|filelist|pathelement|path)">
<attribute name="id" type="ID" />
<attribute name="location" type="CDATA" />
<attribute name="cache" type="(true|false|on|off|yes|no)" />
<attribute name="refid" type="CDATA" />
<attribute name="description" type="CDATA" />
<attribute name="path" type="CDATA" />
</element>
<!-- ... -->
The generated file may be downloaded as XML plugin archive. Open XML.jar and browse to xml/completion directory. It's syntax is defined in xml-completion-info.dtd.
The task code does not contain an explicit license, but it's at least GPL. Anyway you probably don't need to distribute that task, only to use it and this doesn't require any license.
I can't assess the usability of the resulting xml file, but jEdit uses it for autocompletion.

Using Ivy to download/install ant-contrib, bsf, beanshell, commons-logging

I am building a project using Ant and Ivy. The build.xml file depends on ant-contrib, bean scripting framework, beanshell, and commons-logging.
Ant searches for libraries in several places, including ${user.home}/.ant/lib.
Is there any way in the build.xml file to have these libraries automatically download and install in the ${user.home}/.ant/lib directory if they are not already present, perhaps using Ivy itself?
Thanks, Ralph
The only jar you need in your ant lib is ivy :-)
Declare your dependencies as normal within your ivy.xml file. Make use of a configuration to collectively group the jars associated with ANT tasks:
<configurations>
<conf name="tasks" description="Ant tasks"/>
</configurations>
<dependencies>
<dependency org="ant-contrib" name="cpptasks" rev="1.0b5" conf="tasks->default"/>
<dependency org="junit" name="junit" rev="3.8" conf="tasks->default"/>
..
In your build.xml file you can create a path from this configuration
<ivy:resolve/>
<ivy:cachepath pathid="tasks.path" conf="tasks"/>
<taskdef name="task1" classname="??" classpathref="tasks.path"/>
<taskdef name="task2" classname="??" classpathref="tasks.path"/>
I happened on this question as I was reading the Ivy cachefileset documentation, which states:
Please prefer the use of retrieve +
standard ant path creation, which make
your build more independent from ivy
(once artifacts are properly
retrieved, ivy is not required any
more).
The Ivy cachepath documentation similarly states:
If you want to make your build more
independent from Ivy, you could
consider using the retrieve task. Once
the artifacts are properly retrieved,
you can use standard Ant path creation
which makes Ivy not necessary any
more.
So, it would seem a better answer would be to modify Mark's response to something that uses retrieve in conjunction with ant paths. Something along the lines of the following:
Mark's Response (modified)
<configurations>
<conf name="tasks" description="Ant tasks"/>
</configurations>
<dependencies>
<dependency org="ant-contrib" name="cpptasks" rev="1.0b5"
conf="tasks->default"/>
<dependency org="junit" name="junit" rev="3.8" conf="tasks->default"/>
..
In your build.xml file you can create a path from this config
<ivy:retrieve conf="tasks"
pattern="${dir.where.you.want.taskdef.jars}/[artifact]-[revision].[ext] />
<path id="tasks.path">
<fileset dir="${dir.where.you.want.taskdef.jars}">
<include name="**/*.jar"/>
</fileset>
</path>
<taskdef name="task1" classname="??" classpathref="tasks.path"/>
<taskdef name="task2" classname="??" classpathref="tasks.path"/>
This would even allow you to move the retrieve task into a separate ant file that deals with dependencies. Thereby, you don't have to rely on ivy after your dependencies are retrieved into their directories.
The intention of ivy is that you use it to pull down your jars (resolve & retrieve). Once you have them in place, you can switch back to using standard Ant.
Note: I would just pull these dependencies into the lib directory. That would simplify the retrieve task:
<ivy:retrieve conf="tasks" />
Also Note: visit the 'Path-like Structures' section of this page for more on "standard ant path creation"
I'd use ant to install everything INTO ant =D
Just use depends="init-ant-contrib, init-ivy"
<!-- ANT-CONTRIB Auto Installer -->
<available property="ant-contrib-exists"
file="${ant.library.dir}/ant-contrib-1.0b3.jar" />
<target name="download-ant-contrib" unless="ant-contrib-exists">
<mkdir dir="${ant.library.dir}" />
<get src="http://downloads.sourceforge.net/project/ant-contrib/ant-contrib/1.0b3/ant-contrib-1.0b3-bin.zip?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fant-contrib%2Ffiles%2Fant-contrib%2F1.0b3%2F&use_mirror=cdnetworks-us-1"
dest="${ant.library.dir}/ant-contrib-1.0b3-bin.zip"
username="true" />
<unzip src="${ant.library.dir}/ant-contrib-1.0b3-bin.zip"
dest="${ant.library.dir}"
overwrite="no" />
<move todir="${ant.library.dir}">
<fileset file="${ant.library.dir}/ant-contrib/*.jar" />
<fileset file="${ant.library.dir}/ant-contrib/lib/*.jar" />
</move>
<delete file="${ant.library.dir}/ant-contrib-1.0b3-bin.zip" />
<delete dir="${ant.library.dir}/ant-contrib" />
</target>
<target name="init-ant-contrib" depends="download-ant-contrib">
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${ant.library.dir}/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
</target>
<!-- IVY Auto Installer -->
<property name="ivy.install.version" value="2.1.0-rc2" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
<property name="ivy.home" value="${user.home}/.ant" />
<property name="ivy.jar.dir" value="${ivy.home}/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<available file="${ivy.jar.file}" property="ivy-exists" />
<target name="download-ivy" unless="ivy-exists">
<mkdir dir="${ivy.jar.dir}" />
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}"
usetimestamp="true" />
</target>
<target name="init-ivy" depends="download-ivy">
<!-- try to load ivy here from ivy home, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar" />
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant"
classpathref="ivy.lib.path" />
</target>
Now that you have ant-contrib & ivy, everything else should be a simple ivy.xml & ivy-resolve away:
<target name="resolve" depends="init-ivy">
<ivy:retrieve />
</target>
I'm sure you can find similar methods of installing whatever ant task you might need.

Resources