Package jdiff

Source Code of jdiff.JDiffAntTask$ProjectInfo

package jdiff;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Vector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Javadoc;
import org.apache.tools.ant.taskdefs.Javadoc.DocletInfo;
import org.apache.tools.ant.taskdefs.Javadoc.DocletParam;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.Path;

/**
* An Ant task to produce a simple JDiff report. More complex reports still
* need parameters that are controlled by the Ant Javadoc task.
*/
public class JDiffAntTask {

    public void execute() throws BuildException {
  jdiffHome = project.getProperty("JDIFF_HOME");
  if (jdiffHome == null || jdiffHome.compareTo("") == 0 |
      jdiffHome.compareTo("(not set)") == 0) {
      throw new BuildException("Error: invalid JDIFF_HOME property. Set it in the build file to the directory where jdiff is installed");
  }
        project.log(" JDiff home: " + jdiffHome, Project.MSG_INFO);

  jdiffClassPath = jdiffHome + DIR_SEP + "jdiff.jar" +
      System.getProperty("path.separator") +
      jdiffHome + DIR_SEP + "xerces.jar";

  // TODO detect and set verboseAnt

  // Create, if necessary, the directory for the JDiff HTML report
        if (!destdir.mkdir() && !destdir.exists()) {
      throw new BuildException(getDestdir() + " is not a valid directory");
  } else {
      project.log(" Report location: " + getDestdir() + DIR_SEP
      + "changes.html", Project.MSG_INFO);
  }
  // Could also output the other parameters used for JDiff here
  
  // Check that there are indeed two projects to compare. If there
  // are no directories in the project, let Javadoc do the complaining
  if (oldProject == null || newProject == null) {
      throw new BuildException("Error: two projects are needed, one <old> and one <new>");
  }

  /*
  // Display the directories being compared, and some name information
  if (getVerbose()) {
      project.log("Older version: " + oldProject.getName(),
      Project.MSG_INFO);
      project.log("Included directories for older version:",
      Project.MSG_INFO);
      DirectoryScanner ds =
    oldProject.getDirset().getDirectoryScanner(project);
      String[] files = ds.getIncludedDirectories();
      for (int i = 0; i < files.length; i++) {
    project.log(" " + files[i], Project.MSG_INFO);
      }
      ds = null;
     
      project.log("Newer version: " + newProject.getName(),
      Project.MSG_INFO);
      project.log("Included directories for newer version:",
      Project.MSG_INFO);
      ds = newProject.getDirset().getDirectoryScanner(project);
      files = ds.getIncludedDirectories();
      for (int i = 0; i < files.length; i++) {
    project.log(" " + files[i], Project.MSG_INFO);
      }
  }
  */

  // Call Javadoc twice to generate Javadoc for each project
  generateJavadoc(oldProject);
  generateJavadoc(newProject);

  // Call Javadoc three times for JDiff.
  generateXML(oldProject);
  generateXML(newProject);
  compareXML(oldProject.getName(), newProject.getName());

  // Repeat some useful information
  project.log(" Report location: " + getDestdir() + DIR_SEP
        + "changes.html", Project.MSG_INFO);
    }

    /**
     * Convenient method to create a Javadoc task, configure it and run it
     * to generate the XML representation of a project's source files.
     *
     * @param proj The current Project
     */
    protected void generateXML(ProjectInfo proj) {
  String apiname = proj.getName();
  Javadoc jd = initJavadoc("Analyzing " + apiname);
  jd.setDestdir(getDestdir());
  addSourcePaths(jd, proj);

  // Tell Javadoc which packages we want to scan.
  // JDiff works with packagenames, not sourcefiles.
  jd.setPackagenames(getPackageList(proj));
 
  // Create the DocletInfo first so we have a way to use it to add params
  DocletInfo dInfo = jd.createDoclet();
  jd.setDoclet("jdiff.JDiff");
  jd.setDocletPath(new Path(project, jdiffClassPath));
 
  // Now set up some parameters for the JDiff doclet.
  DocletParam dp1 = dInfo.createParam();
  dp1.setName("-apiname");
  dp1.setValue(apiname);
  DocletParam dp2 = dInfo.createParam();
  dp2.setName("-baseURI");
  dp2.setValue("http://www.w3.org");
  // Put the generated file in the same directory as the report
  DocletParam dp3 = dInfo.createParam();
  dp3.setName("-apidir");
  dp3.setValue(getDestdir().toString());
 
  // Execute the Javadoc command to generate the XML file.
  jd.perform();
    }

