FileDocCategorySizeDatePackage
MakeAPIDB.javaAPI DocExample8161Mon Sep 22 13:30:32 BST 1997None

MakeAPIDB

public class MakeAPIDB extends Object
This class is a standalone program that reads a list of classes and builds a database of packages, classes, and class fields and methods.

Fields Summary
static Hashtable
package_to_id
This hash table records the mapping between package names and package id. This is the only one we need to store temporarily. The others are stored in the db and don't have to be looked up by this program
static int
packageId
static int
classId
static PreparedStatement
insertpackage
static PreparedStatement
insertclass
static PreparedStatement
insertmember
Constructors Summary
Methods Summary
public static voidmain(java.lang.String[] args)

    Connection c = null;       // The connection to the database
    try { 
      // Read the names of classes to index from a file specified by args[0]
      Vector classnames = new Vector();
      BufferedReader in = new BufferedReader(new FileReader(args[0]));
      String name;
      while((name = in.readLine()) != null) classnames.addElement(name);
      
      // Now determine the values needed to set up the database connection
      // The program attempts to read a property file named "APIDB.props",
      // or optionally specified by args[1].  This property file (if any)
      // may contain "driver", "database", "user", and "password" properties
      // that specify the necessary values for connecting to the db.
      // If the properties file does not exist, or does not contain the named
      // properties, defaults will be used.
      Properties p = new Properties();              // Empty properties
      try { p.load(new FileInputStream(args[1])); } // Try to load properties
      catch (Exception e1) { 
        try { p.load(new FileInputStream("APIDB.props")); }
        catch (Exception e2) {}
      } 

      // Read values from Properties file, using the specified defaults if
      // they are not found.  These defaults will probably not work for you!
      String driver = p.getProperty("driver", "postgres95.PGDriver");
      String database = p.getProperty("database","jdbc:postgres95:///APIDB");
      String user = p.getProperty("user", "");
      String password = p.getProperty("password", "");

      // Load the database driver
      Class.forName(driver);

      // And set up a connection to the specified database
      c = DriverManager.getConnection(database, user, password);
      
      // Create three new tables for our data
      // The package table contains a package id and a package name
      // The class table contains a class id, a package id, and a class name
      // The member table contains a class id, a member name, and an int
      // that indicates whether the class member is a field or a method.
      Statement s = c.createStatement();
      s.executeUpdate("CREATE TABLE package " + 
                      "(id SMALLINT, name VARCHAR(80))");
      s.executeUpdate("CREATE TABLE class " + 
                      "(id SMALLINT, packageId SMALLINT, name VARCHAR(48))");
      s.executeUpdate("CREATE TABLE member " + 
                      "(classId SMALLINT,name VARCHAR(48),isField SMALLINT)");
      
      // Prepare some statements that will be used to insert records into
      // these three tables.
      insertpackage = c.prepareStatement("INSERT INTO package VALUES(?,?)");
      insertclass = c.prepareStatement("INSERT INTO class VALUES(?,?,?)");
      insertmember = c.prepareStatement("INSERT INTO member VALUES(?,?,?)");

      // Now loop through the list of classes and store them all in the tables
      for(int i = 0; i < classnames.size(); i++) 
        storeClass((String)classnames.elementAt(i));
    }
    catch (Exception e) {
      System.err.println(e);
      if (e instanceof SQLException)
        System.err.println("SQLState: " + ((SQLException)e).getSQLState());
      System.err.println("Usage: java MakeAPIDB <classlistfile> <propfile>");
    }
    // When we're done, close the connection to the database
    finally { try { c.close(); } catch (Exception e) {} }
  
public static voidstoreClass(java.lang.String name)
Given a fully-qualified classname, this method stores the package name in the package table (if it is not already there), stores the class name in the class table, and then uses the Java Reflection API to look up all methods and fields of the class, and stores those in the member table.


                                                         
       
          
    String packagename, classname;

    // Dynamically load the class.
    Class c = Class.forName(name);

    // Display output so the user knows that the program is progressing
    System.out.println("Storing data for: " + name);

    // Figure out the packagename and the classname
    int pos = name.lastIndexOf('.");
    if (pos == -1) {
      packagename = "";
      classname = name;
    }
    else {
      packagename = name.substring(0,pos);
      classname = name.substring(pos+1);
    }

    // Figure out what the package id is.  If there is one, then this package
    // has already been stored in the database.  Otherwise, assign an id, 
    // and store it and the packagename in the db.
    Integer pid;
    pid = (Integer)package_to_id.get(packagename);  // Check hashtable
    if (pid == null) {
      pid = new Integer(++packageId);          // Assign an id
      package_to_id.put(packagename, pid);     // Remember it in the hashtable
      insertpackage.setInt(1,packageId);       // Set args to PreparedStatement
      insertpackage.setString(2,packagename);  
      insertpackage.executeUpdate();           // Insert the package into db
    }

    // Now, store the classname in the class table of the database.
    // This record includes the package id, so that the class is linked to 
    // the package that contains it.  To store the class, we set arguments
    // to the PreparedStatement, then execute that statement
    insertclass.setInt(1, ++classId);       // Set class identifier
    insertclass.setInt(2, pid.intValue());  // Set package identifier
    insertclass.setString(3, classname);    // Set class name
    insertclass.executeUpdate();            // Insert the class record

    // Now, get a list of all non-private methods of the class, and
    // insert those into the "members" table of the database.  Each
    // record includes the class id of the containing class, and also
    // a value that indicates that these are methods, not fields.
    Method[] methods = c.getDeclaredMethods();         // Get a list of methods
    for(int i = 0; i < methods.length; i++) {          // For all non-private
      if (Modifier.isPrivate(methods[i].getModifiers())) continue;
      insertmember.setInt(1, classId);                 // Set the class id
      insertmember.setString(2, methods[i].getName()); // Set the method name
      insertmember.setInt(3, 0);                       // It is not a field
      insertmember.executeUpdate();                    // Insert the record
    }

    // Do the same thing for the non-private fields of the class
    Field[] fields = c.getDeclaredFields();            // Get a list of fields
    for(int i = 0; i < fields.length; i++) {           // For each non-private
      if (Modifier.isPrivate(fields[i].getModifiers())) continue;
      insertmember.setInt(1, classId);                 // Set the class id
      insertmember.setString(2, fields[i].getName());  // Set the field name
      insertmember.setInt(3, 1);                       // It is a field
      insertmember.executeUpdate();                    // Insert the record
    }