// 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 |