FileDocCategorySizeDatePackage
APIRef.javaAPI DocExample3916Sat Nov 25 12:55:22 GMT 2000None

APIRef.java

import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.lang.reflect.*;

/**
 * APIRef prints a cross-reference about all classes named in argv.
 * For each class, all public fields and methods are listed.
 * "Reflectance" is used to look up the information.
 *
 * It is expected that the output will be post-processed e.g.,
 * with sort and awk/perl. Try: 
	java APIRef | 
		uniq | # squeeze out polymorphic forms early
		grep ' method ' |
		sort | awk '{ ... }' > crossref-methods.txt
 * The part in "{ ... }" is left as an exercise for the reader. :-(
 *
 * @author	Ian Darwin, Ian@DarwinSys.com
 *
 */
public class APIRef {
	/** Counter of fields/methods printed. */
	static int n = 0;

	/** A "Modifier" object, to decode modifiers of fields/methods */
	Modifier m = new Modifier();

	/** Simple main program, construct self, process each .ZIP file
	 * found in CLASSPATH.
	 */
	public static void main(String[] argv) {
		APIRef xref = new APIRef();

		for (int i=0; i<argv.length; i++) {
			String cand = argv[i];
			// System.err.println("Trying path " + cand);
			if (cand.endsWith(".zip") || cand.endsWith(".jar"))
				xref.processOneZip(cand);
		}
		System.exit(0);
	}

	/** For each Zip file, for each entry, xref it */
	public void processOneZip(String classes) {
			try {
				ZipFile zippy = 
				new ZipFile(new File(classes));
				Enumeration all = zippy.entries();
				while (all.hasMoreElements()) {
					doClass(((ZipEntry)(all.nextElement())).getName());
				}
			} catch (IOException err) {
				System.err.println("IO Error: " + err);
				return;
			}
	}

	/** Format the fields and methods of one class, given its name.
	 */
	protected void doClass(String zipName) {
		// Ignore package/directory, other odd-ball stuff.
		if (zipName.endsWith("/")) {
			return;
		}
		if (zipName.startsWith("META-INF/")) {
			return;
		}
		if (!zipName.endsWith(".class")) {
			System.err.println("Not a class: " + zipName);
			return;
		}
	
		// Convert the zip file entry, like
		//	java/lang/Math.class
		// to a class name like
		//	java.lang.Math
		String className = zipName.replace('/', '.').
			substring(0, zipName.length() - 6);	// 6 for ".class"
		// System.err.println("ZipName " + zipName + 
		//	"; className " + className);
		try {
			Class c = Class.forName(className);
			printClass(c);
		} catch (ClassNotFoundException e) {
			System.err.println("Error: Class " + 
				className + " not found!");
		} catch (Exception e) {
			System.err.println(e);
		}
		// System.err.println("in gc...");
		System.gc();
		// System.err.println("done gc");
	}

	/**
	 * Print the fields and methods of one class.
	 */
	protected void printClass(Class c) {
		int i, mods;
		String className = c.getName();
		System.out.println(className + " " + c);
		try {
			Field fields[] = c.getFields();
			for (i = 0; i < fields.length; i++) {
				System.out.println(className + " " + fields[i]);
			}

			Method methods[] = c.getMethods();
			for (i = 0; i < methods.length; i++) {
				System.out.println(className + " " + methods[i]);
			}
		} catch (Exception e) {
			System.err.println(e);
		}
	}

	/** put a Field's information to the standard output.
	 * Marked protected so you can override it (hint, hint).
	 */
	protected void putField(Field fld, Class c) {
		println(fld.getName() + " field " + c.getName() + " ");
		++n;
	}
	/** put a Method's information to the standard output.
	 * Ignores ubiquitous methods listed in the "if" statement.
	 * Marked protected so you can override it (hint, hint).
	 */
	protected void putMethod(Method meth, Class c) {
		String methName = meth.getName();
		if (methName.equals("wait") ||
			methName.equals("notify") ||
			methName.equals("toString"))
			return;
		println(methName + " method " + c.getName() + " ");
		++n;
	}

	/** Convenience routine, short for System.out.println */
	private final void println(String s) {
		System.out.println(s);
	}
}