ANT xmlproperty: demux properties with multiple values - java

I'm using cobertura to calculate test coverage. I want my ant script to echo coverage information about specific packages.
So far, I have:
<target name="coverage-check">
<loadfile property="coveragexml" srcFile="${coverage.report.dir}/coverage.xml">
<filterchain>
<linecontains negate="true">
<contains value="!DOCTYPE"/>
</linecontains>
</filterchain>
</loadfile>
<xmlproperty validate="false">
<string value="${coveragexml}"/>
</xmlproperty>
</target>
This works to load the various cobertura information into ant variables like: coverage.packages.package(name)=lots,of,package,names.
I'd like to find a way to appropriate a specific package name (from one variable) to coverage metrics stored in other variables. If I were using python, lisp, or the like, I'd zip them together, then search. I don't know how to do zipping or searching in ant.

I made an example with use of xmltask
<target name="xml-test">
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask" classpathref="extension.classpath"/>
<property name="xml.file" location="coverage.xml"></property>
<!-- package to search for -->
<property name="packageName" value="foo"></property>
<!-- extract for example line-rate and echo it -->
<xmltask source="${xml.file}">
<copy path="/coverage/packages/package[#name='${packageName}']/#line-rate" property="line-rate" />
</xmltask>
<echo>
Line Rate: ${line-rate}
</echo>
<!-- extract complete xml-block for package ${packageName}
and write it to other file
-->
<xmltask source="${xml.file}">
<copy path="/coverage/packages/package[#name='${packageName}']" buffer="foo-buffer" append="true" />
</xmltask>
<!-- write cut out to file -->
<xmltask dest="foo-coverage.xml">
<insert path="/" buffer="foo-buffer"/>
</xmltask>
</target>
The snipped copied from the source xml can unfortunately not echoed by default, but written to another file.
It's not a solution but an example that may be helps.
I think it would be less work to write a custom ant task your self.

Related

JaCoCo coverage report setups(exclude test classes)

Im generating a jacoco coverage report using the following target :
<target name="report" depends="test">
<!-- This task needs the collected execution data and ... -->
<executiondata>
<file file="${result.exec.file}" />
</executiondata>
<!-- the class files and optional source files ... -->
<structure name="JaCoCo Ant Example">
<classfiles>
<fileset dir="${result.classes.dir}" />
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="${src.dir}" >
<exclude name="**/*Test*.class"/>
</fileset>
</sourcefiles>
</structure>
<!-- to produce reports in different formats. -->
<html destdir="${result.report.dir}" />
<csv destfile="${result.report.dir}/report.csv" />
<xml destfile="${result.report.dir}/report.xml" />
</jacoco:report>
</target>
The problem is that the report takes into account the code from unit tests and I consider this fact a mistake. This way, your line coverage percent and instruction coverage will be artificially increased(because test lines are considered 100% covered) and report correctness is pretty affected. I tried to add this tag
<exclude name="**/*Test*.class"/
under fileset tag, hoping that testClasses will be excluded, but it doesnt works. Do you have any ideas for my problem? I want to avoid programmatically
report modification.
Thanks!
You need to exclude the Test class files from the classfiles fileset:
<structure name="JaCoCo Ant Example">
<classfiles>
<fileset dir="${result.classes.dir}">
<exclude name="**/*Test*.class"/>
</fileset>
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="${src.dir}" />
</sourcefiles>
</structure>
See documentation:
"Note that the classfiles and sourcefiles elements accept any Ant resource collection. Therefore also filtering the class file set is possible and allows to narrow the scope of the report, for example:
<classfiles>
<fileset dir="classes">
<include name="org/jacoco/examples/important/**/*.class"/>
</fileset>
</classfiles>
This is because the actual report is done from the classfiles. The sourcefiles are there to include highlighted source code in the report - as of course the human eye can't read compiled code.
Again from the documentation:
classfiles: Container element for Ant resources and resource
collections that can specify Java class files, archive files (jar,
war, ear etc. or Pack200) or folders containing class files. Archives
and folders are searched recursively for class files.
sourcefiles:
Optional container element for Ant resources and resource collections
that specify corresponding source files. If source files are
specified, some report formats include highlighted source code.
Source files can be specified as individual files or as source
directories.

