Ant Download a Jar at Build - java

I'm trying to integrate forbiddenapis check into my project. I've defined that:
<target name="forbidden-checks" depends="clean, runtime, test">
<ivy:cachepath organisation="de.thetaphi" module="forbiddenapis" revision="2.2" inline="true" pathid="classpath"/>
<taskdef uri="antlib:de.thetaphi.forbiddenapis" classpathref="classpath"/>
<forbiddenapis classpathref="all-lib-classpath" dir="${build.dir}" targetVersion="${javac.version}">
<bundledsignatures name="jdk-unsafe"/>
<bundledsignatures name="jdk-deprecated"/>
<bundledsignatures name="jdk-non-portable"/>
</forbiddenapis>
</target>
all-lib-classpath includes all files to be checked by forbiddenapis plugin. I think that forbiddenapis jar will go into ${build.dir}. However I get that error:
Problem: failed to create task or type forbiddenapis
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.

The files don't get downloaded into your workspace. The cachpath task will do two things, download and cache jars into the default directory "~/.ivy2/cache" and then create an Ant path based on those cached jars.
Secondly, as #Denis Kurochkin pointed out, the task you're using apparently requires a namespace to be declared, not unusual with modern Ant tasks.
Finally I couldn't resist demonstrating how you can also configure your ANT build to install the ivy jar if it is missing, making your build even more stand-alone.
Example
build.xml
<project name="demo" default="forbidden-checks" xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:fa="antlib:de.thetaphi.forbiddenapis">
<available classname="org.apache.ivy.Main" property="ivy.installed"/>
<target name="resolve" depends="install-ivy">
<ivy:cachepath pathid="classpath">
<dependency org="de.thetaphi" name="forbiddenapis" rev="2.2" />
</ivy:cachepath>
<ivy:cachepath pathid="all-lib-classpath">
<dependency .... />
<dependency .... />
<dependency .... />
</ivy:cachepath>
</target>
<target name="forbidden-checks" depends="resolve">
<taskdef uri="antlib:de.thetaphi.forbiddenapis" classpathref="classpath"/>
<fa:forbiddenapis classpathref="all-lib-classpath" dir="${build.dir}" targetVersion="${javac.version}">
<bundledsignatures name="jdk-unsafe"/>
<bundledsignatures name="jdk-deprecated"/>
<bundledsignatures name="jdk-non-portable"/>
</fa:forbiddenapis>
</target>
<target name="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>
</project>

You need to declare namespace for forbiddenapis task from Ivy:
<project xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:fa="antlib:de.thetaphi.forbiddenapis">
...
<fa:forbiddenapis ... >
Or declare task name explicitly:
<taskdef name="forbiddenapis"
classname="de.thetaphi.forbiddenapis.ant.AntTask"
classpath="path/to/forbiddenapis.jar"/>
Anyway look at the documentation https://github.com/policeman-tools/forbidden-apis/wiki/AntUsage

Related

How to get class files even when the build fails with ant

I have a java project with java files more than 2500 and some of them may have compilation issue. I need to generate classfiles and route to a particular folder. Even with some of the compilation error, rest of jave turned to class files, with eclipse.
But I need to compile with build tools like ANT but it stops as build failed.
Hence no classfiles generated. Is there a way to compile and generated when project has some compilation error using ANT. The sample code is like
<?xml version="1.0"?>
<project name="REL854" basedir="." default="compile">
<target name="create" depends="delete">
<mkdir dir="src"/>
</target>
<target name="delete">
<delete dir ="src" />
<echo>exclude not working</echo>
</target>
<target name="copy" depends="create">
<copydir src="C:\ClearCase_Storage\Views\Snapshot\username_view6\opensource\Selenium\REL854\src" dest="C:\Users\username\neon\ANTBuildFor854\build\src" excludes="Samples"></copydir>
<copy todir ="C:\Users\username\neon\ANTBuildFor854\build\lib" overwrite="true">
<fileset dir="C:\ClearCase_Storage\Views\Snapshot\username_view6\opensource\Selenium\REL854\lib" ></fileset>
</copy>
</target>
<target name="compile" depends="copy"></target>
<javac failonerror="false" includeantruntime="false" srcdir="C:\Users\username\neon\ANTBuildFor854\build\src" destdir="C:\Users\username\neon\ANTBuildFor854\build\bin" includes="**/*.java"></javac>
</project>

Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency

