/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.client.jdbc;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.log4j.Logger;
import com.alipay.zdal.client.config.DataSourceConfigType;
import com.alipay.zdal.client.dispatcher.SqlDispatcher;
import com.alipay.zdal.client.util.ExceptionUtils;
/**
*
* @author ����
* @version $Id: ZdalConnection.java, v 0.1 2014-1-6 ����05:02:15 Exp $
*/
public class ZdalConnection implements Connection {
private static final Logger logger = Logger
.getLogger(ZdalConnection.class);
private Map<String, DBSelector> dbSelectors;
private SqlDispatcher writeDispatcher;
private SqlDispatcher readDispatcher;
private int retryingTimes;
private String username;
private String password;
// ZdalConnection���������е��������ݿ�����
private Map<String, ConnectionAndDatasource> actualConnections = new HashMap<String, ConnectionAndDatasource>();
private boolean autoCommit = true;
private int transactionIsolation = -1;
private boolean closed;
private boolean readOnly;
private boolean txStart;
private String txTarget;
// TConnection����������TStatement������TPreparedStatement����
private Set<ZdalStatement> openStatements = new HashSet<ZdalStatement>();
private DataSourceConfigType dbConfigType = null;
/** ����Դ������*/
protected String appDsName = null;
public ZdalConnection() {
}
public ZdalConnection(String username, String password) {
this.username = username;
this.password = password;
}
public DatabaseMetaData getMetaData() throws SQLException {
checkClosed();
// TODO: DatabaseMetaDataĿǰ��������Ԫ���ݵ���Ϣ
return new ZDatabaseMetaData();
}
public boolean getAutoCommit() throws SQLException {
checkClosed();
return autoCommit;
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
checkClosed();
this.autoCommit = autoCommit;
this.txStart = !autoCommit;
}
public int getTransactionIsolation() throws SQLException {
checkClosed();
return transactionIsolation;
}
public void setTransactionIsolation(int transactionIsolation) throws SQLException {
checkClosed();
this.transactionIsolation = transactionIsolation;
}
public Statement createStatement() throws SQLException {
checkClosed();
ZdalStatement stmt = new RetryableTStatement(writeDispatcher, readDispatcher);
stmt.setDataSourcePool(dbSelectors);
// stmt.setHintReplaceSupport(isHintReplaceSupport);
//stmt.setRuleController(ruleController);
stmt.setAutoCommit(autoCommit);
stmt.setReadOnly(readOnly);
stmt.setConnectionProxy(this);
stmt.setRetryingTimes(retryingTimes);
// stmt.setPoolRandom(poolRandom);
stmt.setDbConfigType(dbConfigType);
stmt.setAppDsName(getAppDsName());
openStatements.add(stmt);
return stmt;
}
public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
ZdalStatement stmt = (ZdalStatement) createStatement();
stmt.setResultSetType(resultSetType);
stmt.setResultSetConcurrency(resultSetConcurrency);
return stmt;
}
public Statement createStatement(int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
ZdalStatement stmt = (ZdalStatement) createStatement(resultSetType, resultSetConcurrency);
stmt.setResultSetHoldability(resultSetHoldability);
return stmt;
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
checkClosed();
ZdalPreparedStatement stmt = new RetryableTPreparedStatement(writeDispatcher,
readDispatcher);
stmt.setDataSourcePool(dbSelectors);
stmt.setAutoCommit(autoCommit);
stmt.setReadOnly(readOnly);
stmt.setConnectionProxy(this);
stmt.setSql(sql);
stmt.setRetryingTimes(retryingTimes);
stmt.setDbConfigType(dbConfigType);
stmt.setAppDsName(getAppDsName());
openStatements.add(stmt);
return stmt;
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
ZdalPreparedStatement stmt = (ZdalPreparedStatement) prepareStatement(sql);
stmt.setResultSetType(resultSetType);
stmt.setResultSetConcurrency(resultSetConcurrency);
return stmt;
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
ZdalPreparedStatement stmt = (ZdalPreparedStatement) prepareStatement(sql, resultSetType,
resultSetConcurrency);
stmt.setResultSetHoldability(resultSetHoldability);
return stmt;
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
ZdalPreparedStatement stmt = (ZdalPreparedStatement) prepareStatement(sql);
stmt.setAutoGeneratedKeys(autoGeneratedKeys);
return stmt;
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
ZdalPreparedStatement stmt = (ZdalPreparedStatement) prepareStatement(sql);
stmt.setColumnIndexes(columnIndexes);
return stmt;
}
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
ZdalPreparedStatement stmt = (ZdalPreparedStatement) prepareStatement(sql);
stmt.setColumnNames(columnNames);
return stmt;
}
public CallableStatement prepareCall(String sql) throws SQLException {
throw new UnsupportedOperationException("prepareCall");
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
throw new UnsupportedOperationException("prepareCall");
}
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
throw new UnsupportedOperationException("prepareCall");
}
public void commit() throws SQLException {
if (logger.isDebugEnabled()) {
logger.debug("invoke commit");
}
checkClosed();
if (autoCommit) {
return;
}
txStart = true;
List<SQLException> exceptions = null;
for (Map.Entry<String, ConnectionAndDatasource> entry : actualConnections.entrySet()) {
try {
entry.getValue().connection.commit();
} catch (SQLException e) {
if (exceptions == null) {
exceptions = new ArrayList<SQLException>();
}
exceptions.add(e);
logger.error(new StringBuilder("data source name: ").append(entry.getKey())
.toString(), e);
}
}
ExceptionUtils.throwSQLException(exceptions, null, null);
}
public void rollback() throws SQLException {
if (logger.isDebugEnabled()) {
logger.debug("invoke rollback");
}
checkClosed();
if (autoCommit) {
return;
}
txStart = true;
List<SQLException> exceptions = null;
for (Map.Entry<String, ConnectionAndDatasource> entry : actualConnections.entrySet()) {
try {
entry.getValue().connection.rollback();
} catch (SQLException e) {
if (exceptions == null) {
exceptions = new ArrayList<SQLException>();
}
exceptions.add(e);
logger.error(new StringBuilder("data source name: ").append(entry.getKey())
.toString(), e);
}
}
ExceptionUtils.throwSQLException(exceptions, null, null);
}
public void rollback(Savepoint savepoint) throws SQLException {
throw new UnsupportedOperationException("rollback");
}
public Savepoint setSavepoint() throws SQLException {
throw new UnsupportedOperationException("setSavepoint");
}
public Savepoint setSavepoint(String name) throws SQLException {
throw new UnsupportedOperationException("setSavepoint");
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
throw new UnsupportedOperationException("releaseSavepoint");
}
protected void checkClosed() throws SQLException {
if (closed) {
throw new SQLException("No operations allowed after connection closed.");
}
}
public boolean isClosed() throws SQLException {
return closed;
}
public void close() throws SQLException {
if (logger.isDebugEnabled()) {
logger.debug("invoke close");
}
if (closed) {
return;
}
List<SQLException> exceptions = null;
try {
for (ZdalStatement stmt : openStatements) {
try {
//bug fix by shenxun :���ﲻ�����ڲ�����remove�ķ����������ⲿ��ʾ�ĵ��ø÷���
//����bug����Ҫԭ���ǵ�set�����size����1�������ҵ���remove����ʱ�ᷢ����ʱ��HashSet����modification.
stmt.closeInternal(false);
} catch (SQLException e) {
if (exceptions == null) {
exceptions = new ArrayList<SQLException>();
}
exceptions.add(e);
}
}
for (Map.Entry<String, ConnectionAndDatasource> entry : actualConnections.entrySet()) {
try {
entry.getValue().connection.close();
} catch (SQLException e) {
if (exceptions == null) {
exceptions = new ArrayList<SQLException>();
}
exceptions.add(e);
logger.error(new StringBuilder("data source name: ").append(entry.getKey())
.toString(), e);
}
}
} finally {
closed = true;
openStatements.clear();
actualConnections.clear();
}
ExceptionUtils.throwSQLException(exceptions, null, null);
}
public boolean isReadOnly() throws SQLException {
checkClosed();
return readOnly;
}
public void setReadOnly(boolean readOnly) throws SQLException {
checkClosed();
this.readOnly = readOnly;
}
public String getCatalog() throws SQLException {
throw new UnsupportedOperationException("getCatalog");
}
public void setCatalog(String catalog) throws SQLException {
throw new UnsupportedOperationException("setCatalog");
}
public int getHoldability() throws SQLException {
throw new UnsupportedOperationException("getHoldability");
}
public void setHoldability(int holdability) throws SQLException {
throw new UnsupportedOperationException("setHoldability");
}
public SQLWarning getWarnings() throws SQLException {
// TODO:
return null;
}
public void clearWarnings() throws SQLException {
// TODO:
}
public Map<String, Class<?>> getTypeMap() throws SQLException {
throw new UnsupportedOperationException("getTypeMap");
}
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
throw new UnsupportedOperationException("setTypeMap");
}
public String nativeSQL(String sql) throws SQLException {
throw new UnsupportedOperationException("nativeSQL");
}
public Map<String, DBSelector> getDataSourcePool() {
return dbSelectors;
}
public void setDataSourcePool(Map<String, DBSelector> dbSelectors) {
this.dbSelectors = dbSelectors;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
/* public Map<String, ConnectionAndDatasource> getActualConnections() {
return actualConnections;
}*/
public ConnectionAndDatasource getConnectionAndDatasourceByDBSelectorID(String id) {
// Map<String, ConnectionAndDatasource> connectionAndDatasources = actualConnections;
ConnectionAndDatasource connectionAndDatasource = actualConnections.get(id);
return connectionAndDatasource;
}
public void put(String key, ConnectionAndDatasource connectionAndDatasource) {
actualConnections.put(key, connectionAndDatasource);
}
public ConnectionAndDatasource get(String key) {
return actualConnections.get(key);
}
public void removeConnectionAndDatasourceByID(String id) {
ConnectionAndDatasource connectionAndDatasource = actualConnections.remove(id);
if (connectionAndDatasource == null) {
logger.warn("remove by other object?");
} else {
if (connectionAndDatasource.connection == null) {
logger.warn("connection is null");
} else {
try {
connectionAndDatasource.connection.close();
} catch (SQLException e) {
logger.error("Failed to close connection", e);
}
}
}
}
public boolean containsID(String id) {
return actualConnections.containsKey(id);
}
public Set<? extends Statement> getOpenStatements() {
return openStatements;
}
public boolean getTxStart() {
return txStart;
}
public int size() {
return actualConnections.size();
}
public boolean isEmpty() {
return actualConnections.isEmpty();
}
public void setTxStart(boolean txStart) {
this.txStart = txStart;
}
public String getTxTarget() {
return txTarget;
}
public void setTxTarget(String txTarget) {
this.txTarget = txTarget;
}
public void setWriteDispatcher(SqlDispatcher writeDispatcher) {
this.writeDispatcher = writeDispatcher;
}
public void setReadDispatcher(SqlDispatcher readDispatcher) {
this.readDispatcher = readDispatcher;
}
public int getRetryingTimes() {
return retryingTimes;
}
public void setRetryingTimes(int retryingTimes) {
this.retryingTimes = retryingTimes;
}
@Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
@Override
public Blob createBlob() throws SQLException {
return null;
}
@Override
public Clob createClob() throws SQLException {
return null;
}
@Override
public NClob createNClob() throws SQLException {
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
return null;
}
@Override
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
return null;
}
@Override
public String getClientInfo(String name) throws SQLException {
return null;
}
@Override
public boolean isValid(int timeout) throws SQLException {
return false;
}
@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
public void setDbConfigType(DataSourceConfigType dbConfigType) {
this.dbConfigType = dbConfigType;
}
public DataSourceConfigType getDbConfigType() {
return dbConfigType;
}
public String getAppDsName() {
return appDsName;
}
public void setAppDsName(String appDsName) {
this.appDsName = appDsName;
}
}