    /**
     * Convenient method to create a Javadoc task, configure it and run it
     * to compare the XML representations of two instances of a project's
     * source files, and generate an HTML report summarizing the differences.
     *
     * @param oldapiname The name of the older version of the project
     * @param newapiname The name of the newer version of the project
     */
    protected void compareXML(String oldapiname, String newapiname) {
  Javadoc jd = initJavadoc("Comparing versions");
  jd.setDestdir(getDestdir());
  jd.setPrivate(true);

  // Tell Javadoc which files we want to scan - a dummy file in this case
  jd.setSourcefiles(jdiffHome + DIR_SEP + "Null.java");
 
  // Create the DocletInfo first so we have a way to use it to add params
  DocletInfo dInfo = jd.createDoclet();
  jd.setDoclet("jdiff.JDiff");
  jd.setDocletPath(new Path(project, jdiffClassPath));
 
  // Now set up some parameters for the JDiff doclet.
  DocletParam dp1 = dInfo.createParam();
  dp1.setName("-oldapi");
  dp1.setValue(oldapiname);
  DocletParam dp2 = dInfo.createParam();
  dp2.setName("-newapi");
  dp2.setValue(newapiname);
  // Get the generated XML files from the same directory as the report
  DocletParam dp3 = dInfo.createParam();
  dp3.setName("-oldapidir");
  dp3.setValue(getDestdir().toString());
  DocletParam dp4 = dInfo.createParam();
  dp4.setName("-newapidir");
  dp4.setValue(getDestdir().toString());

  // Assume that Javadoc reports already exist in ../"apiname"
  DocletParam dp5 = dInfo.createParam();
  dp5.setName("-javadocold");
  dp5.setValue(".." + DIR_SEP + oldapiname + DIR_SEP);
  DocletParam dp6 = dInfo.createParam();
  dp6.setName("-javadocnew");
  dp6.setValue(".." + DIR_SEP + newapiname + DIR_SEP);
 
  if (getStats()) {
      // There are no arguments to this argument
      dInfo.createParam().setName("-stats");
      // We also have to copy two image files for the stats pages
      copyFile(jdiffHome + DIR_SEP + "black.gif",
         getDestdir().toString() + DIR_SEP + "black.gif");
      copyFile(jdiffHome + DIR_SEP + "background.gif",
         getDestdir().toString() + DIR_SEP + "background.gif");
  }
 
  if (getDocchanges()) {
      // There are no arguments to this argument
      dInfo.createParam().setName("-docchanges");
  }
 
  if (getIncompatible()) {
      // There are no arguments to this argument
      dInfo.createParam().setName("-incompatible");
  }

        if(getScript()) {
            dInfo.createParam().setName("-script");
        }

  // Execute the Javadoc command to compare the two XML files
  jd.perform();
    }

    /**
     * Generate the Javadoc for the project. If you want to generate
     * the Javadoc report for the project with different parameters from the
     * simple ones used here, then use the Javadoc Ant task directly, and
     * set the javadoc attribute to the "old" or "new" element.
     *
     * @param proj The current Project
     */
    protected void generateJavadoc(ProjectInfo proj) { 
  String javadoc = proj.getJavadoc();
  if (javadoc != null && javadoc.compareTo("generated") != 0) {
      project.log("Configured to use existing Javadoc located in "
      javadoc, Project.MSG_INFO);
      return;
  }

  String apiname = proj.getName();
  Javadoc jd = initJavadoc("Javadoc for " + apiname);
  jd.setDestdir(new File(getDestdir().toString() + DIR_SEP + apiname));
  addSourcePaths(jd, proj);

  jd.setPrivate(true);
  jd.setPackagenames(getPackageList(proj));

  // Execute the Javadoc command to generate a regular Javadoc report
  jd.perform();
    }

