The sensor for the JDepend dependency finder and analysis tool is implemented using the XmlData sensor. It sends Dependency data (documented in Section 25.9, “Dependency”) to the Hackystat server.
The JDepend sensor requires Java 1.5.0 or later and the XmlData sensor.
Follow the instructions in Chapter 2, Client-side configuration: Tool sensor installation to set your Hackystat host and user key.
Follow the instructions for installation of either the Ant or command-line interfaces to the XmlData sensor in Section 26.34, “XmlData”.
To begin, invoke JDepend with its XML output enabled. Example 26.43, “An Ant task for generating JDepend dependency data as the XML file” illustrates an Ant file that runs JDepend over a sample system.
Example 26.43. An Ant task for generating JDepend dependency data as the XML file
<property name="jdepend.dir" location="${build.dir}/jdepend" >
<target name="jdepend.tool" depends="clean, compile"
description="Runs JDepend over the byte code to check dependency.">
<!-- Fail this target if JDepend is not installed. -->
<available file="${env.JDEPEND_HOME}/lib/jdepend-2.9.jar" property="jdepend.available" />
<fail unless="jdepend.available"
message="Error: JDEPEND_HOME not set or jdepend-2.9.jar not found." />
<!-- Run JDepend. -->
<mkdir dir="${jdepend.dir}" />
<jdepend format="xml" outputfile="${jdepend.dir}/jdepend-report.xml">
<exclude name="java.*" />
<exclude name="javax.*" />
<classespath>
<pathelement location="build/classes" />
</classespath>
<classpath location="classes" />
</jdepend>
</target>
The next step is to convert the XML data generated by JDepend into a format acceptable to the XmlData sensor. Example 26.44, “The jdepend2hackystat.xsl file” shows the contents of a file called jdepend2hackystat.xsl, which extracts the dependency data from the JDepend dependency report and puts it into a form appropriate for the XmlData sensor.
Example 26.44. The jdepend2hackystat.xsl file
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:param name="path" />
<xsl:template match="JDepend">
<xmldata>
<xsl:for-each select="./Packages/Package">
<xsl:if test="count(error) = 0">
<xsl:variable name="packagename" select="@name" />
<xsl:variable name="afferentCouplings" select="./Stats/Ca" />
<xsl:variable name="efferentCouplings" select="./Stats/Ce" />
<xsl:variable name="cycles" select="count(//Cycles/Package[@Name=$packagename]/Package)" />
<xsl:variable name="outboundpackages">
<xsl:for-each select="./DependsUpon/Package">
<xsl:variable name="attribute_name" select="@name" />
<xsl:variable name="attribute_value" select="." />
<xsl:value-of select="concat(., ',')" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="outbound">
<xsl:variable name="fullength" select="string-length($outboundpackages)" />
<xsl:choose>
<xsl:when test="$fullength>'0'">
<xsl:variable name="length" select="$fullength - 1" />
<xsl:variable name="lastchar" select="substring($outboundpackages,$fullength, 1)" />
<xsl:choose>
<xsl:when test="$lastchar = ','">
<xsl:value-of select="substring($outboundpackages, 1, $length)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$outboundpackages" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="inboundpackages">
<xsl:for-each select="./UsedBy/Package">
<xsl:variable name="attribute_name" select="@name" />
<xsl:variable name="attribute_value" select="." />
<xsl:value-of select="concat(., ',')" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="inbound">
<xsl:variable name="fullength" select="string-length($inboundpackages)" />
<xsl:choose>
<xsl:when test="$fullength>'0'">
<xsl:variable name="length" select="$fullength - 1" />
<xsl:variable name="lastchar" select="substring($inboundpackages,$fullength, 1)" />
<xsl:choose>
<xsl:when test="$lastchar = ','">
<xsl:value-of select="substring($inboundpackages, 1, $length)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$inboundpackages" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="suffix" select="translate($packagename , '.', '\')" />
<xsl:variable name="full_path" select="concat($path,'\',$suffix)" />
<entry sdt="Dependency" granularity="package" tool="JDepend" path="{$full_path}"
package="{$packagename}" outbound="{$outbound}" inbound="{$inbound}"
afferentCouplings="{$afferentCouplings}" efferentCouplings="{$efferentCouplings}"
cycles="{$cycles}" />
</xsl:if>
</xsl:for-each>
</xmldata>
</xsl:template>
</xsl:stylesheet>
Example 26.45, “The jdepend.xslt Ant task” shows a simple Ant task that uses the jdepend2hackystat.xsl file listed above to generate a file called hackystat.xml, containing the coverage data in a form suitable for input to the XmlData sensor.
Example 26.45. The jdepend.xslt Ant task
<target name="jdepend.hackystat" depends="jdepend.report"
description="Transforms the XML file produced by JDepend into the hackystat XML data format.">
<xslt style="${lib.dir}/jdepend/jdepend2hackystat.xsl" in="${jdepend.dir}/jdepend-report.xml"
out="${jdepend.dir}/hackystat.xml">
<param name="path" expression="${src.dir}" />
</xslt>
</target>
Example 26.46, “The hackystat.xml file produced by the jdepend2hackystat.xsl transform” shows the data file produced by this Ant task for a simple Java system.
Example 26.46. The hackystat.xml file produced by the jdepend2hackystat.xsl transform
<?xml version="1.0" encoding="UTF-8"?> <xmldata> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\basics" package="edu.hawaii.senin.iclouds.basics" outbound="edu.hawaii.senin.iclouds.simple,org.jdom,org.jdom.input,org.junit" inbound="edu.hawaii.senin.iclouds.simple,edu.hawaii.senin.iclouds.util,edu.hawaii.senin.iclouds.view" afferentCouplings="3" efferentCouplings="4" cycles="3"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\controller" package="edu.hawaii.senin.iclouds.controller" outbound="edu.hawaii.senin.iclouds.simple,edu.hawaii.senin.iclouds.util,edu.hawaii.senin.iclouds.view" inbound="edu.hawaii.senin.iclouds.main,edu.hawaii.senin.iclouds.simple" afferentCouplings="2" efferentCouplings="3" cycles="2"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\main" package="edu.hawaii.senin.iclouds.main" outbound="edu.hawaii.senin.iclouds.controller,edu.hawaii.senin.iclouds.simple,edu.hawaii.senin.iclouds.view" inbound="" afferentCouplings="0" efferentCouplings="3" cycles="3"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\plotting" package="edu.hawaii.senin.iclouds.plotting" outbound="org.jdom,org.jdom.input" inbound="" afferentCouplings="0" efferentCouplings="2" cycles="0"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\simple" package="edu.hawaii.senin.iclouds.simple" outbound="edu.hawaii.senin.iclouds.basics,edu.hawaii.senin.iclouds.controller,org.apache.commons.math.random,org.jdom,org.jdom.input,org.junit" inbound="edu.hawaii.senin.iclouds.basics,edu.hawaii.senin.iclouds.controller,edu.hawaii.senin.iclouds.main,edu.hawaii.senin.iclouds.view" afferentCouplings="4" efferentCouplings="6" cycles="2"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\statistics" package="edu.hawaii.senin.iclouds.statistics" outbound="org.apache.commons.math.util,org.junit" inbound="" afferentCouplings="0" efferentCouplings="2" cycles="0"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\util" package="edu.hawaii.senin.iclouds.util" outbound="edu.hawaii.senin.iclouds.basics" inbound="edu.hawaii.senin.iclouds.controller" afferentCouplings="1" efferentCouplings="1" cycles="4"/> <entry sdt="Dependency" granularity="package" tool="JDepend" path="H:\home\senin\projects\iclouds\src\edu\hawaii\senin\iclouds\view" package="edu.hawaii.senin.iclouds.view" outbound="edu.hawaii.senin.iclouds.basics,edu.hawaii.senin.iclouds.simple,net.miginfocom.swing" inbound="edu.hawaii.senin.iclouds.controller,edu.hawaii.senin.iclouds.main" afferentCouplings="2" efferentCouplings="3" cycles="3"/> </xmldata>
Example 26.47, “XmlData CLI invocation” shows a simple command line invocation of the XmlData sensor and the resulting output.
Example 26.47. XmlData CLI invocation
H:\home\senin\projects\iclouds>java -jar "C:\Documents and Settings\Administrator\.hackystat\sensor.xmldata-cli.jar" -file build/jdepend/hackystat.xml -createRunTime runTime -verbose true Verbose mode on: true Runtime name is: runTime, value is: 1170809843486 Sensor enabled: true Processing file: build/jdepend/hackystat.xml Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\basics, outbound=edu.hawaii.senin.iclouds.simple,org.jdom,org.jdom.input,org.junit, inboun d=edu.hawaii.senin.iclouds.simple,edu.hawaii.senin.iclouds.util,edu.hawaii.senin.iclouds.view, runTime=1170809843486, pM ap=000800006cycles00001300017efferentCouplings00001400017afferentCouplings00001300007package00031edu.hawaii.senin.icloud s.basics] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\controller, outbound=edu.hawaii.senin.iclouds.simple,edu.hawaii.senin.iclouds.util,edu.haw aii.senin.iclouds.view, inbound=edu.hawaii.senin.iclouds.main,edu.hawaii.senin.iclouds.simple, runTime=1170809843486, pM ap=000800006cycles00001200017efferentCouplings00001300017afferentCouplings00001200007package00035edu.hawaii.senin.icloud s.controller] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\main, outbound=edu.hawaii.senin.iclouds.controller,edu.hawaii.senin.iclouds.simple,edu.haw aii.senin.iclouds.view, inbound=, runTime=1170809843486, pMap=000800006cycles00001300017efferentCouplings00001300017affe rentCouplings00001000007package00029edu.hawaii.senin.iclouds.main] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\plotting, outbound=org.jdom,org.jdom.input, inbound=, runTime=1170809843486, pMap=00080000 6cycles00001000017efferentCouplings00001200017afferentCouplings00001000007package00033edu.hawaii.senin.iclouds.plotting] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\simple, outbound=edu.hawaii.senin.iclouds.basics,edu.hawaii.senin.iclouds.controller,org.a pache.commons.math.random,org.jdom,org.jdom.input,org.junit, inbound=edu.hawaii.senin.iclouds.basics,edu.hawaii.senin.ic louds.controller,edu.hawaii.senin.iclouds.main,edu.hawaii.senin.iclouds.view, runTime=1170809843486, pMap=000800006cycle s00001200017efferentCouplings00001600017afferentCouplings00001400007package00031edu.hawaii.senin.iclouds.simple] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\statistics, outbound=org.apache.commons.math.util,org.junit, inbound=, runTime=11708098434 86, pMap=000800006cycles00001000017efferentCouplings00001200017afferentCouplings00001000007package00035edu.hawaii.senin. iclouds.statistics] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\util, outbound=edu.hawaii.senin.iclouds.basics, inbound=edu.hawaii.senin.iclouds.controlle r, runTime=1170809843486, pMap=000800006cycles00001400017efferentCouplings00001100017afferentCouplings00001100007package 00029edu.hawaii.senin.iclouds.util] Sending to sensorshell: Dependency [add, tool=DependencyFinder, granularity=package, path=H:\home\senin\projects\iclouds \src\edu\hawaii\senin\iclouds\view, outbound=edu.hawaii.senin.iclouds.basics,edu.hawaii.senin.iclouds.simple,net.miginfo com.swing, inbound=edu.hawaii.senin.iclouds.controller,edu.hawaii.senin.iclouds.main, runTime=1170809843486, pMap=000800 006cycles00001300017efferentCouplings00001300017afferentCouplings00001200007package00029edu.hawaii.senin.iclouds.view]
Example 26.48, “The jdepend.sensor Ant task” shows a simple Ant task that invokes the XmlData sensor and sends the Dependency data to the HackyStat server.
Example 26.48. The jdepend.sensor Ant task
<target name="jdepend.sensor" depends="jdepend.hackystat"
description="Sends the Hackystat data to the server.">
<available classname="org.hackystat.sensor.dependencyfinder.DependencyFinderSensor"
property="dependencyfinder.sensor.available" />
<fail unless="dependencyfinder.sensor.available"
message="Error: DependencyFinder sensor not installed." />
<taskdef name="hacky-xmldata" classname="org.hackystat.sensor.xmldata.XmlDataSensor" />
<hacky-xmldata verbose="${hackystat.verbose.mode}" createRunTime="runTime">
<fileset file="${jdepend.dir}/hackystat.xml" />
</hacky-xmldata>
</target>
The first step in troubleshooting your sensor installation is to verify that your Hackystat host and key settings are valid and that you can contact the Hackystat server, as described in Section 2.4, “HackyInstaller GUI: Setting and verifying the Hackystat host and user key”
If you find that you need to modify the XSL stylesheet in some manner, you may find it useful to read the Developer Guide section called Section 17.3, “Designing a sensor using the XmlData sensor”, or the XmlData sensor documentation at Section 26.34, “XmlData”.
The XmlData sensor writes out a file called XmlData.0.log to the .hackystat/logs directory that can be useful in debugging your installation.
If none of the above troubleshooting activities solves your problem, then you should send an email to your Hackystat Administrator to request help. Please include in your email the following information:
The output from 'java -version'.
The output from 'java -jar sensorshell.jar -verify'.
The contents of your sensor.properties file.
The contents of the XmlData.0.log file.
A description of the problem you are having.
To disable XmlData sensor data collection temporarily from Ant or the command-line, invoke HackyInstaller, bring up the XmlData-Ant or XmlData-Cli configuration window, and uncheck the "Enable XmlData sensor" property, and apply the setting. To permanently uninstall the XmlData sensor, press the "Uninstall" button.