How do I create a Jar file from my program

I am using eclipse, and I am having difficulty in creating jar files.
So I have codes like getClass().getResource("/imagesfolder/dog.jpg").
How would I create Jar files such that the folder containing my images will also be included. Because error occurs if my Jar file is not in my bin folder with the class files and the imagesfolder.
I tried File>Export>Java>Executable Jar>Save in desktop but when I double click it, it does not start. I tried cmd and it worked but with errors that it can't find imagesfolder.
How will I do a jar file in a separate directory that executes with a double click
I have a class TreeIcon; it uses two images, and I store them in a folder 'images' which is within the package of TreeIcon. For whatever reason, I made the package of TreeIcon spacecheck.images (it could just as easily have been com.mycompany.images). Therefore I used following code to access my images:
expandedIcon = new ImageIcon(TreeIcon.class.getResource("images/Expanded.GIF"));
where the 'images' here is the name of the folder containing just the images, not the one that is part of the package. I.E., in my tree structure for the program source, the images are in a folder named spacecheck.images.images.
Note that there's no slash at the start of my string; this means it references a path relative to that of the class. Putting the slash in front of the spec causes getResource to regard the path as absolute within your jar, so I could also have used the string "/spacecheck/images/images/Expanded.GIF".
ANT is The Way
In eclipse you can use Ant to build your .jar file.
From ant.apache.org
Apache Ant is a Java library and command-line tool whose mission is to
drive processes described in build files as targets and extension
points dependent upon each other. The main known usage of Ant is the
build of Java applications. Ant supplies a number of built-in tasks
allowing to compile, assemble, test and run Java applications. Ant can
also be used effectively to build non Java applications, for instance
C or C++ applications. More generally, Ant can be used to pilot any
type of process which can be described in terms of targets and tasks.
Ant is written in Java. Users of Ant can develop their own "antlibs"
containing Ant tasks and types, and are offered a large number of
ready-made commercial or open-source "antlibs".
Ant is extremely flexible and does not impose coding conventions or
directory layouts to the Java projects which adopt it as a build tool.
Software development projects looking for a solution combining build
tool and dependency management can use Ant in combination with Apache
Ivy.
The Apache Ant project is part of the Apache Software Foundation.
Search with google and you will find many documentation, I will show the basic way to do it.
The Build.xml file
First of all create a new file xml, for example "Build.xml" this will be the file that Ant will read.
The you start writing inside it this:
<?xml version="1.0" encoding="UTF-8"?>
This is the basic line you have always to include.
<project name="NameOfYourProject" default="try_jar" basedir=".">
This (with its closing tag </project> at the end of the file, is the main tag, declaring the name of the project and the first task (default) that will be executed, each task is something Ant will do, and is called "Target", you can create a single target that do everything or various target that do few things each, in this case you can create different "flow-chart" that ant will follow. For example I usually create 3 route for Ant: try_jar that is used just to try if all is working in the jar without doing many things, new_version_jar that is the same of try_jar but will update version number, will sign the jar and some other stuff, and javadoc that creates the javadoc for the project. Il will show you the basic try_jar.
<description>
This buildfile is used to build the jar of the game.
</description>
No need to explanation.
<!-- ================= File and Directory Names ==================== -->
<property name="src" location="${basedir}/src" />
<property name="conf" location="${basedir}/conf" />
<property name="build" location="${basedir}/build" />
<property name="dist" location="${basedir}/dist" />
<property name="app.name" value="MyAppName" />
<property name="dist.jarHome" value="${user.home}/MyApplicationMainFolder" />
<property name="app.version" value="0.2" />
<tstamp />
<property name="jar.name" value="${app.name}_${app.version}.${DSTAMP}.jar" />
<property name="jar.completePath" value="${dist.jarHome}/${jar.name}" />
Here we declare the base properties of the jar, we tell it where the source code is, where the build folder should be and so on. We also choose to put all the app in a folder in the base user home (in mac this is /user/UserName/) and create the name for the file that will include the name (obviously) the version and the time when this jar is created. This avoid duplicated or overriding of files that we may want to keep.
<property name="shared.lib" value="${basedir}/lib" />
Here we must specify the directory in which jar files needed by this plugin to run are stored
<!-- =============== Custom Ant Task Definitions =================== -->
<property name="compile.debug" value="true" />
<property name="compile.deprecation" value="false" />
<property name="compile.optimize" value="true" />
This are configuration params for ant
<!-- ================== External Dependencies ======================= -->
<property name="LWJGL" value="lwjgl.jar" />
<property name="Timer" value="timer.jar" />
<property name="Database" value="hsqldb.jar" />
<property name="Splice" value="jarsplice-0.25.jar" />
Here you must specify your external dependencies (something like easymock or powermock if you want to create a test target.
<!-- ================== Compilation Classpath ======================= -->
<path id="compile.classpath">
<fileset dir="${src}">
<include name="**/*.java" />
<exclude name="**/server/*.java"/>
</fileset>
<fileset dir="${shared.lib}">
<include name="**/*.jar" />
</fileset>
</path>
This is what And (with javac command) will build, you have to specify all the folders you want to build and to add (with <fileset>) any jar that is in the buildpath
<!-- =================== All Target ================================ -->
<!-- ================== Try_jar Target ============================ -->
<target name="try_jar" depends="compile, dist, clean_class_files, run" description="Clean build and dist directories, then compile, create jar and finally run" />
This is our target, as specified in "default" the first line, and will run this. Depends tells Ant what it should do before this target. A you can read it will compile, create the jar (dist), remove the class files, and run it.
<!-- ================== Clean Target ============================== -->
<target name="clean" description="Delete old build and dist directories">
<delete dir="${build}" />
<delete dir="${dist}" />
</target>
This is very clear, before to compile a new version we want to remove any old class file to avoid problems. You may think that this is never called, but pay attention to the dependencies of each target.
<!-- ================== Prepare Target ============================= -->
<target name="prepare" depends="clean">
<mkdir dir="${build}" />
<mkdir dir="${build}/classes" />
<mkdir dir="${build}/lib" />
<copy todir="${build}/lib">
<fileset dir="${shared.lib}" includes="${Timer}, ${LWJGL}, ${Database}" />
</copy>
</target>
This prepare the path, creating new needed folders (like build and build/classes) and adding the external dependencies jars.
<!-- ================== Compile Target =========================== -->
<target name="compile" depends="prepare" description="Compile Java sources">
<mkdir dir="${build}/classes" />
<javac srcdir="${src}" destdir="${build}/classes" encoding="8859_1" debug="${compile.debug}" deprecation="${compile.deprecation}" optimize="${compile.optimize}" source="1.6" target="1.6">
<classpath refid="compile.classpath" />
</javac>
</target>
This is the main compiling target, as you can see it depends on prepare (that depends on clean) so until now we are using all <target> tags.
Ant compile .java files using <javac> tag, that needs to know where the source files are, where to put .class files, the encoding, and the three params we specified earlier.
<!-- =================== Dist Target ================================ -->
<target name="dist" description="Creates Jar archive">
<!-- Create the time stamp -->
<tstamp>
<format property="compile.timestamp" pattern="yyyyMMddHHmm" />
</tstamp>
<!-- update version in manifest -->
<replaceregexp file="${basedir}/manifestClient" match="Implementation-Version: .*" replace="Implementation-Version: ${app.version}.${compile.timestamp}" />
<!-- Create Jar file -->
<jar destfile="${jar.completePath}" manifest="${basedir}/manifest">
<fileset dir="${build}/classes" excludes="**/*.bak" />
<fileset dir="${src}/" excludes="mh/" />
<fileset dir="${shared.lib}/native/macosx" />
<zipfileset src="${shared.lib}/${Timer}" />
<zipfileset src="${shared.lib}/${LWJGL}" />
<zipfileset src="${shared.lib}/${Database}" />
</jar>
</target>
this creates the real jar. <tstamp> and <replaceregexp> are used to update the version in the manifest, you can remove them.
Jar tag will create the .jar file, we specified what files to add in the jar that will be avaible to my classes inside. We have also to specify a manifest that will discuss later.
<!-- =================== Delete .class Target===================== -->
<target name="clean_class_files" description="Delete .class files stored inside build directory and dist folder">
<delete dir="${build}" />
<delete dir="${dist}" />
</target>
This target deletes the two folder used to store .class files (and obviously all the files inside).
<!-- ================== Run Target =============================== -->
<target name="run" description="Run MagicHogwarts">
<java jar="${jar.completePath}" fork="true">
</java>
</target>
The end of our build.xml file, that is the run target that runs the jar.
This is almost what you need to compile and and the correct resources to a jar, if something is not like you are expecting, simply try few times and all will go right.
This is the manifest:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Main-Class: package.to.class.with.main
Built-by: Gianmarco
Implementation-Vendor: Gianmarco
Implementation-Title: Title
I hope this will be useful to you.
I am editing few things to make the post better, but no contents will be different.

How to use Ant to auto renaming output apk file?

I'm currently playing with Ant to do some auto branding work. I modified default build.xml and setup my own target. What I hope to ask is that is there a way in Ant Script that could automatic renaming the apk file just build with the certain name?
I currently has this Ant target setup in my build.xml:
<target name="release-brandA"
depends="default, -set-release-mode, -release-obfuscation-check, -package, -post-package, -release-prompt-for-password, -release-nosign, -release-sign, -post-build"
description="Builds the application in release mode for brandA.">
<delete dir="${res}" />
<copydir dest="${res}" src="${branding}/brandA" forceoverwrite="ture" />
<replaceregexp flags="g" byline="false">
<regexp pattern="import com.arthur.android(.*).R;"/>
<substitution expression="import com.arthur.android.brandA.R;"/>
<fileset dir="src" includes="**/*.java" />
</replaceregexp>
<replaceregexp flags="g" byline="false">
<regexp pattern="package="com.arthur.android(.*)"" />
<substitution expression="package="com.arthur.android.brandA"" />
<fileset dir="" includes="AndroidManifest.xml" />
</replaceregexp>
</target>
Is there a way that I could add some more task, to let the output file just be like brandA.apk?
Thank you!
The final apk filename is actually defined by the property 'out.final.file'
So you could create a new Task that sets this property:
<target name="-set-out-final-file">
<property name="out.final.file" location="${out.absolute.dir}/brandA.apk" />
</target>
Finally, you just need to invoke the -set-out-final-file target before calling the debug or release targets.
Using your release-brandA task, it would become this:
<target name="release-brandA"
depends="default, -set-out-final-file, -set-release-mode, -release-obfuscation-check...
Here I found more better explanation and more suitable way to override release target.
Please refer to section:
<target
name="release"
depends="custom-set-release-mode, android_rules.release" />
Its very simple.Refer this link [1]: https://ant.apache.org/manual/running.html
So in the above case,we need to run it like this,
ant debug -Dout.final.file=brandA.apk
Thats it.

is there a way to set ant -verbose inside build.xml?

I would like to get verbose console output while building from eclipse and hudson.
There seems to be no verbose property for <target> and <project> and it seems very wrong to call <exec> on ant from inside the script just to pass the verbose prop.
Is there a better way?
You could use Ant's <record> task (http://ant.apache.org/manual/Tasks/recorder.html) to get verbose logging to a file. If this task is defined early in the build file, you should get logging for all build tasks. You could also start and stop the recorder anywhere in your build file. This could, for example, allow you to not log the output of some task that you do not want to see in the log file.
Here's an example of a simple build file that uses the <record> task:
<?xml version="1.0" encoding="UTF-8"?>
<project default="all" basedir=".">
<record name="build.log" loglevel="verbose" action="start" />
<target name="all">
<path id="all.files">
<fileset dir="." includes="**/*" />
</path>
<property name="files" refid="all.files" />
<echo level="verbose">files=${files}</echo>
</target>
</project>
It will be an eclipse External Tools Configuration parameter (under Run -> External Tools). Please see the screenshot below:

How to use wildcard in Ant's Available command

I'm using an Ant build script to collate my Eclipse-based application for distribution.
One step of the build is to check that the correct libraries are present in the build folders. I currently use the Ant command for this. Unfortunately, I have to amend the script each time I switch to a new Eclipse build (since the version numbers will have updated).
I don't need to check the version numbers, I just need to check that the file's there.
So, how do I check for:
org.eclipse.rcp_3.5.0.*
instead of:
org.eclipse.rcp_3.5.0.v20090519-9SA0FwxFv6x089WEf-TWh11
using Ant?
cheers,
Ian
You mean, something like (based on the pathconvert task, after this idea):
<target name="checkEclipseRcp">
<pathconvert property="foundRcp" setonempty="false" pathsep=" ">
<path>
<fileset dir="/folder/folder/eclipse"
includes="org.eclipse.rcp_3.5.0.*" />
</path>
</pathconvert>
</target>
<target name="process" depends="checkEclipseRcp" if="foundRcp">
<!-- do something -->
</target>
A slightly shorter and more straightforward approach with resourcecount condition:
<target name="checkEclipseRcp">
<condition property="foundRcp">
<resourcecount when="greater" count="0">
<fileset file="/folder/folder/eclipse/org.eclipse.rcp_3.5.0.*"/>
</resourcecount>
</condition>
</target>
<target name="process" depends="checkEclipseRcp" if="foundRcp">
<!-- do something -->
</target>
The pathconvert task is probably the preferred way to go in most cases. But it creates a little problem when the directory tree is very large and one uses the echoproperties task. With a very large directory tree, the string generated by pathconvert can be huge. Then echoproperties sprays the huge string, making the output more difficult to work with. I use a macrodef on Linux that creates a property set to "1" if there are files in the directory:
<macrodef name="chkDirContents" >
<attribute name="propertyName" />
<attribute name="dirPath" />
<attribute name="propertyFile" />
<sequential>
<exec executable="sh" dir="." failonerror="false" >
<arg value="-c" />
<arg value='fyles=`ls -1 #{dirPath} | head -1` ; if [ "$fyles" != "" ] ; then echo #{propertyName}=1 > #{propertyFile} ; fi' />
</exec>
</sequential>
</macrodef>
<target name="test" >
<tempfile destdir="." property="temp.file" deleteonexit="true" />
<chkDirContents propertyName="files.exist" dirPath="./target_dir" propertyFile="${temp.file}" />
<property file="${temp.file}" />
<echoproperties/>
</target>
Executing the "test" target will generate the following echoproperties line if there are files in the ./target_dir/ directory:
[echoproperties] files.exist=1
What "test" does:
It generates a temporary filename, ${temp.file}, that can later be used as a property file.
It then executes the macrodef, which calls the shell to check the contents of the dirPath directory. If there are any files or directories in dirPath, it assigns the propertyName property a value of 1 in the temporary file. It then reads the file and sets the property given in the file. If the file is empty, no property is defined.
Note that the temporary file could be reused for subsequent calls of the macrodef if desired. On the other hand, of course, once a property is set, it is immutable.

Categories

Resources