    /**
     * Create a fresh new Javadoc task object and initialize it.
     *
     * @param logMsg String which appears as a prefix in the Ant log
     * @return The new task.Javadoc object
     */
    protected Javadoc initJavadoc(String logMsg) {
  Javadoc jd = new Javadoc();
  jd.setProject(project); // Vital, otherwise Ant crashes
  jd.setTaskName(logMsg);
  jd.setSource(getSource()); // So we can set the language version
  jd.init();

  // Set up some common parameters for the Javadoc task
  if (verboseAnt) {
      jd.setVerbose(true);
  }
  return jd;
    }

    /**
     * Add the root directories for the given project to the Javadoc
     * sourcepath.
     */
    protected void addSourcePaths(Javadoc jd, ProjectInfo proj) {
  Vector dirSets = proj.getDirsets();
  int numDirSets = dirSets.size();
  for (int i = 0; i < numDirSets; i++) {
      DirSet dirSet = (DirSet)dirSets.elementAt(i);
      jd.setSourcepath(new Path(project, dirSet.getDir(project).toString()));
  }
    }

    /**
     * Return the comma-separated list of packages. The list is
     * generated from Ant DirSet tasks, and includes all directories
     * in a hierarchy, e.g. com, com/acme. com/acme/foo. Duplicates are
     * ignored.
     */
    protected String getPackageList(ProjectInfo proj) throws BuildException {
  String packageList = "";
  java.lang.StringBuffer sb = new StringBuffer();
  Vector dirSets = proj.getDirsets();
  int numDirSets = dirSets.size();
  boolean addComma = false;
  for (int i = 0; i < numDirSets; i++) {
      DirSet dirSet = (DirSet)dirSets.elementAt(i);
      DirectoryScanner dirScanner = dirSet.getDirectoryScanner(project);
      String[] files = dirScanner.getIncludedDirectories();
      for (int j = 0; j < files.length; j++) {
    if (!addComma){
        addComma = true;
    } else {
        sb.append(",");
    }
    sb.append(files[j]);
      }
  }
  packageList = sb.toString();
  if (packageList.compareTo("") == 0) {
      throw new BuildException("Error: no packages found to scan");
  }
  project.log(" Package list: " + packageList, Project.MSG_INFO);
 
  return packageList;
    }

    /**
     * Copy a file from src to dst. Also checks that "destdir/changes" exists
     */
    protected void copyFile(String src, String dst){
  File srcFile = new File(src);
  File dstFile = new File(dst);
  try {
      File reportSubdir = new File(getDestdir().toString() +
           DIR_SEP + "changes");
      if (!reportSubdir.mkdir() && !reportSubdir.exists()) {
    project.log("Warning: unable to create " + reportSubdir,
          Project.MSG_WARN);
      }

      InputStream in = new FileInputStream(src);
      OutputStream out = new FileOutputStream(dst);
   
      // Transfer bytes from in to out
      byte[] buf = new byte[1024];
      int len;
      while ((len = in.read(buf)) > 0) {
    out.write(buf, 0, len);
      }
      in.close();
      out.close();
  } catch (java.io.FileNotFoundException fnfe) {
      project.log("Warning: unable to copy " + src.toString() +
      " to " + dst.toString(), Project.MSG_WARN);
      // Discard the exception
  } catch (java.io.IOException ioe) {
      project.log("Warning: unable to copy " + src.toString() +
      " to " + dst.toString(), Project.MSG_WARN);
      // Discard the exception
  }
    }

    /**
     * The JDiff Ant task does not inherit from an Ant task, such as the
     * Javadoc task, though this is usually how most Tasks are
     * written. This is because JDiff needs to run Javadoc three times
     * (twice for generating XML, once for generating HTML). The
     * Javadoc task has not easy way to reset its list of packages, so
     * we needed to be able to crate new Javadoc task objects.
     *
     * Note: Don't confuse this class with the ProjectInfo used by JDiff.
     * This Project class is from Ant.
     */
    private Project project;

    /**
     * Used as part of Ant's startup.
     */
    public void setProject(Project proj) {
        project = proj;
    }

    /**
     * Ferward or backward slash, as appropriate.
     */
    static String DIR_SEP = System.getProperty("file.separator");

    /**
     * JDIFF_HOME must be set as a property in the Ant build file.
     * It should be set to the root JDiff directory, ie. the one where
     * jdiff.jar is found.
     */
    private String jdiffHome = "(not set)";

    /**
     * The classpath used by Javadoc to find jdiff.jar and xerces.jar.
     */
    private String jdiffClassPath = "(not set)";

