26.19. JDepend

26.19.1. Overview

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.

26.19.2. Installation

26.19.2.1. Prerequisites

The JDepend sensor requires Java 1.5.0 or later and the XmlData sensor.

26.19.2.2. Download HackyInstaller and set your Hackystat Host and User Key

Follow the instructions in Chapter 2, Client-side configuration: Tool sensor installation to set your Hackystat host and user key.

26.19.2.3. Configure and install the XmlData sensor

Follow the instructions for installation of either the Ant or command-line interfaces to the XmlData sensor in Section 26.34, “XmlData”.

26.19.2.4. Invoke JDepend and generate its XML file

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>

26.19.2.5. Transform the JDepend XML coverage report into the XmlData sensor input format

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>

26.19.2.6. Run the XSLT processor to generate the XmlData input file

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>

26.19.2.7. Invoke the XmlData sensor on the hackystat.xml file

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]

26.19.2.8. An Ant task to invoke the XmlData sensor on the hackystat.xml file

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>  

26.19.3. Installation troubleshooting

26.19.3.1. Troubleshooting general client-server problems

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”

26.19.3.2. Troubleshooting XSL design problems

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”.

26.19.3.3. Checking client-side logging

The XmlData sensor writes out a file called XmlData.0.log to the .hackystat/logs directory that can be useful in debugging your installation.

26.19.3.4. Submit a trouble report

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.

26.19.4. Uninstallation

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.