Sanity4J Ant Task user guide

Intoduction

Sanity4J has been created in order to simplify running ad-hoc static code analysis over Java projects using a standardised set of rules types and priorities.

Various tools are used to conduct the analysis, each with their own set of requirements. Both bytecode and source code are analysed, to ensure the best chance of finding potential problems. Sanity4J presents a single interface to run all the tools and produce a combined report presenting all the findings in a easily accessible manner.

Running the Ant task

To run the Ant task, you will need the following:

  • The Sanity4J jar file; sanity4j.jar
  • Apache Ant 1.6.5+
  • JDK/JRE 1.8.x+
  • A directory containing the tools needed by Sanity4J (see parameters below).
  • A built project, optionally with a JaCoco coverage data file.
  • Depending on the size of your project, you may need to increase the memory available to Ant. This can be set using the ANT_OPTS environment variable, e.g. "set ANT_OPTS=-Xmx512M" to use 512MB max heap.

Ant Macros

There are two Ant macros that can be run.

  • sanity4j - The "santy4j" macro supports multiple JaCoCo coverage datafiles by merging them. This can also be run against a single coverage datafile without merging. Sanity4j will detect whether a merge is required based on the number of supplied datafiles.
  • sanity4j.run - The "sanity4j.run" macro supports only a single JaCoCo coverage datafile without merging. This exists primarily to support backward compatability as Ant nested elements cannot be made optional.

Parameters

AttributeDescriptionRequired
products.dirThe products.dir must point to a directory containing all the tools in use. For example, with a default configuration, these could be spotbugs-3.1.6, pmd-5.0.4, checkstyle-5.6 and jacoco-0.7.9Yes
report.dirThe report output directory.Yes
coverage.data.fileThe location of a coverage data file (e.g. jacoco.exec for JaCoCo) if you want to include unit testing coverage data in your report.No
coverage.merge.data.fileThe location of the merged coverage data file. Must be used in conjunction with a list of coverage.data.files nested elements, see below.No
external.properties.pathThe path location of the sanity4j.properties file. The default is the current directory.No
java.runtimeThe full path to the java run-time to use. If not specified, "java" is used.No
summary.data.fileThe location of a (persistent) summary data file if you want to include trend graphs over time.No
include.tool.outputIf set to "true", the raw tool xml output is also copied into the report directory. This is only useful if there is some other part of your build process that requires it.No

Parameters specified as nested elements

AttributeDescriptionRequired
source.pathThis element accepts nested Paths / FileSets pointing to the location of the target project's source only. If you have multiple source directories contained within a main directory, you can just list the main directory here - the task will search for all source directories.Yes
class.pathThis element accepts nested Paths/FileSets pointing to the location of the target project's built classes/jars only.Yes
library.pathThis element accepts nested Paths / FileSets pointing to the location of jars/classes that the target project depends on. Don't use e.g. an entire local maven repository; only include direct dependencies.No
coverage.data.filesThis element accepts nested Paths / FileSets pointing to the location of coverage data files to be merged.No
configurationsThis element accepts nested "configuration" elements describing the "configuration" file passed to the underlying tools.No

The source / class / library path will accept Filesets or Paths. If there are multiple source / class directories, it is possible to specify a common parent directory and have the tool find all the nested source/class directories.

The products.dir must point to a directory containing all the tools in use. For example, with a default configuration, these could be spotbugs-3.1.6, pmd-5.0.4, checkstyle-5.6 and cobertura-2.0.1.

The configurations element accepts nested "configuration" elements. "configuration" elements have the following attributes:

AttributeDescriptionRequired
toolThe name of the tool for which the configuration is to be specified ("checkstyle", "spotbugs", "pmd")Yes
versionThe version of the tool for which the configuration is to be specified. (If no version is specified this configuration will be used by all versions.)No
configThe configuration to be used. Usually this is the name of a file passed to the command line of the tool to specify the tool specific configuration. However, this parameter is simply substituted as the value of the $sanity4j.tool.tool.config parameter within the $sanity4j.tool.tool.command parameter that is used to specify the command line of the tool. So the value specified, can be any set of options that make sense at the point of substitution within the $sanity4j.tool.toolcommand. The resource can be a file contained within a jar file on the classpath, or an external file in the file system. If the resource is a jar, then the name is compared with the classpath and the full path to the jar is then passed to the tool instead.Yes

Below is a sample XML file with examples for both Ant macros.

<project name="test_sanity4j_ant" default="analyse.test">

    <target name="analyse.test" depends="analyse.single, analyse.multi" />

    <!-- Run the analysis -->
    <target name="analyse.single"
        description="This target runs the QA tools against the given project.
            The project's coverage task should have been run first.">

        <!-- Imports -->
        <typedef
            resource  ="sanity4j-ant.xml"
            classpath ="target/sanity4j-1.8.2-jar-with-dependencies.jar"/>

        <!-- Run the Sanity4J QA task -->
        <sanity4j.run
            products.dir="target/tools"
            report.dir="target/sanity4j-ant-report-single"
            coverage.data.file="target/jacoco.exec">

            <source.path>
               <fileset dir="src/main/java">
                  <include name="**/*.java"/>
               </fileset>
               <fileset dir="src/test/java">
                  <include name="**/*.java"/>
               </fileset>
            </source.path>

            <class.path>
               <path path="target/classes"/>
               <path path="target/test-classes"/>
            </class.path>

            <library.path>
               <path path="target/sanity4j-1.8.2-jar-with-dependencies.jar"/>
            </library.path>

            <configurations>
                <configuration tool="checkstyle" config="local_checkstyle_rules.xml"/>
            </configurations>

         </sanity4j.run>

    </target>


    <!-- Run the analysis -->
    <target name="analyse.multi"
        description="This target runs the QA tools against the given project,
            merging coverage datafiles. The project's coverage task should have been run first.">

        <!-- Imports -->
        <typedef
            resource  ="sanity4j-ant.xml"
            classpath ="target/sanity4j-1.8.2-jar-with-dependencies.jar"/>

        <!-- Run the Sanity4J QA task -->
        <sanity4j
            products.dir="target/tools"
            report.dir="target/sanity4j-ant-report-multi"
            coverage.merge.data.file="target/jacoco.exec">

            <source.path>
               <fileset dir="../sanity4j-test/maven3-multi/child1/src/main/java">
                  <include name="**/*.java"/>
               </fileset>
               <fileset dir="../sanity4j-test/maven3-multi/child1/src/test/java">
                  <include name="**/*.java"/>
               </fileset>
            </source.path>

            <class.path>
               <path path="../sanity4j-test/maven3-multi/child1/target/classes"/>
               <path path="../sanity4j-test/maven3-multi/child1/target/test-classes"/>

               <path path="../sanity4j-test/maven3-multi/child2/target/classes"/>
               <path path="../sanity4j-test/maven3-multi/child2/target/test-classes"/>
            </class.path>

            <library.path>
               <path path="target/sanity4j-1.8.2-jar-with-dependencies.jar"/>
            </library.path>

            <coverage.data.files>
               <path path="../sanity4j-test/maven3-multi/child1/target/jacoco.exec"/>
               <path path="../sanity4j-test/maven3-multi/child2/target/jacoco.exec"/>
            </coverage.data.files>

            <configurations>
                <configuration tool="spotbugs" config="-pluginList local_plugin.jar"/>
                <configuration tool="pmd"      config="local_pmd_rules.xml"/>
            </configurations>

         </sanity4j>

    </target>

</project>