donaldp 01/10/16 03:12:23
Modified: docs/manual/OptionalTasks jdepend.html
src/main/org/apache/tools/ant/taskdefs/optional/jdepend
JDependTask.java
Added: src/etc jdepend.xsl
Log:
I've just put together a patch for the JDepend task to use xml
output. A new
attribute "format" has been added that can take either "xml" or "text"
defaulting to the latter. �Appropriate changes have been made to the
documentation, and additionally a .xsl file is attached to
produce html with
a similar style to that of junitreport.
Submitted by: "Rob Oxspring" <[EMAIL PROTECTED]>
Revision Changes Path
1.4 +13 -8 jakarta-ant/docs/manual/OptionalTasks/jdepend.html
Index: jdepend.html
===================================================================
RCS file: /home/cvs/jakarta-ant/docs/manual/OptionalTasks/jdepend.html,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- jdepend.html 2001/09/08 01:05:18 1.3
+++ jdepend.html 2001/10/16 10:12:23 1.4
@@ -16,14 +16,14 @@
<P>Invokes the <a
href="http://www.clarkware.com/software/JDepend.html">JDepend</a> parser.</P>
<P>This parser "traverses a set of Java source file directories and
generates design quality metrics for each Java package".
-It allows to "automatically measure the quality of a design in terms of
its extensibility, reusability, and maintainability to
+It allows to "automatically measure the quality of a design in terms of
its extensibility, reusability, and maintainability to
effectively manage and control package dependencies."</P>
<p>Source file directories are defined by nested
<code><sourcespath></code>, see <a href="#nested">nested elements</a>.</p>
<p>Optionally, you can also set the <code>outputfile</code> name where the
output is stored. By default the task writes its report to the standard
output.</P>
-<p> The task requires at least the JDepend 1.2 version. </p>
+<p> The task requires at least the JDepend 1.2 version. </p>
<P>Note: whereas the JDepend tool can be customized to exclude some
packages, the current jdepend And Task does not have parameters to allow these
exclusions. Read JDepend specific documentation for that purpose.</P>
@@ -41,6 +41,11 @@
<td ALIGN=CENTER VALIGN=TOP>No</td>
</tr>
<tr>
+ <td VALIGN=TOP>format</td>
+ <td VALIGN=TOP>The fomat to write the output in. The default is "text",
the alternative is "xml"</td>
+ <td ALIGN=CENTER VALIGN=TOP>No</td>
+ </tr>
+ <tr>
<td VALIGN=TOP>fork</td>
<td VALIGN=TOP>Run the tests in a separate VM.</td>
<td ALIGN=CENTER VALIGN=TOP>No, default is "off"</td>
@@ -74,8 +79,8 @@
<h3><a name="nested">Nested Elements</a></h3>
-<p><code>jdepend</code> supports two nested elements
<code><classpath></code> and <code><sourcespath></code>,
-that represent <a href="../using.html#path">PATH like structures</a>.</p>
+<p><code>jdepend</code> supports two nested elements
<code><classpath></code> and <code><sourcespath></code>,
+that represent <a href="../using.html#path">PATH like structures</a>.</p>
<p><code><sourcespath></code> is used to define the paths of the
source code to analyze.</p>
@@ -96,7 +101,7 @@
<blockquote>
<pre>
-<jdepend outputfile="docs/jdepend.txt" fork="yes">
+<jdepend outputfile="docs/jdepend.xml" fork="yes" format="xml">
<sourcespath>
<pathelement location="src" />
</sourcespath>
@@ -106,10 +111,10 @@
</classpath>
</jdepend>
</pre>
-</blockquote>
+</blockquote>
-This invokes JDepend in a separate VM on the <code>src</code> and
<code>testsrc</code> directories, writing the output in the
<code><docs/jdepend.txt></code> file.
-The classpath is defined using nested elements.
+This invokes JDepend in a separate VM on the <code>src</code> and
<code>testsrc</code> directories, writing the output to the
<code><docs/jdepend.xml></code> file in xml format.
+The classpath is defined using nested elements.
<hr>
</body>
1.1 jakarta-ant/src/etc/jdepend.xsl
Index: jdepend.xsl
===================================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:decimal-format decimal-separator="." grouping-separator="," />
<xsl:template match="JDepend">
<html>
<head>
<title>JDepend Analysis</title>
<style type="text/css">
body {
font:normal 68% verdana,arial,helvetica;
color:#000000;
}
table tr td, tr th {
font-size: 68%;
}
table.details tr th{
font-weight: bold;
text-align:left;
background:#a6caf0;
}
table.details tr td{
background:#eeeee0;
}
p {
line-height:1.5em;
margin-top:0.5em; margin-bottom:1.0em;
margin-left:2em;
margin-right:2em;
}
h1 {
margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
}
h2 {
margin-top: 1em; margin-bottom: 0.5em; font: bold 125%
verdana,arial,helvetica
}
h3 {
margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
}
h4 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
h5 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
h6 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
.Error {
font-weight:bold; color:red;
}
.Failure {
font-weight:bold; color:purple;
}
.Properties {
text-align:right;
}
</style>
</head>
<body>
<!--h1>JDepend Report</h1>
<ul>
<xsl:for-each select="./Packages/Package">
<xsl:sort select="@name"/>
<li><xsl:value-of select="@name"/></li>
</xsl:for-each>
</ul-->
<h1><a name="top">JDepend Analysis</a></h1>
<p align="right">Designed for use with <a
href="http://www.clarkware.com/software/JDepend.html">JDepend</a> and <a
href="http://jakarta.apache.org">Ant</a>.</p>
<hr size="2" />
<table width="100%"><tr><td>
<a name="NVsummary"><h2>Summary</h2></a>
</td><td align="right">
[<a href="#NVsummary">summary</a>]
[<a href="#NVpackages">packages</a>]
[<a href="#NVcycles">cycles</a>]
[<a href="#NVexplanations">explanations</a>]
</td></tr></table>
<table width="100%" class="details">
<tr>
<th>Package</th>
<th>Total Classes</th>
<th><a href="#EXnumber">Abstract Classes</a></th>
<th><a href="#EXnumber">Concrete Classes</a></th>
<th><a href="#EXafferent">Afferent Couplings</a></th>
<th><a href="#EXefferent">Efferent Couplings</a></th>
<th><a href="#EXabstractness">Abstractness</a></th>
<th><a href="#EXinstability">Instability</a></th>
<th><a href="#EXdistance">Distance</a></th>
</tr>
<xsl:for-each select="./Packages/Package">
<xsl:if test="count(error) = 0">
<tr>
<td align="left">
<a>
<xsl:attribute
name="href">#PK<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</td>
<td align="right"><xsl:value-of
select="Stats/TotalClasses"/></td>
<td align="right"><xsl:value-of
select="Stats/AbstractClasses"/></td>
<td align="right"><xsl:value-of
select="Stats/ConcreteClasses"/></td>
<td align="right"><xsl:value-of
select="Stats/Ca"/></td>
<td align="right"><xsl:value-of
select="Stats/Ce"/></td>
<td align="right"><xsl:value-of
select="format-number(Stats/A, '0%')"/></td>
<td align="right"><xsl:value-of
select="format-number(Stats/I, '0%')"/></td>
<td align="right"><xsl:value-of
select="format-number(Stats/D, '0%')"/></td>
</tr>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="./Packages/Package">
<xsl:if test="count(error) > 0">
<tr>
<td align="left">
<xsl:value-of select="@name"/>
</td>
<td align="left" colspan="8"><xsl:value-of
select="error"/></td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
<table width="100%"><tr><td>
<a name="NVpackages"><h2>Packages</h2></a>
</td><td align="right">
[<a href="#NVsummary">summary</a>]
[<a href="#NVpackages">packages</a>]
[<a href="#NVcycles">cycles</a>]
[<a href="#NVexplanations">explanations</a>]
</td></tr></table>
<xsl:for-each select="./Packages/Package">
<xsl:if test="count(error) = 0">
<h3><a><xsl:attribute name="name">PK<xsl:value-of
select="@name"/></xsl:attribute>
<xsl:value-of select="@name"/></a></h3>
<table width="100%"><tr>
<td><a href="#EXafferent">Afferent
Couplings</a>: <xsl:value-of select="Stats/Ca"/></td>
<td><a href="#EXefferent">Efferent
Couplings</a>: <xsl:value-of select="Stats/Ce"/></td>
<td><a href="#EXabstractness">Abstractness</a>:
<xsl:value-of select="format-number(Stats/A, '0%')"/></td>
<td><a href="#EXinstability">Instability</a>:
<xsl:value-of select="format-number(Stats/I, '0%')"/></td>
<td><a href="#EXdistance">Distance</a>:
<xsl:value-of select="format-number(Stats/D, '0%')"/></td>
</tr></table>
<table width="100%" class="details">
<tr>
<th>Abstract Classes</th>
<th>Concrete Classes</th>
<th>Used by Packages</th>
<th>Uses Packages</th>
</tr>
<tr>
<td valign="top" width="25%">
<xsl:if
test="count(AbstractClasses/Class)=0">
<i>None</i>
</xsl:if>
<xsl:for-each
select="AbstractClasses/Class">
<xsl:value-of
select="node()"/><br/>
</xsl:for-each>
</td>
<td valign="top" width="25%">
<xsl:if
test="count(ConcreteClasses/Class)=0">
<i>None</i>
</xsl:if>
<xsl:for-each
select="ConcreteClasses/Class">
<xsl:value-of
select="node()"/><br/>
</xsl:for-each>
</td>
<td valign="top" width="25%">
<xsl:if
test="count(UsedBy/Package)=0">
<i>None</i>
</xsl:if>
<xsl:for-each
select="UsedBy/Package">
<a>
<xsl:attribute
name="href">#PK<xsl:value-of select="node()"/></xsl:attribute>
<xsl:value-of
select="node()"/>
</a><br/>
</xsl:for-each>
</td>
<td valign="top" width="25%">
<xsl:if
test="count(DependsUpon/Package)=0">
<i>None</i>
</xsl:if>
<xsl:for-each
select="DependsUpon/Package">
<a>
<xsl:attribute
name="href">#PK<xsl:value-of select="node()"/></xsl:attribute>
<xsl:value-of
select="node()"/>
</a><br/>
</xsl:for-each>
</td>
</tr>
</table>
</xsl:if>
</xsl:for-each>
<table width="100%"><tr><td>
<a name="NVcycles"><h2>Cycles</h2></a>
</td><td align="right">
[<a href="#NVsummary">summary</a>]
[<a href="#NVpackages">packages</a>]
[<a href="#NVcycles">cycles</a>]
[<a href="#NVexplanations">explanations</a>]
</td></tr></table>
<xsl:if test="count(Cycles/Package) = 0">
<p>There are no cyclic dependancies.</p>
</xsl:if>
<xsl:for-each select="Cycles/Package">
<h3><xsl:value-of select="@Name"/></h3><p>
<xsl:for-each select="Package">
<xsl:value-of select="."/><br/>
</xsl:for-each></p>
</xsl:for-each>
<table width="100%"><tr><td>
<a name="NVexplanations"><h2>Explanations</h2></a>
</td><td align="right">
[<a href="#NVsummary">summary</a>]
[<a href="#NVpackages">packages</a>]
[<a href="#NVcycles">cycles</a>]
[<a href="#NVexplanations">explanations</a>]
</td></tr></table>
<p>The following explanations are for quick reference and are lifted
directly from the original <a
href="http://www.clarkware.com/software/JDepend.html">JDepend
documentation</a>.</p>
<h3><a name="EXnumber">Number of Classes</a></h3>
<p>The number of concrete and abstract classes (and interfaces)
in the package is an indicator of the extensibility of the package.</p>
<h3><a name="EXafferent">Afferent Couplings</a></h3>
<p>The number of other packages that depend upon classes within
the package is an indicator of the package's responsibility. </p>
<h3><a name="EXefferent">Efferent Couplings</a></h3>
<p>The number of other packages that the classes in the package
depend upon is an indicator of the package's independence. </p>
<h3><a name="EXabstractness">Abstractness</a></h3>
<p>The ratio of the number of abstract classes (and interfaces)
in the analyzed package to the total number of classes in the analyzed package.
</p>
<p>The range for this metric is 0 to 1, with A=0 indicating a
completely concrete package and A=1 indicating a completely abstract package.
</p>
<h3><a name="EXinstability">Instability</a></h3>
<p>The ratio of efferent coupling (Ce) to total coupling (Ce /
(Ce + Ca)). This metric is an indicator of the package's resilience to change.
</p>
<p>The range for this metric is 0 to 1, with I=0 indicating a
completely stable package and I=1 indicating a completely instable package. </p>
<h3><a name="EXdistance">Distance</a></h3>
<p>The perpendicular distance of a package from the idealized
line A + I = 1. This metric is an indicator of the package's balance between
abstractness and stability. </p>
<p>A package squarely on the main sequence is optimally
balanced with respect to its abstractness and stability. Ideal packages are
either completely abstract and stable (x=0, y=1) or completely concrete and
instable (x=1, y=0). </p>
<p>The range for this metric is 0 to 1, with D=0 indicating a
package that is coincident with the main sequence and D=1 indicating a package
that is as far from the main sequence as possible. </p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
1.2 +82 -42
jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java
Index: JDependTask.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- JDependTask.java 2001/06/01 04:43:03 1.1
+++ JDependTask.java 2001/10/16 10:12:23 1.2
@@ -71,6 +71,7 @@
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.EnumeratedAttribute;
/**
* Ant task to run JDepend tests.
@@ -82,10 +83,11 @@
* The current implementation spawn a new Java VM.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Jerome Lacoste</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Rob Oxspring</a>
*/
public class JDependTask extends Task {
- private CommandlineJava commandline = new CommandlineJava();
-
+ //private CommandlineJava commandline = new CommandlineJava();
+
// required attributes
private Path _sourcesPath;
@@ -94,23 +96,26 @@
private File _dir;
private Path _compileClasspath;
private boolean _haltonerror = false;
- private boolean _fork = false;
+ private boolean _fork = false;
//private Integer _timeout = null;
-
+
+ private String _jvm = null;
+ private String format = "text";
+
public JDependTask() {
- commandline.setClassname("jdepend.textui.JDepend");
+
}
/*
public void setTimeout(Integer value) {
_timeout = value;
}
-
+
public Integer getTimeout() {
return _timeout;
}
*/
-
+
public void setOutputFile(File outputFile) {
_outputFile = outputFile;
}
@@ -134,9 +139,9 @@
* Tells whether a JVM should be forked for the task. Default: false.
* @param value <tt>true</tt> if a JVM should be forked, otherwise
<tt>false<tt>
*/
- public void setFork(boolean value) {
- _fork = value;
- }
+ public void setFork(boolean value) {
+ _fork = value;
+ }
public boolean getFork() {
return _fork;
@@ -148,9 +153,10 @@
* @see #setFork(boolean)
*/
public void setJvm(String value) {
- commandline.setVm(value);
+ _jvm = value;
+
}
-
+
/**
* Maybe creates a nested classpath element.
*/
@@ -165,7 +171,7 @@
public Path getSourcespath() {
return _sourcesPath;
}
-
+
/**
* The directory to invoke the VM in. Ignored if no JVM is forked.
* @param dir the directory to invoke the JVM from.
@@ -210,7 +216,7 @@
* @return create a new JVM argument so that any argument can be passed
to the JVM.
* @see #setFork(boolean)
*/
- public Commandline.Argument createJvmarg() {
+ public Commandline.Argument createJvmarg(CommandlineJava commandline ) {
return commandline.createVmArgument();
}
@@ -221,27 +227,56 @@
createClasspath().setRefid(r);
}
+
+ public void setFormat(FormatAttribute ea)
+ {
+ format = ea.getValue();
+ }
+
+ public static class FormatAttribute extends EnumeratedAttribute
+ {
+ private String [] formats = new String[]{"xml","text"};
+
+ public String[] getValues()
+ {
+ return formats;
+ }
+ }
+
+
/**
* No problems with this test.
*/
- private static final int SUCCESS = 0;
+ private static final int SUCCESS = 0;
/**
* An error occured.
- */
+ */
private static final int ERRORS = 1;
-
+
public void execute() throws BuildException {
+
+ CommandlineJava commandline = new CommandlineJava();
+
+ if("text".equals(format))
+ commandline.setClassname("jdepend.textui.JDepend");
+ else
+ if("xml".equals(format))
+ commandline.setClassname("jdepend.xmlui.JDepend");
+
+ if(_jvm!=null)
+ commandline.setVm(_jvm);
+
if (getSourcespath() == null)
throw new BuildException("Missing Sourcepath required argument");
-
+
// execute the test and get the return code
int exitValue = JDependTask.ERRORS;
boolean wasKilled = false;
if (! getFork()) {
- exitValue = executeInVM();
+ exitValue = executeInVM(commandline);
} else {
- ExecuteWatchdog watchdog = createWatchdog();
- exitValue = executeAsForked(watchdog);
+ ExecuteWatchdog watchdog = createWatchdog();
+ exitValue = executeAsForked(commandline,watchdog);
// null watchdog means no timeout, you'd better not check with
null
if (watchdog != null) {
//info will be used in later version do nothing for now
@@ -260,21 +295,26 @@
else
log("JDepend FAILED", Project.MSG_ERR);
}
- }
+ }
+
-
// this comment extract from JUnit Task may also apply here
// "in VM is not very nice since it could probably hang the
// whole build. IMHO this method should be avoided and it would be best
- // to remove it in future versions. TBD. (SBa)"
-
+ // to remove it in future versions. TBD. (SBa)"
+
/**
* Execute inside VM.
*/
- public int executeInVM() throws BuildException {
- jdepend.textui.JDepend jdepend = new jdepend.textui.JDepend();
-
+ public int executeInVM(CommandlineJava commandline) throws
BuildException {
+ jdepend.textui.JDepend jdepend;
+
+ if("xml".equals(format))
+ jdepend = new jdepend.xmlui.JDepend();
+ else
+ jdepend = new jdepend.textui.JDepend();
+
if (getOutputFile() != null) {
FileWriter fw;
try {
@@ -286,21 +326,21 @@
throw new BuildException(msg);
}
jdepend.setWriter(new PrintWriter(fw));
- log("Ouptut to be stored in " + getOutputFile().getPath());
+ log("Output to be stored in " + getOutputFile().getPath());
}
PathTokenizer sourcesPath = new
PathTokenizer(getSourcespath().toString());
while (sourcesPath.hasMoreTokens()) {
File f = new File(sourcesPath.nextToken());
-
- // not necessary as JDepend would fail, but why loose some time?
+
+ // not necessary as JDepend would fail, but why loose some time?
if (! f.exists() || !f.isDirectory()) {
String msg = "\""+ f.getPath() + "\" does not represent a
valid directory. JDepend would fail.";
log(msg);
throw new BuildException(msg);
}
- try {
- jdepend.addDirectory(f.getPath());
+ try {
+ jdepend.addDirectory(f.getPath());
}
catch (IOException e) {
String msg = "JDepend Failed when adding a source directory:
" + e.getMessage();
@@ -311,8 +351,8 @@
jdepend.analyze();
return SUCCESS;
}
-
+
/**
* Execute the task by forking a new JVM. The command will block until
* it finishes. To know if the process was destroyed or not, use the
@@ -322,15 +362,15 @@
* the test could probably hang forever.
*/
// JL: comment extracted from JUnitTask (and slightly modified)
- public int executeAsForked(ExecuteWatchdog watchdog) throws
BuildException {
+ public int executeAsForked(CommandlineJava commandline,ExecuteWatchdog
watchdog) throws BuildException {
// if not set, auto-create the ClassPath from the project
createClasspath();
// not sure whether this test is needed but cost nothing to put.
// hope it will be reviewed by anybody competent
if (getClasspath().toString().length() > 0) {
- createJvmarg().setValue("-classpath");
- createJvmarg().setValue(getClasspath().toString());
+ createJvmarg(commandline).setValue("-classpath");
+ createJvmarg(commandline).setValue(getClasspath().toString());
}
if (getOutputFile() != null) {
@@ -344,22 +384,22 @@
PathTokenizer sourcesPath = new
PathTokenizer(getSourcespath().toString());
while (sourcesPath.hasMoreTokens()) {
File f = new File(sourcesPath.nextToken());
-
+
// not necessary as JDepend would fail, but why loose some time?
if (! f.exists() || !f.isDirectory())
throw new BuildException("\""+ f.getPath() + "\" does not
represent a valid directory. JDepend would fail.");
commandline.createArgument().setValue(f.getPath());
}
-
- Execute execute = new Execute(new LogStreamHandler(this,
Project.MSG_INFO, Project.MSG_WARN), watchdog);
+
+ Execute execute = new Execute(new LogStreamHandler(this,
Project.MSG_INFO, Project.MSG_WARN), watchdog);
execute.setCommandline(commandline.getCommandline());
if (getDir() != null) {
execute.setWorkingDirectory(getDir());
execute.setAntRun(project);
}
- if (getOutputFile() != null)
- log("Ouptut to be stored in " + getOutputFile().getPath());
+ if (getOutputFile() != null)
+ log("Output to be stored in " + getOutputFile().getPath());
log("Executing: "+commandline.toString(), Project.MSG_VERBOSE);
try {
return execute.execute();