FileDocCategorySizeDatePackage
MakeAPIDB.javaAPI DocExample7277Sat Jun 02 02:42:20 BST 2001None

MakeAPIDB.java

// This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com)
// Copyright (c) 1997 by David Flanagan
// This example is provided WITHOUT ANY WARRANTY either expressed or implied.
// You may study, use, modify, and distribute it for non-commercial purposes.
// For any commercial use, see http://www.davidflanagan.com/javaexamples

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

/**
 * This class is a standalone program that reads a list of classes and 
 * builds a database of packages, classes, and class fields and methods.
 **/
public class MakeAPIDB {
  public static void main(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) {} }
  }

  /** 
   * 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 Hashtable package_to_id = new Hashtable();

  // Counters for the package and class identifier columns
  static int packageId = 0, classId = 0;

  // Some prepared SQL statements for use in inserting
  // new values into the tables.  Initialized in main() above.
  static PreparedStatement insertpackage, insertclass, insertmember;

  /**
   * 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.
   **/
  public static void storeClass(String name) 
       throws SQLException, ClassNotFoundException {
    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