JDiff.javaAPI DocAndroid 1.5 API11666Wed May 06 22:41:22 BST 2009jdiff


public class JDiff extends Doclet
Generates HTML describing the changes between two sets of Java source code. See the file LICENSE.txt for copyright details.
Matthew Doar,

Fields Summary
static String
The name of the file where the XML representing the old API is stored.
static String
The name of the directory where the XML representing the old API is stored.
static String
The name of the file where the XML representing the new API is stored.
static String
The name of the directory where the XML representing the new API is stored.
static boolean
If set, then generate the XML for an API and exit.
static boolean
If set, then read in two XML files and compare their APIs.
static String
The file separator for the local filesystem, forward or backward slash.
static final String
Details for where to find JDiff.
static final String
Contact email address for the primary JDiff maintainer.
static final String
A description for HTML META tags.
static final String
Keywords for HTML META tags.
static final String
The current JDiff version.
static String
The current virtual machine version.
private static boolean
Set to enable increased logging verbosity for debugging.
Constructors Summary
Methods Summary
public static LanguageVersionlanguageVersion()

      return LanguageVersion.JAVA_1_5;
public static voidmain(java.lang.String[] args)
This method is only called when running JDiff as a standalone application, and uses ANT to execute the build configuration in the XML configuration file passed in.

        if (args.length == 0) {
            System.out.println("Looking for a local 'build.xml' configuration file");
        } else if (args.length == 1) {
            if (args[0].compareTo("-help") == 0 ||
                args[0].compareTo("-h") == 0 ||
                args[0].compareTo("?") == 0) {
            } else if (args[0].compareTo("-version") == 0) {
                System.out.println("JDiff version: " + JDiff.version);
        int rc = runAnt(args);
public static intoptionLength(java.lang.String option)
This method is called by Javadoc to parse the options it does not recognize. It then calls {@link #validOptions} to validate them.

option a String containing an option
an int telling how many components that option has

        return Options.optionLength(option);
public static intrunAnt(java.lang.String[] args)
Invoke ANT by reflection.

The integer return code from running ANT.

        String className = null;
        Class c = null;
        try {
            className = "";
            c = Class.forName(className);
        } catch (ClassNotFoundException e1) {
            System.err.println("Error: ant.jar not found on the classpath");
            return -1;
        try {
            Class[] methodArgTypes = new Class[1];
            methodArgTypes[0] = args.getClass();
            Method mainMethod = c.getMethod("main", methodArgTypes);
            Object[] methodArgs = new Object[1];
            methodArgs[0] = args;
            // The object can be null because the method is static
            Integer res = (Integer)mainMethod.invoke(null, methodArgs);
            System.gc(); // Clean up after running ANT
            return res.intValue();
        } catch (NoSuchMethodException e2) {
            System.err.println("Error: method \"main\" not found");
        } catch (IllegalAccessException e4) {
            System.err.println("Error: class not permitted to be instantiated");
        } catch (InvocationTargetException e5) {
            System.err.println("Error: method \"main\" could not be invoked");
        } catch (Exception e6) {
            System.err.println("Error: ");
        System.gc(); // Clean up after running ANT
        return -1;
public static voidshowUsage()
Display usage information for JDiff.

        System.out.println("usage: java jdiff.JDiff [-version] [-buildfile <XML configuration file>]");
        System.out.println("If no build file is specified, the local build.xml file is used.");
public static booleanstart(RootDoc root)
Doclet-mandated start method. Everything begins here.

root a RootDoc object passed by Javadoc
true if document generation succeeds

        if (root != null)
            System.out.println("JDiff: doclet started ...");
        JDiff jd = new JDiff();
        return jd.startGeneration(root);
protected booleanstartGeneration(RootDoc newRoot)
Generate the summary of the APIs.

root the RootDoc object passed by Javadoc
true if no problems encountered within JDiff

        long startTime = System.currentTimeMillis();

        // Open the file where the XML representing the API will be stored.
        // and generate the XML for the API into it.
        if (writeXML) {

        if (compareAPIs) {
	    String tempOldFileName = oldFileName;
	    if (oldDirectory != null) {
		tempOldFileName = oldDirectory;
		if (!tempOldFileName.endsWith(JDiff.DIR_SEP)) {
		    tempOldFileName += JDiff.DIR_SEP;
		tempOldFileName += oldFileName;

            // Check the file for the old API exists
            File f = new File(tempOldFileName);
            if (!f.exists()) {
                System.out.println("Error: file '" + tempOldFileName + "' does not exist for the old API");
                return false;
            // Check the file for the new API exists

	    String tempNewFileName = newFileName;
            if (newDirectory != null) {
		tempNewFileName = newDirectory;
		if (!tempNewFileName.endsWith(JDiff.DIR_SEP)) {
		    tempNewFileName += JDiff.DIR_SEP;
		tempNewFileName += newFileName;
            f = new File(tempNewFileName);
            if (!f.exists()) {
                System.out.println("Error: file '" + tempNewFileName + "' does not exist for the new API");
                return false;

            // Read the file where the XML representing the old API is stored
            // and create an API object for it.
            System.out.print("JDiff: reading the old API in from file '" + tempOldFileName + "'...");
            // Read the file in, but do not add any text to the global comments
            API oldAPI = XMLToAPI.readFile(tempOldFileName, false, oldFileName);
            // Read the file where the XML representing the new API is stored
            // and create an API object for it.
            System.out.print("JDiff: reading the new API in from file '" + tempNewFileName + "'...");
            // Read the file in, and do add any text to the global comments
            API newAPI = XMLToAPI.readFile(tempNewFileName, true, newFileName);
            // Compare the old and new APIs.
            APIComparator comp = new APIComparator();
            comp.compareAPIs(oldAPI, newAPI);
            // Read the file where the XML for comments about the changes between
            // the old API and new API is stored and create a Comments object for 
            // it. The Comments object may be null if no file exists.
            int suffix = oldFileName.lastIndexOf('.");
            String commentsFileName = "user_comments_for_" + oldFileName.substring(0, suffix);
            suffix = newFileName.lastIndexOf('.");
            commentsFileName += "_to_" + newFileName.substring(0, suffix) + ".xml";
            commentsFileName = commentsFileName.replace(' ", '_");
                if (HTMLReportGenerator.commentsDir !=null) {
                  commentsFileName = HTMLReportGenerator.commentsDir + DIR_SEP + commentsFileName;
                } else if (HTMLReportGenerator.outputDir != null) {
                  commentsFileName = HTMLReportGenerator.outputDir + DIR_SEP + commentsFileName;
            System.out.println("JDiff: reading the comments in from file '" + commentsFileName + "'...");
            Comments existingComments = Comments.readFile(commentsFileName);
            if (existingComments == null)
                System.out.println(" (the comments file will be created)");
            // Generate an HTML report which summarises all the API differences.
            HTMLReportGenerator reporter = new HTMLReportGenerator();
            reporter.generate(comp, existingComments);
            // Emit messages about which comments are now unused and
            // which are new.
            Comments newComments = reporter.getNewComments();
            Comments.noteDifferences(existingComments, newComments);
            // Write the new comments out to the same file, with unused comments
            // now commented out.
            System.out.println("JDiff: writing the comments out to file '" + commentsFileName + "'...");
            Comments.writeFile(commentsFileName, newComments);

        System.out.print("JDiff: finished (took " + (System.currentTimeMillis() - startTime)/1000 + "s");
        if (writeXML)
            System.out.println(", not including scanning the source files)."); 
        else if (compareAPIs)
       return true;
public static booleanvalidOptions(java.lang.String[][] options, DocErrorReporter reporter)
After parsing the available options using {@link #optionLength}, Javadoc invokes this method with an array of options-arrays.

options an array of String arrays, one per option
reporter a DocErrorReporter for generating error messages
true if no errors were found, and all options are valid

        return Options.validOptions(options, reporter);