I am creating a java agent that will be used to to do some bytecode modification to some classes org.eclipse.jdt.core.JDTCompilerAdapter is one of them. I am using javassit to modify some the execute() method of org.eclipse.jdt.core.JDTCompilerAdapter. So I have included ecj as in my agent project (using gradle)
compile group: 'org.eclipse.jdt.core.compiler' ,name: 'ecj', version :'4.3.1'
As I need to use some classes from ecj.
The goal of the agent is to intercept the calls to execute method, modify the execute method to add some calls to some of my classes in the aim of triggering some processing.
I am testing the agent against a Simple java project with 2 classes. the project is builded with ant and uses JDTCompilerAdapter as a compiler.
Here is the build.xml file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="TestProject">
<property file="build.properties" />
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.7"/>
<property name="source" value="1.7"/>
<path id="PClasspath">
<pathelement location="bin"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="init" name="build">
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="PClasspath"/>
</javac>
</target>
<!--
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_JDT_CORE}" includes="*.jar"/>
</copy>
</target>-->
<target name="build-e" >
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
</target>
The agent is to be used when building a project.
So for testing the agent I use this command:
java -jar agent-wrapper.jar --outdir ./out --exec ./build_wrapper.sh
build_wrapper.sh contains this (I have added ecj dependency so I could compile the project with JDTCompilerAdapter as I have in bulid.xml <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/> :
../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e
The idea is that the agent-wrapper will parse the argument (outdir is used to generate some stuff and exec is a script used to launch a the build of my test project) get the command to be executed from build_wrapper.sh (in this case ../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e) and add it self as java agent to the command.
The problem occurs during the execution of the agent. Here is the output:
java -jar custom-agent.jar --outdir ./out --exec ./build_wrapper.sh [10:18:53]
Picked up JAVA_TOOL_OPTIONS: -javaagent:/Users/dev/TestAgent/project/custom-agent.jar=OUTDIR=/Users/dev/TestAgent/project/./out
objc[30474]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
Buildfile: /Users/dev/TestAgent/project/build.xml
build-e:
init:
[mkdir] Created dir: /Users/dev/TestAgent/project/bin
build:
BUILD FAILED
/Users/dev/TestAgent/project/build.xml:47: The following error occurred while executing this line:
/Users/dev/TestAgent/project/build.xml:32: Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency.
Total time: 2 seconds
abnormal termination, exit code: 1
When I don't use ecj-4.3.1.jar inside my agent project, the build runs well I intercept the call to execute() method but I can't use the other classes from ecj jar.
The show stopper error is "Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency."
First hint at the fault might be found from reading this link
http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-ant_javac_adapter.htm
The second hint might be that one of the jars required for running the JDTCompilerAdapter is missing.
To get the JDTCompilerAdapter to work I copied both the JDTCompilerAdapter.jar and org.eclipse.jdt.core.jar into the ant/lib folder.
There are differences based on version of eclipse and the version of java which are documented in the link mentioned above.

include maven-ant build libs in eclipse java project

I am struggling with maven-ant build with eclipse.
I did work like below steps.
[GUI] new java project
add build.xml in project top folder
run ant file and SUCCEED!
trying to code, but somehow auto completion does not work.(guessing eclipse can not read maven-ant dependency.path)
So I tried.
add ~/.m2/repository in build path as a External class folder - does not work - It looks weird to me to include whole this folder. My current project, I need little libraries, but it has whole libraries that I uses in other projects.
add builders with build.xml like Want an eclipse java project to run ant build files automatically - does not work neither.
How can I add this maven-ant libraries properly? Thanks for sharing your experiences and answers XD
=========== Extra Information ====================
This is my build.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project name="HibernateEx2" default="db" basedir="."
xmlns:artifact="antlib:org.apache.maven.artifact.ant">
<property name="source.root" value="src"/>
<property name="class.root" value="classes"/>
<property name="data.dir" value="data"/>
<artifact:dependencies pathId="dependency.classpath">
<dependency groupId="hsqldb" artifactId="hsqldb" version="1.8.0.10"/>
<dependency groupId="org.hibernate" artifactId="hibernate-core" version="4.3.10.Final">
<exclusion groupId="javax.transaction" artifactId="jta"/>
</dependency>
<!-- 3.2.4.GA - After hibernate4 need upgrade hibernate-tools -->
<dependency groupId="org.hibernate" artifactId="hibernate-tools" version="4.3.1.CR1"/>
<dependency groupId="org.apache.geronimo.specs" artifactId="geronimo-jta_1.1_spec" version="1.1.1"/>
<!-- java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory -->
<dependency groupId="commons-logging" artifactId="commons-logging" version="1.2"/>
<dependency groupId="log4j" artifactId="log4j" version="1.2.17"/>
<!-- java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder -->
<dependency groupId="org.slf4j" artifactId="slf4j-log4j12" version="1.7.12"/>
</artifact:dependencies>
<path id="project.class.path">
<pathelement location="${class.root}"/>
<path refid="dependency.classpath" />
</path>
<!-- Explaining how to use hibernate -->
<taskdef name="hibernatetool"
classname="org.hibernate.tool.ant.HibernateToolTask"
classpathref="project.class.path"/>
<target name="db" description="Run HSQLDB database management UI against the database file -- use when application is not running">
<java classname="org.hsqldb.util.DatabaseManager" fork="yes">
<classpath refid="project.class.path"/>
<arg value="-driver"/>
<arg value="org.hsqldb.jdbcDriver"/>
<arg value="-url"/>
<arg value="jdbc:hsqldb:${data.dir}/music/"/>
<arg value="-user"/>
<arg value="sa"/>
</java>
</target>
<target name="print-classpath" description="Show the dependency class path">
<property name="class.path" refid="dependency.classpath"/>
<echo>${class.path}</echo>
</target>
<!-- Generate java code -->
<target name="codegen" description="Generate Java source from the OR mapping files">
<hibernatetool destdir="${source.root}">
<configuration configurationfile="${source.root}/hibernate.cfg.xml"/>
<hbm2java/>
</hibernatetool>
</target>
<!-- Creating Sub drectories -->
<target name="prepare" description="Set up build structures">
<mkdir dir="${class.root}"/>
<copy todir="${class.root}">
<fileset dir="${source.root}">
<include name="**/*.properties"/>
<include name="**/*.xml"/>
</fileset>
</copy>
</target>
<!-- Creating Schema for mapping files -->
<target name="schema" depends="prepare" description="Generate DB schema from the OR mappinf files">
<hibernatetool destdir="${source.root}">
<configuration configurationfile="${source.root}/hibernate.cfg.xml"/>
<hbm2ddl drop="yes"/>
</hibernatetool>
</target>
<!-- Compile Java -->
<!-- added includeantruntime="false" to javac, since terminal compile warning -->
<target name="compile" depends="prepare">
<javac srcdir="${source.root}" destdir="${class.root}"
debug="on" optimize="off" deprecation="on" includeantruntime="false">
<classpath refid="project.class.path"/>
</javac>
</target>
<target name="ctest" depends="compile">
<java classname="org.owls.ht.CreateTest" fork="true">
<classpath refid="project.class.path"/>
</java>
</target>
</project>
and This is what my project looks like.
src
-- source codes (includes hibernate.cfg.xml)
classes
-- compiled classes
data
-- logs and queries
build.xml
FYI, I am doing this with a book named [[Harness Hibernate]] written by James Elliot from O'reilly.
Thanks again b
For what you are trying to do, you need the filesetId and versionsId="dependency.versions" in your declaration of:
<artifact:dependencies filesetId="dependency.fileset" versionsId="dependency.versions"
Then add a copy task like so:
<copy todir="${lib.dir}">
<fileset refid="dependency.fileset" />
<mapper classpathref="maven-ant-tasks.classpath"
classname="org.apache.maven.artifact.ant.VersionMapper"
from="${dependency.versions}" to="flatten" />
</copy>
The to="flatten" will flaten your dependencies into a single folder, then you can include that folder on the classpath of eclipse project or wherever you need it.

Adding external dependencies to ant project (IDEA Android project)

In the documentation to socket.io-java by nkzawa is mentioned that to add ant dependency should be used next snippet:
<dependency org="com.github.nkzawa" name="socket.io-client" rev="0.1.1-SNAPSHOT">
<artifact name="socket.io-client" type="jar" />
</dependency>
In which file and how I should include it? How I should compile my application after that?
In order to manage dependency with ant you'll need to use Ivy
But I agree with Bart Kiers - switch to Gradle, especially as you're already using IDEA.
The socket.io-client documentation is misleading. ANT has an extension called ivy for performing dependency management, but it is not bundled by default.
Once setup you can list your project's dependencies in an ivy.xml file or within your build.xml using the cachepath task:
<ivy:cachepath pathid="compile.path">
<dependency org="com.github.nkzawa" name="socket.io-client" rev="0.1.1" />
</ivy:cachepath>
I have included a more complete example below. It details how to configure your ANT build to automatically setup ivy.
I am not an android programmer, so not able to recommend the best build tool. What I can say is that adding dependency management to your build process is a very good idea. ANT pre-dates more modern tools like Maven and Gradle that have this feature baked in.
Example
build.xml
<project name="demo" default="build" xmlns:ivy="antlib:org.apache.ivy.ant">
<!--
================
Build properties
================
-->
<available classname="org.apache.ivy.Main" property="ivy.installed"/>
<!--
===========
Build setup
===========
-->
<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.3.0/ivy-2.3.0.jar"/>
<fail message="Ivy has been installed. Run the build again"/>
</target>
<target name="resolve" depends="install-ivy" description="Use ivy to resolve classpaths">
<ivy:cachepath pathid="compile.path">
<dependency org="com.github.nkzawa" name="socket.io-client" rev="0.1.1" />
</ivy:cachepath>
</target>
<!--
===============
Compile targets
===============
-->
<target name="build" depends="resolve" description="Project build logic goes here">
<javac .... classpathref="compile.path">
</javac>
...
</target>
<!--
===============
Clean-up targets
===============
-->
<target name="clean" description="Cleanup build files">
<delete dir="build"/>
</target>
<target name="clean-all" depends="clean" description="Additionally purge ivy cache">
<ivy:cleancache/>
</target>
</project>

How to add Ivy to Ant dynamically

Typically, to make Ivy tasks available to an Ant build, you need to:
Add ivy.jar to ${ANT_HOME}/lib.
Add an xmlns:ivy="antlib:org.apache.ivy.ant" declaration to your build.xml's <project> element.
Add a <taskdef> declaration inside build.xml that reference's the ivy.jar's antlib.xml file where all other tasks are defined.
I'd like to accomplish all of the above except the first step (adding ivy.jar to ${ANT_HOME}/lib). I'd like to have ivy.jar living somewhere inside my project, say, at lib/buildtime/ivy.jar, and somehow reference lib/buildtime/ivy.jar as where Ivy is located.
Is this possible? If so, how? If not, why? Thanks in advance!
The taskdef (step 3) is not required if the ivy jar is located in a standard ANT library directory.
I would recommend including a special "bootstrap" target that will install the ivy jar. Once this is done all other dependencies (including 3rd party ANT tasks) can be downloaded by ivy as a build dependency.
Here is my default build file that demonstrates the concept:
<project name="demo" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="bootstrap" description="Install ivy">
<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.3.0/ivy-2.3.0.jar"/>
</target>
<target name="resolve" description="Use ivy to resolve classpaths">
<ivy:resolve/>
<ivy:report todir='build/ivy-reports' graph='false' xml='false'/>
<ivy:cachepath pathid="compile.path" conf="compile"/>
<ivy:cachepath pathid="test.path" conf="test"/>
</target>
<target name="clean" description="Cleanup build files">
<delete dir="build"/>
</target>
<target name="clean-all" depends="clean" description="Additionally purge ivy cache">
<ivy:cleancache/>
</target>
</project>
Notes:
The "bootstrap" target only needs to be run once on a new development environment. Once installed the ivy jar is available to all future ANT runs.
This example doesn't use "$ANT_HOME/lib" (which you may not have write permissions for). Instead it uses the lesser known "$HOME/.ant/lib" directory which serves the same purpose.

Categories

Resources