package org.qdao;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import org.qdao.annotation.Column;
import org.qdao.annotation.PrimaryKey;
import org.qdao.annotation.Table;
import org.qdao.core.JarClassLoader;
import org.qdao.implement.mysql.MySqlEntityDao;
import org.qdao.implement.oracle.OracleEntityDao;
/**
*
* @author 譚元吉
* @since 2010/02/06 11:00:50
*/
public abstract class AbstractDBEngine implements IDBEngine {
protected DBConfig config;
private Connection connection;
private Driver driver;
private JarClassLoader loader;
private Map<Class<?>, TableDescriptor> tableCache;
protected boolean isLogger;
// initialize the properties
private Properties info = new Properties();
protected Logger logger = Logger.getLogger( getClass().getName() );
public AbstractDBEngine() {
this(DBConfig.getInstance());
}
public AbstractDBEngine(DBConfig config) {
this.config = config;
isLogger = config.isLogger();
tableCache = new HashMap<Class<?>, TableDescriptor>();
tableCache.clear();
info.setProperty("user", config.username);
info.setProperty("password", config.password);
}
public TableDescriptor getTableDescriptor(Class<?> tableClazz) {
TableDescriptor tableDescriptor;
tableDescriptor = tableCache.get(tableClazz);
if (tableDescriptor != null) {
return tableDescriptor;
}
// TODO : use reflect to get annotation from table class
tableDescriptor = new TableDescriptor();
Table table = (Table) tableClazz.getAnnotation(Table.class);
if (table != null) {
tableDescriptor.name = table.name();
tableDescriptor.description = table.description();
}
Field[] fields = tableClazz.getDeclaredFields();
List<TableDescriptor.ColumnDescription> columnDescriptors =
new ArrayList<TableDescriptor.ColumnDescription>();
List<String> primaryKeys = new ArrayList<String>();
List<TableDescriptor.ColumnDescription> pks = new ArrayList<TableDescriptor.ColumnDescription>();
Column co;
PrimaryKey pk;
TableDescriptor.ColumnDescription cd;
/* TableDescriptor.FkDescription fkd;
String fkTableName;
ForeignKey fk;
*/ for (int i = 0; i < fields.length; i++) {
co = fields[i].getAnnotation(Column.class);
pk = fields[i].getAnnotation(PrimaryKey.class);
// fk = fields[i].getAnnotation(ForeignKey.class);
if (co != null) {
cd = new TableDescriptor.ColumnDescription();
cd.decimal = co.decimal();
cd.description = co.description();
cd.name = co.name();
cd.length = co.length();
cd.nullable = co.nullable();
cd.type = co.type();
cd.javaField = fields[i].getName();
cd.primaryKey = null != pk;
cd.autoIncrement = co.autoIncrement();
cd.defaultValue = co.defaultValue();
columnDescriptors.add(cd);
if (cd.primaryKey) {
pks.add(cd);
}
/*if (fk != null) {
table = fk.getClass().getAnnotation(Table.class);
fkTableName = null == table ? null : table.name();
if (null != fkTableName) {
fkd = new TableDescriptor.FkDescription();
fkd.foreignKeys = "(" + co.name();
fkd.references = fkTableName + " (";
}
}*/
}
if (pk != null) {
primaryKeys.add(co.name());
}
}
// set the columns
tableDescriptor.columns = columnDescriptors.toArray(
new TableDescriptor.ColumnDescription[columnDescriptors.size()]);
tableDescriptor.primaryKeys = primaryKeys.toArray(new String[primaryKeys.size()]);
tableDescriptor.pks = pks.toArray(new TableDescriptor.ColumnDescription[pks.size()]);
tableCache.put(tableClazz, tableDescriptor);
return tableDescriptor;
}
@SuppressWarnings("unchecked")
public InvocationHandler getEntityDaoHandler(Class<?> entity) {
return getEntityDaoHandler(entity, config.isLogSql());
}
@SuppressWarnings("unchecked")
public InvocationHandler getEntityDaoHandler(Class<?> entity, boolean isLogger) {
if (null == config || config.driver == null) {
return new DefaultEntityDao(this, entity, isLogger);
}
String driverLowerCase = config.driver.toLowerCase();
if (driverLowerCase.indexOf("oracle") != -1) {
return new OracleEntityDao(this, entity, isLogger);
} else if (driverLowerCase.indexOf("mysql") != -1) {
return new MySqlEntityDao(this, entity, isLogger);
}
return new DefaultEntityDao(this, entity, isLogger);
}
public IEntityDao<?> getEntityDao(Class<?> entity) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException,
InvocationTargetException, NoSuchMethodException {
InvocationHandler handler = getEntityDaoHandler(entity);
return (IEntityDao<?>) Proxy.newProxyInstance(IEntityDao.class.getClassLoader(),
// new Class[] { IEntityDao.class },
new Class[] { IEntityDao.class, InvocationHandler.class },
handler);
}
public IEntityDao<?> getEntityDao(Class<?> entity, boolean isLogger) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
InvocationHandler handler = getEntityDaoHandler(entity, isLogger);
return (IEntityDao<?>) Proxy.newProxyInstance(IEntityDao.class.getClassLoader(),
// new Class[] { IEntityDao.class },
new Class[] { IEntityDao.class, InvocationHandler.class },
handler);
}
public void dispose() {
try {
if (connection != null && !connection.isClosed()) {
connection.close();
connection = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
// judge the connection is right
if (connection == null || connection.isClosed()) {
// judge the config is right
if (config == null || !this.support(config)) {
return null;
}
// when the driver is not null then connect the url for the db with the propeties "info"
if ( null == driver ) {
Class<?> clazz = null;
try {
clazz = Class.forName( config.driver ); // use the current class loader.
} catch( Throwable e ) {
}
if ( null != clazz ) {
log( " ClassLoader 加载驱动:" + config.driver + " 成功! [WEB-INFO/LIB加载]" );
} else if ( config.validateJarPath() ){
// load the class
clazz = getLoader().loadClass(config.driver);
log( " JarClassLoader 加载驱动:" + config.driver + " 成功! [JAR文件加载]" );
}
driver = (Driver) clazz.newInstance();
}
// connect to db
connection = driver.connect(config.url, info);
}
return connection;
}
public boolean initialize(DBConfig config) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
this.config = config;
return true;
}
public boolean checkConnection()
{
Connection conn = null;
String cataLog;
boolean result = false;
try
{
conn = getConnection();
result = (null != conn);
if (result) {
cataLog = conn.getCatalog();
System.out.println(cataLog);
}
}
catch (SQLException e)
{
e.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
} finally {
if (null != conn) {
try
{
conn.close();
}
catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
conn = null;
}
}
return result;
}
// getter
public DBConfig getConfig() {
return config;
}
private JarClassLoader getLoader() {
if (loader == null) {
loader = new JarClassLoader(config.jarPath, this.getClass().getClassLoader());
}
return this.loader;
}
public Driver getDriver() {
return this.driver;
}
public void log( final Object msg ) {
if ( isLogger ) {
logger.info( String.valueOf(msg) );
}
}
}