FileDocCategorySizeDatePackage
RevEngAPI.javaAPI DocExample5743Sat May 29 21:43:44 BST 2004None

RevEngAPI

public class RevEngAPI extends APIFormatter
Make up a compilable version of a given Sun or other API, so developers can compile against it without a licensed copy. In Sun's case, all public API info is public on Sun's web site, so this does not disclose anything that is Sun Confidential.

This is a clean-room implementation: I did not look at the code for Sun's javap or any similar tool in preparing this program. XXX TODO:

  • Class printing: add superclasses.
  • Collapse common code in printing Constructors and Methods
  • Method printing: add exceptions
  • Arguments: Handle arrays (names begin [L)
  • Provide default (0, false, null) based on type; use in return statements and in assigment to protected final variables.
author
Ian Darwin, http://www.darwinsys.com/
version
$Id: RevEngAPI.java,v 1.11 2004/05/30 01:43:43 ian Exp $

Fields Summary
private static final String
PREFIX_ARG
private String
className
NOT THREAD SAFE
private int
classNameOffset
private ModInfo[]
modInfo
Constructors Summary
Methods Summary
private java.lang.StringdefaultValue(java.lang.Class c)

		if (c.getName().equals("boolean"))
			return "false";
		// XXX else if object type return null;
		else return "0";
	
public voiddoClass(java.lang.Class c)
Generate a .java file for the outline of the given class.

		className = c.getName();
		// pre-compute offset for stripping package name
		classNameOffset = className.lastIndexOf('.") + 1;

		// Inner class
		if (className.indexOf('$") != -1)
			return;

		// get name, as String, with . changed to /
		String slashName = className.replace('.",'/");
		String fileName = slashName + ".java";

		System.out.println(className + " --> " + fileName);

		String dirName = slashName.substring(0, slashName.lastIndexOf("/"));
		new File(dirName).mkdirs();

		// create the file.
		PrintWriter out = new PrintWriter(new FileWriter(fileName));

		out.println("// Generated by RevEngAPI for class " + className);

		// If in a package, say so.
		Package pkg;
		if ((pkg = c.getPackage()) != null) {
			out.println("package " + pkg.getName() + ';");
			out.println();
		}
		// print class header
		int cMods = c.getModifiers();
		printMods(cMods, out);
		out.print("class ");
		out.print(trim(c.getName()));
		out.print(' ");
		// XXX get superclass 
		out.println('{");

		// print constructors
		Constructor[] ctors = c.getDeclaredConstructors();
		for (int i=0; i< ctors.length; i++) {
			if (i == 0) {
				out.println();
				out.println("\t// Constructors");
			}
			Constructor cons = ctors[i];
			int mods = cons.getModifiers();
			if (Modifier.isPrivate(mods))
				continue;
			out.print('\t");
			printMods(mods, out);
			out.print(trim(cons.getName()) + "(");
			Class[] classes = cons.getParameterTypes();
			for (int j = 0; j<classes.length; j++) {
				if (j > 0) out.print(", ");
				out.print(trim(classes[j].getName()) + ' " + 
						mkName(PREFIX_ARG, j));
			}
			out.println(") {");
			out.print("\t}");
		}

		// print method names
		Method[] mems = c.getDeclaredMethods();
		for (int i=0; i< mems.length; i++) {
			if (i == 0) {
				out.println();
				out.println("\t// Methods");
			}
			Method m = mems[i];
			if (m.getName().startsWith("access$"))
				continue;
			int mods = m.getModifiers();
			if (Modifier.isPrivate(mods))
				continue;
			out.print('\t");
			printMods(mods, out);
			out.print(m.getReturnType());
			out.print(' ");
			out.print(trim(m.getName()) + "(");
			Class[] classes = m.getParameterTypes();
			for (int j = 0; j<classes.length; j++) {
				if (j > 0) out.print(", ");
				out.print(trim(classes[j].getName()) + ' " + 
						mkName(PREFIX_ARG, j));
			}
			out.println(") {");
			out.println("\treturn " + defaultValue(m.getReturnType()) + ';");
			out.println("\t}");
		}

		// print fields
		Field[] flds = c.getDeclaredFields();
		for (int i=0; i< flds.length; i++) {
			if (i == 0) {
				out.println();
				out.println("\t// Fields");
			}
			Field f = flds[i];
			int mods = f.getModifiers();
			if (Modifier.isPrivate(mods))
				continue;
			out.print('\t");
			printMods(mods, out);
			out.print(trim(f.getType().getName()));
			out.print(' ");
			out.print(f.getName());
			if (Modifier.isFinal(mods)) {
				try {
					out.print(" = " + f.get(null));
				} catch (IllegalAccessException ex) {
					out.print("; // " + ex.toString());
				}
			}
			out.println(';");
		}
		out.println("}");
		//out.flush();
		out.close();
	
public voidendFile()

		// XXX generate a trivial "build.xml" for Ant to create the jar file.
	
public static voidmain(java.lang.String[] argv)

		new RevEngAPI().doArgs(argv);
	
private java.lang.StringmkName(java.lang.String name, int number)
Make up names like "arg0" "arg1", etc.

	        
	      
		return new StringBuffer(name).append(number).toString();
	
private voidprintMods(int mods, java.io.PrintWriter out)


	      
		for (int i=0; i < modInfo.length; i++) {
			if ((mods & modInfo[i].val) == modInfo[i].val) {
				out.print(modInfo[i].name);
				out.print(' ");
			}
		}
	
public voidstartFile()

		// XXX save filename as project name
	
private java.lang.Stringtrim(java.lang.String theName)

		return theName.startsWith(className) ?
			theName.substring(classNameOffset) : theName;