import java.sql.*; import java.util.*; /** * Facade pattern implementation * for JDBC * This init method creates the * connection to the database and retrieves * additional database information. * @author Douglas Lyon * @version 1.00 */ public class MetaBean { private String url = null; private String driver = null; private String userId = null; private String password = null; private Connection c = null; private Statement statement = null; private DatabaseMetaData dbmd = null; private ResultSet rs = null; private ResultSetMetaData rsmd = null; private ResultSet rs_tabletypes = null; private boolean isReadOnly = false; private boolean usesLocalFiles = false; private String driverName = null; private String catalogName = null; private String productName = null; private String keyWords = null; private String tablename = null; private String currentquery= null; private String tableFields[]= null; private String tableNames[] = null; private String nonMSysTables[] = null; /** * Determines if database * uses a local file. * * The value is set using the DatabaseMetaData. * usesLocalFiles() method * contained in the java.sql package. This method is called and this value is * set in this classes init() method. * * @return true if it does, false if not */ public boolean getUsesLocalFiles() { return usesLocalFiles; } /** * Gets whether or not this connection to this database is read only. * * The value is set using the Connection.isReadOnly() method * contained in the java.sql package. * This method is called and this value is * set in this classes init() method. * * @return true if it is, false if not */ public boolean getReadOnly() { return isReadOnly; } /** * Gets this Connection's current catalog name. * * The value is set using the Connection.getCatalog() method * contained in the java.sql package. This method is called and this value is * set in this classes init() method. * * @return the current catalog name or null */ public String getCatalogName() { return catalogName; } /** * Gets the name of this JDBC driver. * * The value is set using the DatabaseMetaData.getDriverName() method * contained in the java.sql package. This method is called and this value is * set in this classes init() method. * * @return the JDBC Driver name */ public String getDriverName() { return driverName; } /** * Gets the name of this database product. * * The value is set using the DatabaseMetaData.getDatabaseProductName() method * contained in the java.sql package. This method is called and this value is * set in this classes init() method. * * @return the database product name */ public String getProductName() { return productName; } /** * Gets the ResultSet contained in this instance variable rs. * * @return this classes ResultSet */ public ResultSet getResultSet() { return rs; } /** * Gets the value of this current table name. * * The value is set using the SqlBean.setTableName() method * * @return the current table name */ public String getTableName() { return tablename; } /** * Gets the value of this current SQL. * * The value is set using the SqlBean.query() method * * @return the current SQL query */ public String getCurrentQuery() { return currentquery; } /** * Gets the table names contained in this current database. * * The table names are placed in a ResultSet using the DatabaseMetaData. * getTables() method * From the ResultSet, the tables are added to a vector and then * converted into a String array. This method can be used at anytime after the init() * method is called to set the DataBaseMetaData. * * @return the table names */ public String[] getTableNames() { Vector tableVector = new Vector(); try { rs = dbmd.getTables(null,null,null,null); rsmd = rs.getMetaData(); while (rs.next()) tableVector.addElement(rs.getString("TABLE_NAME")); } catch(SQLException e) { print(e); } int n = tableVector.size(); tableNames =new String[n]; for (int i=0; i < n; i++) tableNames[i] = (String)tableVector.elementAt(i); return tableNames; } /** * Gets the names of all the Non-System Tables in this Database. * * Retrieves all the tables using the getTableNames() method. Then uses the * getNumberOfMSysTables() to determine the number of SystemTables contained in the * database and places those names in a String array. This method can be used at anytime * after the init() method is called to set the DataBaseMetaData. * * @return the names of the non-system tables */ public String[] getNonMSysTables() { String tn[] = getTableNames(); int n = tableNames.length - getNumberOfMSysTables(); nonMSysTables = new String[n]; for (int i=0; i < n; i++) nonMSysTables[i]= tn[i+getNumberOfMSysTables()]; return nonMSysTables; } /** * Gets the number of the System Tables in this Database. * * Used to help determine the table names in the getNonMSysTables() method. * Determine the number of SystemTables contained in the database my searching for * names starting with MSys. * * @return the number of system tables */ private int getNumberOfMSysTables() { int k = 0; for (int i=0; i < tableNames.length; i++) if (tableNames[i].startsWith("MSys")) k++; return k; } /** * Gets the table types available in this database connection. The results are ordered by table type. * * The results are ordered by table type. Typical types are: *
"TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL", "TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM". * * @return the current SQL query */ public ResultSet getTableTypes() { return rs_tabletypes; } /** * Sets this classes resultset instance variable, rs, based on a provided SQL query. * * @param myquery the SQL query */ public void setResultSet(String myquery) { rs = query(myquery); } /** * Sets this classes instance variable, userId, for this database connection. * * This is the database user on whose behalf the Connection is being made for * * @param _userID the database UserId */ public void setUserId(String _userId) { userId = _userId; } /** * Sets this classes instance variable, password, for this database connection. * * The password associated with the database user on whose behalf the * Connection is being made for. * * @param _password the database Password */ public void setPassword(String _password) { password = _password; } /** * Sets this classes instance variable, url, for this database url. * * The url is in the form of jdbc:subprotocol:subname * * @param _url the database url */ public void setUrl(String _url) { url = _url; } /** * Sets the name of the instance variable, driver, which this class is loadeding. * * This is the string representation of the driver being loaded to make the connection to the database. * * @param _driver the driver name */ public void setDriver(String _driver) { driver = _driver; } /** * Sets this classes instance variable, tablename, for the current database tablename. * * @param _tablename the database tablename */ public void setTableName(String _tablename) { tablename = _tablename; } /** * Constructor. */ public MetaBean() { } /** * Loads specified driver and initializes the Connection to this Database. * *

Loads the driver and Connects to the Database *
Retrieves and sets Database/ Connection Information as follows: *
    MetaData of this Database *
    Read Only Property *
    Uses Local Files Property *
    Driver Name Used for the Connection *
    Database Product Name *
    Table Types in this Database */ public void init() { try { Class.forName(driver); c = DriverManager.getConnection(url,userId,password); dbmd = c.getMetaData(); catalogName = c.getCatalog(); isReadOnly = c.isReadOnly(); usesLocalFiles = dbmd.usesLocalFiles(); driverName = dbmd.getDriverName(); productName = dbmd.getDatabaseProductName(); rs_tabletypes = dbmd.getTableTypes(); } catch (ClassNotFoundException e) { println(e); } catch (SQLException e) { print(e); } System.out.println("Opened Connection:"+url); } /** * Prints information about this database connection. *

*
Prints the following information: *
    The name of this database product *
    This Connection's current catalog name *
    Is this connection in read-only mode *
    Does this database store tables in a local files *
    The name of this JDBC driver *
    The SQL keywords of this database *
    The table types of all the tables in this database *
    The names of all the tables in this database *
    The names of all the non-system tables in this database */ public void printDataBaseInfo() { println("*****"); println("productName="+productName); println("*****"); println("catalogName="+catalogName); println("*****"); println("is ReadOnly="+getReadOnly()); println("*****"); println("usesLocalFiles="+getUsesLocalFiles()); println("*****"); println("driverName="+driverName); println("*****"); println("Non SL92 keywords:"); println(getKeyWords()); println("*****"); println("TableTypes:"); print(getTableTypes()); println("*****"); println("TableNames - All:"); println(getTableNames()); println("*****"); println("TableNames - NonSystem:"); println(getNonMSysTables()); } /** * Prints information about this current ResultSet. *

*
Prints the following information: *
    The column names (fields) of this database *
    The type name of the columns (fields) used by this database * * @param _rs the current ResultSet */ public void printResultSetInfo(ResultSet _rs) { println("*****"); println("Column Names:"); println(getTableFields(getResultSetMetaData(_rs))); println("*****"); println("Column Types:"); println(getColumnTypeNames(getResultSetMetaData(_rs))); println("*****"); println("Number of Rows:"); println(Integer.toString((getNumberofRows(getRows(_rs))))); println("*****"); println("Print The First Row:"); } /** * Closes the connections to this database. */ public void close() { try { rs.close(); rs_tabletypes.close(); statement.close(); c.close(); System.out.println("closed connection"); } catch (SQLException e) { print(e); } } /** * Creates a Result Set based on an sql query. * * @param _sql the sql query * @return the ResultSet */ public ResultSet query(String sql) { try { statement = c.createStatement (); currentquery = sql; return statement.executeQuery(sql); } catch (SQLException e) { print(e); } return null; } /** * Gets the MetaData for a specified ResultSet. * * @param _rs the ResultSet * @return the ResultSetMetaData */ public ResultSetMetaData getResultSetMetaData(ResultSet _rs) { try { return _rs.getMetaData(); } catch(SQLException e) { print(e); } return null; } /** * Gets the number of columns in a ResultSet. * * @param _rsmd the ResultSetMetaData * @return number of Columns (fields) */ public int getColumnCount(ResultSetMetaData _rsmd) { try { return _rsmd.getColumnCount(); } catch(SQLException e) { print(e); } return 0; } /** * Gets the keywords associated with this database. * * @return the keywords */ public String getKeyWords(){ try{ return dbmd.getSQLKeywords(); } catch (SQLException e) { print(e); } return null; } /** * Gets the database types of the columns in a ResultSet. * * These are the type name used by this database. If the column type is a user-defined type, * then a fully-qualified type name is returned. * * @param _rsmd the ResultSetMetaData * @return the column types */ public String [] getColumnTypeNames(ResultSetMetaData _rsmd) { int count = getColumnCount(_rsmd); String sa [] = new String[count]; try { for (int i=0; i < sa.length; i++) { sa[i] = _rsmd.getColumnTypeName(i+1); } } catch(SQLException e) { print(e); } return sa; } /** * Converts a row in a ResultSet to a String. * * @param _rs the ResultSet pointed to a particular row * @return the contents of the ResultSet */ public String [] getRowAsString(ResultSet _rs) { int N = getColumnCount(getResultSetMetaData(_rs)); String s[] = new String[N]; try { for (int i =0; i < N; i++) s[i] = _rs.getString(i+1); } catch(SQLException e) { print(e); } return s; } /** * Converts a ResultSet to a Vector of Strings. * * @param _rs the ResultSet * @return the vector containing the ResultSet with each row as a String */ public Vector getRows(ResultSet _rs) { Vector v = new Vector(); while(nextRow(_rs)) v.addElement(getRowAsString(_rs)); return v; } /** * Returns the size of a vector. Used with the getRows() method that converts a ResultSet to a vector. * * @param v the Vector * @return the number of rows */ public int getNumberofRows(Vector v) { return v.size(); } /** * Moves to the top of this RecordSet. * * @param _rs the ResultSet */ public void moveToTop(ResultSet _rs) { try{ _rs.beforeFirst(); } catch(SQLException e) { print(e); } } /** * Prints the contents of a provided ResultSet. * * @param _rs the ResultSet */ public void print(ResultSet _rs) { int i; String cn[] = getTableFields(getResultSetMetaData(_rs)); println(cn); boolean more = false; while (more = nextRow(_rs)) println(getRowAsString(_rs)); } /** * Prints the contents of a provided Object. * Uses the toString() method for the * provided object. * * @param o the Object */ public void println(Object o) { System.out.println(o); } /** * Prints the contents of a String array. * * @param s[] the array */ public void println(String s[]) { for (int i=0; i < s.length; i++) System.out.print(s[i]+'\t'); System.out.println(); } /** * Prints messages about this SQL Exception. * * @param ex the exception */ private void print(SQLException ex) { println ("\n*** SQLException caught ***\n"); while (ex != null) { println ("SQLState: " + ex.getSQLState ()); println ("Message: " + ex.getMessage ()); println ("Vendor: " + ex.getErrorCode ()); ex = ex.getNextException (); println (""); } ex.printStackTrace (); } /** * Moves to the next row of a provided ResultSet. * * @param _rs the ResultSet */ public boolean nextRow(ResultSet _rs) { try { return _rs.next(); } catch(SQLException e) { return false; } } /** * Gets the names of the columns (fields) in a provided ResultSet. * * @param _rs the ResultSetMetaData * @return the table names */ public String[] getTableFields(ResultSetMetaData _rsmd) { String s [] = new String[getColumnCount(_rsmd)]; try { for (int i=1; i <= s.length; i++) s[i-1]=_rsmd.getColumnLabel(i); } catch(SQLException e) { print(e); } tableFields = s; return s; } /** * Gets this DataBaseMetaData object. * * @return this DataBaseMetaData */ public DatabaseMetaData getDatabaseMetaData() { return dbmd; } /** * Process an SQL INSERT, DELETE or UPDATE statement string. * * Additionally, this could be an SQL * statement that returns nothing such as SQL DDL statments. * * @param sql the SQL INSERT, UPDATE or DELETE statement * or an SQL statement that returns nothing */ public void modifyDatabase(String sql) { try { Statement s = c.createStatement(); int insertResult = s.executeUpdate(sql); println("UPDATE SUCCESSFUL"); println("SQL Statment= " + sql); } catch (SQLException e) { println("UPDATE NOT SUCCESSFUL"); println("SQL Statment= " + sql); print(e); } } /** * Main entry point for application. * * @param args[] the command line arguments */ public static void main(String args[]) { MetaBean sb = new MetaBean(); // The driver and DSN are parameters. sb.setUrl("jdbc:odbc:Addresses"); sb.setDriver("sun.jdbc.odbc.JdbcOdbcDriver"); sb.setUserId(""); sb.setPassword(""); sb.println("Calling Init Method"); sb.init(); sb.println("****************"); sb.println("Tables"); sb.println(sb.getTableNames()); // the following are not standard... String tn[] = sb.getNonMSysTables(); sb.println(tn); sb.println("****************"); sb.println("Calling printDataBaseInfo Method"); sb.printDataBaseInfo(); sb.setTableName(tn[0]); // table name is a parameter we got from // the data base itself. // There might have been more than one.... sb.println("****************"); sb.println( "Calling printResultSetInfo Method for Table Name: " + sb.getTableName()); sb.printResultSetInfo( sb.query("SELECT * FROM "+ sb.getTableName())); sb.println("****************"); sb.println("Calling Method to Print the Result Set for Table Name: " + sb.getTableName() ); sb.print(sb.query( "SELECT * FROM " +sb.getTableName())); sb.close(); } }