/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.datasource.resource.adapter.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.ResultSet;
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.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.Logger;
import com.alipay.zdal.common.jdbc.sorter.ExceptionSorter;
import com.alipay.zdal.datasource.ZDataSource;
import com.alipay.zdal.datasource.exception.NestedSQLException;
/**
* A wrapper for a connection.
*
* @author ����
* @version $Id: WrappedConnection.java, v 0.1 2014-1-6 ����05:30:28 Exp $
*/
public class WrappedConnection implements Connection {
private static final Logger log = Logger.getLogger(WrappedConnection.class);
private BaseWrapperManagedConnection mc;
private WrapperDataSource dataSource;
private HashMap statements;
private boolean closed = false;
private int trackStatements;
/** ���ÿ����Ĕ���Դ*/
private ZDataSource zdatasource = null;
/**
* @param mc
*/
public WrappedConnection(final BaseWrapperManagedConnection mc) {
this.mc = mc;
if (mc != null) {
trackStatements = mc.getTrackStatements();
}
}
void setManagedConnection(final BaseWrapperManagedConnection mc) {
this.mc = mc;
if (mc != null) {
trackStatements = mc.getTrackStatements();
}
}
public WrapperDataSource getDataSource() {
return dataSource;
}
protected void setDataSource(WrapperDataSource dataSource) {
this.dataSource = dataSource;
}
public void setReadOnly(boolean readOnly) throws SQLException {
checkStatus();
try {
mc.setJdbcReadOnly(readOnly);
} catch (Throwable t) {
throw checkException(t);
}
}
public boolean isReadOnly() throws SQLException {
checkStatus();
try {
return mc.isJdbcReadOnly();
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#close()
*/
public void close() throws SQLException {
closed = true;
if (mc != null) {
if (trackStatements != BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) {
synchronized (this) {
if (statements != null) {
for (Iterator i = statements.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
WrappedStatement ws = (WrappedStatement) entry.getKey();
if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT) {
Throwable stackTrace = (Throwable) entry.getValue();
log
.warn(
"Closing a statement you left open, please do your own housekeeping",
stackTrace);
}
try {
ws.internalClose();
} catch (Throwable t) {
log.warn("Exception trying to close statement:", t);
}
}
}
}
}
mc.closeHandle(this);
}
mc = null;
dataSource = null;
}
public boolean isClosed() throws SQLException {
return closed;
}
/**
* @see java.sql.Connection#createStatement()
*/
public Statement createStatement() throws SQLException {
checkTransaction();
try {
return new WrappedStatement(this, mc.getConnection().createStatement(), dataSource
.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#createStatement(int, int)
*/
public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
checkTransaction();
try {
return new WrappedStatement(this, mc.getConnection().createStatement(resultSetType,
resultSetConcurrency), dataSource.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#createStatement(int, int, int)
*/
public Statement createStatement(int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkTransaction();
try {
return new WrappedStatement(this, mc.getConnection().createStatement(resultSetType,
resultSetConcurrency, resultSetHoldability), dataSource.getDataSourceName(),
zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareStatement(java.lang.String)
*/
public PreparedStatement prepareStatement(String sql) throws SQLException {
checkTransaction();
try {
return new WrappedPreparedStatement(this, mc.prepareStatement(sql,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY), sql, dataSource
.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareStatement(java.lang.String, int, int)
*/
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
checkTransaction();
try {
return new WrappedPreparedStatement(this, mc.prepareStatement(sql, resultSetType,
resultSetConcurrency), sql, dataSource.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareStatement(java.lang.String, int, int, int)
*/
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
checkTransaction();
try {
return new WrappedPreparedStatement(this, mc.getConnection().prepareStatement(sql,
resultSetType, resultSetConcurrency, resultSetHoldability), sql, dataSource
.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareStatement(java.lang.String, int)
*/
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
checkTransaction();
try {
return new WrappedPreparedStatement(this, mc.getConnection().prepareStatement(sql,
autoGeneratedKeys), sql, dataSource.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareStatement(java.lang.String, int[])
*/
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
checkTransaction();
try {
return new WrappedPreparedStatement(this, mc.getConnection().prepareStatement(sql,
columnIndexes), sql, dataSource.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareStatement(java.lang.String, java.lang.String[])
*/
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
checkTransaction();
try {
return new WrappedPreparedStatement(this, mc.getConnection().prepareStatement(sql,
columnNames), sql, dataSource.getDataSourceName(), zdatasource);
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareCall(java.lang.String)
*/
public CallableStatement prepareCall(String sql) throws SQLException {
checkTransaction();
try {
// doSqlValve(sql);
return new WrappedCallableStatement(this, mc.prepareCall(sql,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY));
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareCall(java.lang.String, int, int)
*/
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
checkTransaction();
try {
// doSqlValve(sql);
return new WrappedCallableStatement(this, mc.prepareCall(sql, resultSetType,
resultSetConcurrency));
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#prepareCall(java.lang.String, int, int, int)
*/
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkTransaction();
try {
// doSqlValve(sql);
return new WrappedCallableStatement(this, mc.getConnection().prepareCall(sql,
resultSetType, resultSetConcurrency, resultSetHoldability));
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* @see java.sql.Connection#nativeSQL(java.lang.String)
*/
public String nativeSQL(String sql) throws SQLException {
checkTransaction();
try {
return mc.getConnection().nativeSQL(sql);
} catch (Throwable t) {
throw checkException(t);
}
}
public void setAutoCommit(boolean autocommit) throws SQLException {
checkStatus();
try {
mc.setJdbcAutoCommit(autocommit);
} catch (Throwable t) {
throw checkException(t);
}
}
public boolean getAutoCommit() throws SQLException {
checkStatus();
try {
return mc.isJdbcAutoCommit();
} catch (Throwable t) {
throw checkException(t);
}
}
public void commit() throws SQLException {
checkTransaction();
try {
mc.jdbcCommit();
} catch (Throwable t) {
throw checkException(t);
}
}
public void rollback() throws SQLException {
checkTransaction();
// check Exception for jdbcRollback, add by an.sun at 2011-06-07
try {
mc.jdbcRollback();
} catch (Throwable t) {
throw checkException(new SQLException(t.getMessage(), t.getMessage(),
ExceptionSorter.ROLLBACK_ERRORCODE, t));
} finally {
}
}
public void rollback(Savepoint savepoint) throws SQLException {
checkTransaction();
// check Exception for jdbcRollback with savepoint, add by an.sun at 2011-06-07
try {
mc.jdbcRollback(savepoint);
} catch (Throwable t) {
throw checkException(new SQLException(t.getMessage(), t.getMessage(),
ExceptionSorter.ROLLBACK_ERRORCODE, t));
} finally {
}
}
public DatabaseMetaData getMetaData() throws SQLException {
checkTransaction();
try {
return mc.getConnection().getMetaData();
} catch (Throwable t) {
throw checkException(t);
}
}
public void setCatalog(String catalog) throws SQLException {
checkTransaction();
try {
mc.getConnection().setCatalog(catalog);
} catch (Throwable t) {
throw checkException(t);
}
}
public String getCatalog() throws SQLException {
checkTransaction();
try {
return mc.getConnection().getCatalog();
} catch (Throwable t) {
throw checkException(t);
}
}
public void setTransactionIsolation(int isolationLevel) throws SQLException {
checkStatus();
try {
mc.setJdbcTransactionIsolation(isolationLevel);
} catch (Throwable t) {
throw checkException(t);
}
}
public int getTransactionIsolation() throws SQLException {
checkStatus();
try {
return mc.getJdbcTransactionIsolation();
} catch (Throwable t) {
throw checkException(t);
}
}
public SQLWarning getWarnings() throws SQLException {
checkTransaction();
try {
return mc.getConnection().getWarnings();
} catch (Throwable t) {
throw checkException(t);
}
}
public void clearWarnings() throws SQLException {
checkTransaction();
try {
mc.getConnection().clearWarnings();
} catch (Throwable t) {
throw checkException(t);
}
}
public Map getTypeMap() throws SQLException {
checkTransaction();
try {
return mc.getConnection().getTypeMap();
} catch (Throwable t) {
throw checkException(t);
}
}
public void setTypeMap(Map<String, Class<?>> typeMap) throws SQLException {
checkTransaction();
try {
mc.getConnection().setTypeMap(typeMap);
} catch (Throwable t) {
throw checkException(t);
}
}
public void setHoldability(int holdability) throws SQLException {
checkTransaction();
try {
mc.getConnection().setHoldability(holdability);
} catch (Throwable t) {
throw checkException(t);
}
}
public int getHoldability() throws SQLException {
checkTransaction();
try {
return mc.getConnection().getHoldability();
} catch (Throwable t) {
throw checkException(t);
}
}
public Savepoint setSavepoint() throws SQLException {
checkTransaction();
try {
return mc.getConnection().setSavepoint();
} catch (Throwable t) {
throw checkException(t);
}
}
public Savepoint setSavepoint(String name) throws SQLException {
checkTransaction();
try {
return mc.getConnection().setSavepoint(name);
} catch (Throwable t) {
throw checkException(t);
}
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
checkTransaction();
try {
mc.getConnection().releaseSavepoint(savepoint);
} catch (Throwable t) {
throw checkException(t);
}
}
public Connection getUnderlyingConnection() throws SQLException {
checkTransaction();
try {
return mc.getConnection();
} catch (Throwable t) {
throw checkException(t);
}
}
void checkTransaction() throws SQLException {
checkStatus();
try {
mc.checkTransaction();
} catch (Throwable t) {
throw checkException(t);
}
}
/**
* The checkStatus method checks that the handle has not been closed and
* that it is associated with a managed connection.
*
* @exception SQLException if an error occurs
*/
protected void checkStatus() throws SQLException {
if (closed) {
throw new SQLException("Connection handle has been closed and is unusable");
}
if (mc == null) {
throw new SQLException(
"Connection handle is not currently associated with a ManagedConnection");
}
}
/**
* The base checkException method rethrows the supplied exception, informing
* the ManagedConnection of the error. Subclasses may override this to
* filter exceptions based on their severity.
*
* @param e a <code>SQLException</code> value
* @exception Exception if an error occurs
*/
protected SQLException checkException(Throwable t) throws SQLException {
if (mc != null) {
mc.connectionError(t);
}
if (t instanceof SQLException) {
throw (SQLException) t;
} else {
throw new NestedSQLException("Error", t);
}
}
int getTrackStatements() {
return trackStatements;
}
void registerStatement(WrappedStatement ws) {
if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) {
return;
}
synchronized (this) {
if (statements == null) {
statements = new HashMap();
}
if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_TRUE_INT) {
statements.put(ws, new Throwable("STACKTRACE"));
} else {
statements.put(ws, null);
}
}
}
/**
*
* @param ws
*/
void unregisterStatement(WrappedStatement ws) {
if (trackStatements == BaseWrapperManagedConnectionFactory.TRACK_STATEMENTS_FALSE_INT) {
return;
}
synchronized (this) {
if (statements != null) {
statements.remove(ws);
}
}
}
/**
*
* @param ws
* @throws SQLException
*/
void checkConfiguredQueryTimeout(WrappedStatement ws) throws SQLException {
if (mc == null || dataSource == null) {
return;
}
int timeout = 0;
// Use the transaction timeout
if (mc.isTransactionQueryTimeout()) {
timeout = dataSource.getTimeLeftBeforeTransactionTimeout();
}
// Look for a configured value
if (timeout <= 0) {
timeout = mc.getQueryTimeout();
}
if (timeout > 0) {
ws.setQueryTimeout(timeout);
}
}
Logger getLogger() {
return log;
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
try {
return iface.isInstance(mc.getConnection());
} catch (Throwable t) {
throw checkException(t);
}
}
public <T> T unwrap(Class<T> iface) throws SQLException {
try {
return (T) (iface.isInstance(mc.getConnection()) ? mc.getConnection() : null);
} catch (Throwable t) {
throw checkException(t);
}
}
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
public Blob createBlob() throws SQLException {
return null;
}
public Clob createClob() throws SQLException {
return null;
}
public NClob createNClob() throws SQLException {
return null;
}
public SQLXML createSQLXML() throws SQLException {
return null;
}
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
public Properties getClientInfo() throws SQLException {
return null;
}
public String getClientInfo(String name) throws SQLException {
return null;
}
public boolean isValid(int timeout) throws SQLException {
return false;
}
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
public ZDataSource getZdatasource() {
return zdatasource;
}
public void setZdatasource(ZDataSource zdatasource) {
this.zdatasource = zdatasource;
}
}