/*
* Copyright (C) Lennart Martens
*
* Contact: lennart.martens AT UGent.be (' AT ' to be replaced with '@')
*/
/*
* Created by IntelliJ IDEA.
* User: Lennart
* Date: 17-dec-02
* Time: 14:14:26
*/
package com.compomics.util.db;
import com.compomics.util.general.CommandLineParser;
import java.sql.*;
import java.util.Properties;
import java.util.Vector;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.File;
/*
* CVS information:
*
* $Revision: 1.3 $
* $Date: 2007/07/06 09:41:53 $
*/
/**
* This class generates an Object that can be used for access to a
* given table in a JDBC accessible RDBMS.
*
* @author Lennart Martens
*/
public class DBAccessorGenerator {
/**
* Default constructor.
*/
public DBAccessorGenerator() {
}
/**
* This method starts the generator for the specified parameters.
*
* @param aDriver String with the JDBC database driver class.
* @param aUrl String with the URL for the database.
* @param aTable String with the tablename to generate the accessor object for.
* @param aPackageName String with the packagename for the generated class. Can be empty String.
* @throws GeneratorException whenever something goes wrong.
*/
public void startGenerator(String aDriver, String aUrl, String aTable, String aPackageName) throws GeneratorException {
this.startGenerator(aDriver, aUrl, aTable, null, null, aPackageName, false);
}
/**
* This method starts the generator for the specified parameters.
*
* @param aDriver String with the JDBC database driver class.
* @param aUrl String with the URL for the database.
* @param aTable String with the tablename to generate the accessor object for.
* @param aUser String with the username for the DB connection. This can be 'null'.
* @param aPassword String with the password for the specified user. This can be 'null'.
* @param aPackageName String with the output packagename. This can be empty String.
* @param aDebug boolean to indicate whether output should be given to stdout.
* @exception GeneratorException whenever something goes wrong.
*/
public void startGenerator(String aDriver, String aUrl, String aTable, String aUser, String aPassword, String aPackageName, boolean aDebug) throws GeneratorException {
// Okay, first we need to get our hands on a connection.
Connection lConn = this.getConnection(aDriver, aUrl, aUser, aPassword);
// Okay, we've got our connection, now get the MetaData.
DBMetaData dbmd = this.getMetaData(lConn, aTable);
if(aDebug) {
System.out.println("\n\n" + dbmd.toString() + "\n");
}
// Close the connection.
try {
lConn.close();
} catch(Exception e) {
System.err.println(e.getMessage());
}
// Generate the accessor class.
this.generateAccessor(dbmd, aPackageName, aDebug);
}
/**
* The main method allows to run this tool from the command-line.
*
* @param args the arguments
*/
public static void main(String[] args) {
DBAccessorGenerator dba = new DBAccessorGenerator();
CommandLineParser clp = new CommandLineParser(args, new String[]{"user", "password"});
// We should have the following parameters:
// - DBDriver
// - DBURL
// - username
// - password
// - table.
if(clp.getParameters() == null || clp.getParameters().length < 4) {
printUsage();
System.exit(1);
}
String drivername = clp.getParameters()[0];
String dburl = clp.getParameters()[1];
String tablename = clp.getParameters()[2];
String packageName = clp.getParameters()[3];
String username = clp.getOptionParameter("user");
String password = clp.getOptionParameter("password");
if(drivername == null || dburl == null || tablename == null || packageName == null) {
printUsage();
} else {
try {
dba.startGenerator(drivername, dburl, tablename, username, password, packageName, true);
System.out.println("\n\nGeneration complete!\n");
} catch(GeneratorException ge) {
System.err.println("\nGenerator encountered the following exception: \n\n" + ge.getMessage() + "\n\n");
}
}
}
/**
* This method prints the usage of this class to stderr.
*/
private static void printUsage() {
System.err.println("\n\nUsage:\n");
System.err.println("\tDBAccessGenerator [--user <username> --password <password>] <DBDriver> <DBURL> <tablename> <outputpackage>\n");
}
/**
* This method attempts to create a Database connection.
*
* @param aDriver String with the JDBC database driver class.
* @param aUrl String with the URL for the database.
* @param aUser String with the username for the DB connection. This can be 'null'.
* @param aPassword String with the password for the specified user. This can be 'null'.
* @exception GeneratorException whenever a connection could not be established.
*/
private Connection getConnection(String aDriver, String aUrl, String aUser, String aPassword) throws GeneratorException {
Driver d = null;
Connection lConn = null;
// Instantiate the Driver.
try {
d = (Driver)Class.forName(aDriver).newInstance();
} catch(ClassNotFoundException cnfe) {
throw new GeneratorException("Unable to locate driver class ('" + aDriver + "')!", cnfe);
} catch(InstantiationException ie) {
throw new GeneratorException("Unable to instantiate driver using default constructor ('" + aDriver + "')!", ie);
} catch(IllegalAccessException iae) {
throw new GeneratorException("Unable to access default constructor for driver ('" + aDriver + "')!", iae);
}
// Connect (with credentials, if supplied).
Properties lProps = new Properties();
if(aUser != null && aPassword != null) {
lProps.put("user", aUser);
lProps.put("password", aPassword);
}
try {
lConn = d.connect(aUrl, lProps);
if(lConn == null) {
throw new SQLException("Connection was 'null'; perhaps USER and PASSWORD required?!");
}
} catch(SQLException sqle) {
throw new GeneratorException("Unable to connect to database at URL '" + aUrl + "' with driver '" + aDriver + "'!", sqle);
}
return lConn;
}
/**
* This method attempts to extract metadata about the table from the DB.
*
* @param lConn Connection to read from.
* @param aTable String with the tablename.
* @return DBMetaData with the metadata for the specified table.
* @exception GeneratorException when metadata could not be read.
*/
private DBMetaData getMetaData(Connection lConn, String aTable) throws GeneratorException {
// Get the metadata.
DatabaseMetaData meta = null;
try {
meta = lConn.getMetaData();
} catch(SQLException sqle) {
throw new GeneratorException("Unable to read MetaData on database!", sqle);
}
Vector names = new Vector();
Vector types = new Vector();
Vector sizes = new Vector();
// Read columnmetadata for our table.
try {
ResultSet rs = meta.getColumns(null, "", aTable, "%");
boolean once = false;
while(rs.next()) {
names.add(rs.getString("COLUMN_NAME"));
types.add(Integer.valueOf(rs.getInt("DATA_TYPE")));
sizes.add(Integer.valueOf(rs.getInt("COLUMN_SIZE")));
once = true;
}
rs.close();
if(!once) {
throw new SQLException("No columns found in table '" + aTable + "'!");
}
} catch(SQLException sqle) {
throw new GeneratorException("Unable to get column metadata from database!", sqle);
}
// Get the primary key columns.
Vector pkColumns = new Vector(5, 2);
try {
ResultSet rs = meta.getPrimaryKeys(null, "", aTable);
boolean once = false;
while(rs.next()) {
pkColumns.add(rs.getString("COLUMN_NAME"));
once = true;
}
if(!once) {
throw new SQLException("No primary key columns found in table '" + aTable + "'!");
}
rs.close();
} catch(SQLException sqle) {
throw new GeneratorException("Unable to get primary key columns from database for table " + aTable + "!", sqle);
}
// Initialize metadata wrapper and return.
DBMetaData dbmd = new DBMetaData(aTable, names, types, sizes, pkColumns);
return dbmd;
}
/**
* This method generates an accessor class code for a table
* with the specified metadata.
*
* @param aDBMD DBMetaData with the metadata for the table to generate the
* accessor for.
* @param aPackageName String with the output package name.
* @param aDebug boolean to indicate whether output to stdout is desired.
* @exception GeneratorException when the accessor ciold not be generated.
*/
private void generateAccessor(DBMetaData aDBMD, String aPackageName, boolean aDebug) throws GeneratorException {
DBAccessor dba = new DBAccessor(aDBMD, aPackageName, aDebug);
// Test output.
String name = aDBMD.getTableName();
name = name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase() + "TableAccessor";
try {
String outputPath = aPackageName.replace('.', '/').trim();
if(!outputPath.endsWith("/")) {
outputPath = outputPath + "/";
}
File dir = new File(outputPath);
if(!dir.exists()) {
if(!dir.mkdirs()) {
throw new GeneratorException("Unable to generate outputpath: " + outputPath + ".");
}
}
BufferedWriter bw = new BufferedWriter(new FileWriter(outputPath + name + ".java"));
bw.write(dba.toString());
bw.flush();
bw.close();
} catch(Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}