    /* ***************************************************************** */
    /* * Objects and methods which are related to attributes           * */
    /* ***************************************************************** */

    /**
     * The destination directory for the generated report.
     * The default is "./jdiff_report".
     */
    private File destdir = new File("jdiff_report");

    /**
     * Used to store the destdir attribute of the JDiff task XML element.
     */
    public void setDestdir(File value) {
  this.destdir = value;
    }

    public File getDestdir() {
  return this.destdir;
    }

    /**
     * Increases the JDiff Ant task logging verbosity if set with "yes", "on"
     * or true". Default has to be false.
     * To increase verbosity of Javadoc, start Ant with -v or -verbose.
     */
    private boolean verbose = false;

    public void setVerbose(boolean value) {
  this.verbose = value;
    }

    public boolean getVerbose() {
  return this.verbose;
    }

    /**
     * Set if ant was started with -v or -verbose
     */
    private boolean verboseAnt = false;

    /**
     * Add the -docchanges argument, to track changes in Javadoc documentation
     * as well as changes in classes etc.
     */
    private boolean docchanges = false;

    public void setDocchanges(boolean value) {
  this.docchanges = value;
    }

    public boolean getDocchanges() {
  return this.docchanges;
    }
   
    /**
     * Add the -incompatible argument, to only report incompatible changes.
     */
    private boolean incompatible = false;

    public void setIncompatible(boolean value) {
  this.incompatible = value;
    }

    public boolean getIncompatible() {
  return this.incompatible;
    }

    /**
     * Add the -script argument
     */
    private boolean script = false;

    public void setScript(boolean value) {
        this.script = value;
    }

    public boolean getScript() {
        return this.script;
    }

    /**
     * Add statistics to the report if set. Default can only be false.
     */
    private boolean stats = false;

    public void setStats(boolean value) {
  this.stats = value;
    }

    public boolean getStats() {
  return this.stats;
    }

    /**
     * Allow the source language version to be specified.
     */
    private String source = "1.5"; // Default is 1.5, so generics will work
   
    public void setSource(String source) {
        this.source = source;
    }
   
    public String getSource() {
        return source;
    }

    /* ***************************************************************** */
    /* * Classes and objects which are related to elements             * */
    /* ***************************************************************** */

    /**
     * A ProjectInfo-derived object for the older version of the project
     */
    private ProjectInfo oldProject = null;

    /**
     * Used to store the child element named "old", which is under the
     * JDiff task XML element.
     */
    public void addConfiguredOld(ProjectInfo projInfo) {
  oldProject = projInfo;
    }

    /**
     * A ProjectInfo-derived object for the newer version of the project
     */
    private ProjectInfo newProject = null;

    /**
     * Used to store the child element named "new", which is under the
     * JDiff task XML element.
     */
    public void addConfiguredNew(ProjectInfo projInfo) {
  newProject = projInfo;
    }

    /**
     * This class handles the information about a project, whether it is
     * the older or newer version.
     *
     * Note: Don't confuse this class with the Project used by Ant.
     * This ProjectInfo class is from local to this task.
     */
    public static class ProjectInfo {
  /**
   * The name of the project. This is used (without spaces) as the
   * base of the name of the file which contains the XML representing
   * the project.
   */
  private String name;

  public void setName(String value) {
      name = value;
  }

  public String getName() {
      return name;
  }

  /**
   * The location of the Javadoc HTML for this project. Default value
   * is "generate", which will cause the Javadoc to be generated in
   * a subdirectory named "name" in the task's destdir directory.
   */
  private String javadoc;

  public void setJavadoc(String value) {
      javadoc = value;
  }

  public String getJavadoc() {
      return javadoc;
  }

   /**
   * These are the directories which contain the packages which make
   * up the project. Filesets are not supported by JDiff.
   */
  private Vector dirsets = new Vector();

  public void setDirset(DirSet value) {
      dirsets.add(value);
  }

  public Vector getDirsets() {
      return dirsets;
  }

  /**
   * Used to store the child element named "dirset", which is under the
   * "old" or "new" XML elements.
   */
  public void addDirset(DirSet aDirset) {
      setDirset(aDirset);
  }
 
    }
}
TOP

Related Classes of jdiff.JDiffAntTask$ProjectInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.