You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by do...@apache.org on 2001/06/01 06:43:04 UTC

cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/jdepend JDependTask.java

donaldp     01/05/31 21:43:04

  Modified:    .        build.xml
               docs/manual optionaltasklist.html
               src/main/org/apache/tools/ant/taskdefs defaults.properties
  Added:       docs/manual/OptionalTasks jdepend.html
               src/main/org/apache/tools/ant/taskdefs/optional/jdepend
                        JDependTask.java
  Log:
  Added in jdpend task
  
  Submitted By: J�r�me Lacoste <je...@smartcardsystem.com>
  
  Revision  Changes    Path
  1.154     +5 -0      jakarta-ant/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/build.xml,v
  retrieving revision 1.153
  retrieving revision 1.154
  diff -u -r1.153 -r1.154
  --- build.xml	2001/05/23 16:43:47	1.153
  +++ build.xml	2001/06/01 04:43:00	1.154
  @@ -143,6 +143,10 @@
       <available property="icontract.present"
                  classname="com.reliablesystems.iContract.IContracted"
                  classpathref="classpath"/>
  +    <available property="jdepend.present" 
  +               classname="jdepend.framework.JDepend"  
  +               classpathref="classpath"/>
  +               
     </target>
   
     <!-- 
  @@ -204,6 +208,7 @@
                  unless="xalan.present" />
         <exclude name="${optional.package}/junit/AggregateTransformer.java"
                  unless="xalan.present" />
  +      <exclude name="${optional.package}/jdepend/*" unless="jdepend.present" />
       </javac>
       
       <copy todir="${build.classes}">
  
  
  
  1.13      +1 -0      jakarta-ant/docs/manual/optionaltasklist.html
  
  Index: optionaltasklist.html
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/docs/manual/optionaltasklist.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- optionaltasklist.html	2001/04/29 16:24:20	1.12
  +++ optionaltasklist.html	2001/06/01 04:43:02	1.13
  @@ -21,6 +21,7 @@
   <a href="OptionalTasks/icontract.html">IContract</a><br>
   <a href="OptionalTasks/javacc.html">JavaCC</a><br>
   <a href="OptionalTasks/javah.html">Javah</a><br>
  +<a href="OptionalTasks/jdepend.html">JDepend</a><br>
   <a href="OptionalTasks/jjtree.html">JJTree</a><br>
   <a href="OptionalTasks/jlink.html">Jlink</a><br>
   <a href="OptionalTasks/junit.html">JUnit</a><br>
  
  
  
  1.1                  jakarta-ant/docs/manual/OptionalTasks/jdepend.html
  
  Index: jdepend.html
  ===================================================================
  <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
  <html>
  <head>
     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
     <meta http-equiv="Content-Language" content="en-us">
     <title>JDepend Task</title>
  </head>
  <body>
  
  <h2>
  <a NAME="JDepend"></a>JDepend</h2>
  
  <h3>
  Description</h3>
  
  <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 effectively manage and control package dependencies."
  </P>
  
  <p>Source file directories are defined by nested <code>&lt;sourcespath&gt;</code>, see <a href="#nested">nested
  elements</a>.<BR>
  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>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>
  
  <p>
  
  <h3>
  Parameters</h3>
  
  <table BORDER CELLSPACING=0 CELLPADDING=2 >
  <tr>
  <td VALIGN=TOP><b>Attribute</b></td>
  
  <td VALIGN=TOP><b>Description</b></td>
  
  <td ALIGN=CENTER VALIGN=TOP><b>Required</b></td>
  </tr>
  
  <tr>
  <td VALIGN=TOP>outputfile</td>
  
  <td VALIGN=TOP>The output file name. If not set, the output is printed on the standard output.</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>
  </tr>
  
  <tr>
  <td VALIGN=TOP>haltonerror</td>
  
  <td VALIGN=TOP>Stop the build process if an error occurs during the jdepend analysis.</td>
  
  <td ALIGN=CENTER VALIGN=TOP>No, default is "off"</td>
  </tr>
  
  <tr>
  <td VALIGN=TOP>timeout</td>
  
  <td VALIGN=TOP>Cancel the operation if it doesn't finish in the given time (measured in milliseconds). (Ignored if fork is disabled.)</td>
  
  <td ALIGN=CENTER VALIGN=TOP>No</td>
  </tr>
  
  <tr>
  <td VALIGN=TOP>jvm</td>
  
  <td VALIGN=TOP>The command used to invoke the Java Virtual Machine, default is 'java'. The command is resolved by java.lang.Runtime.exec(). (Ignored if fork is disabled.)</td>
  
  <td ALIGN=CENTER VALIGN=TOP>No, default "java"</td>
  </tr>
  
  <tr>
  <td VALIGN=TOP>dir</td>
  
  <td VALIGN=TOP>The directory to invoke the VM in. (Ignored if fork is disabled)</td>
  
  <td ALIGN=CENTER VALIGN=TOP>No</td>
  </tr>
  
  <tr>
  <td VALIGN=TOP>classpathref</td>
  
  <td VALIGN=TOP>the classpath to use, given as reference to a PATH defined elsewhere.</td>
  
  <td ALIGN=CENTER VALIGN=TOP>No</td>
  </tr>
  
  </table>
  
  
  <h3><a name="nested">Nested Elements</a></h3>
  
  
  <p><code>jdepend</code> supports two nested elements <code>&lt;classpath&gt;</code> and <code>&lt;sourcespath&gt;</code>, that represent <a href="../using.html#path">PATH like
  structures</a>. 
  
  <BR><code>&lt;sourcespath&gt;</code> is used to define the paths of the source code to analyze.</BR>
  </p> 
  
  <h3>
  Examples</h3>
  
  <blockquote>
  <pre>
  &lt;jdepend classpathref="base.path">
  &nbsp;&nbsp;&nbsp; &lt;sourcespath>
  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="src" />
  &nbsp;&nbsp;&nbsp; &lt;/sourcespath>
  &lt;/jdepend>
  </pre>
  </blockquote>
  
  This invokes JDepend on the <code>src</code> directory, writing the output on the standard output.
  The classpath is defined using a classpath reference.
  <blockquote>
  <pre>
  &lt;jdepend outputfile="docs/jdepend.txt" fork="yes">
  &nbsp;&nbsp;&nbsp; &lt;sourcespath>
  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="src" />
  &nbsp;&nbsp;&nbsp; &lt;/sourcespath>
  &nbsp;&nbsp;&nbsp; &lt;classpath>
  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="classes" />
  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;pathelement location="lib/jdepend.jar" />
  &nbsp;&nbsp;&nbsp; &lt;/classpath>
  &lt;/jdepend>
  </pre>
  </blockquote>  
  
  This invokes JDepend in a separate VM on the <code>src</code> and <code>testsrc</code> directories, writing the output in the <code>&lt;docs/jdepend.txt&gt;</code> file.
  The classpath is defined using nested elements. 
  <br>
  <hr>
  </body>
  </html>
  
  
  
  
  1.76      +1 -0      jakarta-ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
  retrieving revision 1.75
  retrieving revision 1.76
  diff -u -r1.75 -r1.76
  --- defaults.properties	2001/05/01 10:31:44	1.75
  +++ defaults.properties	2001/06/01 04:43:03	1.76
  @@ -101,6 +101,7 @@
   vsscheckin=org.apache.tools.ant.taskdefs.optional.vss.MSVSSCHECKIN
   vsscheckout=org.apache.tools.ant.taskdefs.optional.vss.MSVSSCHECKOUT
   iplanet-ejbc=org.apache.tools.ant.taskdefs.optional.ejb.IPlanetEjbcTask
  +jdepend=org.apache.tools.ant.taskdefs.optional.jdepend.JDependTask
   
   # deprecated ant tasks (kept for back compatibility)
   javadoc2=org.apache.tools.ant.taskdefs.Javadoc
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java
  
  Index: JDependTask.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.jdepend;
  
  import java.io.File;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.util.Enumeration;
  import java.util.Vector;
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.PathTokenizer;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.taskdefs.Execute;
  import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
  import org.apache.tools.ant.taskdefs.LogStreamHandler;
  import org.apache.tools.ant.types.Commandline;
  import org.apache.tools.ant.types.CommandlineJava;
  import org.apache.tools.ant.types.Path;
  import org.apache.tools.ant.types.Reference;
  
  /**
   * Ant task to run JDepend tests.
   *
   * <p>JDepend is a tool to generate design quality metrics for each Java package.
   * It has been initially created by Mike Clark. JDepend can be found at <a
   * href="http://www.clarkware.com/software/JDepend.html">http://www.clarkware.com/software/JDepend.html</a>.
   *
   * The current implementation spawn a new Java VM.
   *
   * @author <a href="mailto:Jerome@jeromelacoste.com">Jerome Lacoste</a>
   */
  public class JDependTask extends Task {
      private CommandlineJava commandline = new CommandlineJava();       
          
      // required attributes
      private Path _sourcesPath;
  
      // optional attributes
      private File _outputFile;
      private File _dir;
      private Path _compileClasspath;
      private boolean _haltonerror = false;
      private boolean _fork = false;    
      //private Integer _timeout = null;
      
      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;
      }
  
      public File getOutputFile() {
          return _outputFile;
      }
  
      /**
       * Halt on Failure? default: false.
       */
      public void setHaltonerror(boolean value) {
          _haltonerror = value;
      }
  
      public boolean getHaltonerror() {
          return _haltonerror;
      }
  
      /**
       * 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 boolean getFork() {
          return _fork;
      }
  
      /**
       * Set a new VM to execute the task. Default is <tt>java</tt>. Ignored if no JVM is forked.
       * @param   value   the new VM to use instead of <tt>java</tt>
       * @see #setFork(boolean)
       */
      public void setJvm(String value) {
          commandline.setVm(value);
      }
      
      /**
       * Maybe creates a nested classpath element.
       */
      public Path createSourcespath() {
          if (_sourcesPath == null) {
              _sourcesPath = new Path(project);
          }
          return _sourcesPath.createPath();
      }
  
      /** Gets the sourcepath. */
      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.
       * @see #setFork(boolean)
       */
      public void setDir(File dir) {
          _dir = dir;
      }
  
      public File getDir() {
          return _dir;
      }
  
      /**
       * Set the classpath to be used for this compilation.
       */
      public void setClasspath(Path classpath) {
          if (_compileClasspath == null) {
              _compileClasspath = classpath;
          } else {
              _compileClasspath.append(classpath);
          }
      }
  
      /** Gets the classpath to be used for this compilation. */
      public Path getClasspath() {
          return _compileClasspath;
      }
  
      /**
       * Maybe creates a nested classpath element.
       */
      public Path createClasspath() {
          if (_compileClasspath == null) {
              _compileClasspath = new Path(project);
          }
          return _compileClasspath.createPath();
      }
  
      /**
       * Create a new JVM argument. Ignored if no JVM is forked.
       * @return  create a new JVM argument so that any argument can be passed to the JVM.
       * @see #setFork(boolean)
       */
      public Commandline.Argument createJvmarg() {
          return commandline.createVmArgument();
      }
  
      /**
       * Adds a reference to a CLASSPATH defined elsewhere.
       */
      public void setClasspathRef(Reference r) {
          createClasspath().setRefid(r);
      }
  
      /**
       * No problems with this test.
       */
      private static final int SUCCESS = 0;    
      /**
       * An error occured.
       */    
      private static final int ERRORS = 1;
      
      public void execute() throws BuildException {
          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();
          } else {
              ExecuteWatchdog watchdog = createWatchdog();                
              exitValue = executeAsForked(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
                  //wasKilled = watchdog.killedProcess();
              }
          }
  
          // if there is an error/failure and that it should halt, stop everything otherwise
          // just log a statement
          boolean errorOccurred = exitValue == JDependTask.ERRORS;
  
          if (errorOccurred) {
              if  (getHaltonerror())
                  throw new BuildException("JDepend failed",
                                           location);
              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)"    
          
      /**
       * Execute inside VM.
       */
      public int executeInVM() throws BuildException {
          jdepend.textui.JDepend jdepend = new jdepend.textui.JDepend();
         
          if (getOutputFile() != null) {
              FileWriter fw;
              try {
                  fw = new FileWriter(getOutputFile().getPath());
              }
              catch (IOException e) {
                  String msg = "JDepend Failed when creating the output file: " + e.getMessage();
                  log(msg);
                  throw new BuildException(msg);
              }
              jdepend.setWriter(new PrintWriter(fw));
              log("Ouptut 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?                    
              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());                  
              }
              catch (IOException e) {
                  String msg = "JDepend Failed when adding a source directory: " + e.getMessage();
                  log(msg);
                  throw new BuildException(msg);
              }
          }
          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
       * <tt>killedProcess()</tt> method of the watchdog class.
       * @param  watchdog   the watchdog in charge of cancelling the test if it
       * exceeds a certain amount of time. Can be <tt>null</tt>, in this case
       * the test could probably hang forever.
       */
      // JL: comment extracted from JUnitTask (and slightly modified)
      public int executeAsForked(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());
          }
  
          if (getOutputFile() != null) {
              // having a space between the file and its path causes commandline to add quotes "
              // around the argument thus making JDepend not taking it into account. Thus we split it in two
              commandline.createArgument().setValue("-file");
              commandline.createArgument().setValue(_outputFile.getPath());
              // we have to find a cleaner way to put this output
          }
  
          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.setCommandline(commandline.getCommandline());
          if (getDir() != null) {
              execute.setWorkingDirectory(getDir());
              execute.setAntRun(project);
          }
  
          if (getOutputFile() != null) 
              log("Ouptut to be stored in " + getOutputFile().getPath());
          log("Executing: "+commandline.toString(), Project.MSG_VERBOSE);
          try {
              return execute.execute();
          } catch (IOException e) {
              throw new BuildException("Process fork failed.", e, location);
          }
      }
  
      /**
       * @return <tt>null</tt> if there is a timeout value, otherwise the
       * watchdog instance.
       */
      protected ExecuteWatchdog createWatchdog() throws BuildException {
  
          return null;
          /*
            if (getTimeout() == null){
            return null;
            }
            return new ExecuteWatchdog(getTimeout().intValue());
          */
      }
  }