/*
* Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
* available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.text.MessageFormat;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
Provides a wrapper around SQLServerConnection object. When returning a connection object from
PooledConnection.getConnection we return this proxy per SPEC.
This class's public functions need to be kept identical to the SQLServerConnection's.
The API javadoc for JDBC API methods that this class implements are not repeated here. Please see Sun's JDBC API
interfaces javadoc for those details.
/**
* Provides a wrapper around SQLServerConnection object. When returning a connection object from
* PooledConnection.getConnection we return this proxy per SPEC.
* <p>
* This class's public functions need to be kept identical to the SQLServerConnection's.
* <p>
* The API javadoc for JDBC API methods that this class implements are not repeated here. Please see Sun's JDBC API
* interfaces javadoc for those details.
*/
class SQLServerConnectionPoolProxy implements ISQLServerConnection, java.io.Serializable {
Always refresh SerialVersionUID when prompted
/**
* Always refresh SerialVersionUID when prompted
*/
private static final long serialVersionUID = 5752599482349578127L;
private SQLServerConnection wrappedConnection;
private boolean bIsOpen;
static private final AtomicInteger baseConnectionID = new AtomicInteger(0); // connection
// id
// dispenser
final private String traceID;
Permission targets currently only callAbort is implemented
/**
* Permission targets currently only callAbort is implemented
*/
private static final String callAbortPerm = "callAbort";
Generates the next unique connection id.
Returns: the next conn id
/**
* Generates the next unique connection id.
*
* @return the next conn id
*/
private static int nextConnectionID() {
return baseConnectionID.incrementAndGet();
}
@Override
public String toString() {
return traceID;
}
SQLServerConnectionPoolProxy(SQLServerConnection con) {
traceID = " ProxyConnectionID:" + nextConnectionID();
wrappedConnection = con;
// the Proxy is created with an open conn
con.setAssociatedProxy(this);
bIsOpen = true;
}
SQLServerConnection getWrappedConnection() {
return wrappedConnection;
}
void checkClosed() throws SQLServerException {
if (!bIsOpen) {
SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_connectionIsClosed"),
SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE, false);
}
}
@Override
public Statement createStatement() throws SQLServerException {
checkClosed();
return wrappedConnection.createStatement();
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareCall(sql);
}
@Override
public String nativeSQL(String sql) throws SQLServerException {
checkClosed();
return wrappedConnection.nativeSQL(sql);
}
@Override
public void setAutoCommit(boolean newAutoCommitMode) throws SQLServerException {
checkClosed();
wrappedConnection.setAutoCommit(newAutoCommitMode);
}
@Override
public boolean getAutoCommit() throws SQLServerException {
checkClosed();
return wrappedConnection.getAutoCommit();
}
@Override
public void commit() throws SQLServerException {
checkClosed();
wrappedConnection.commit();
}
@Override
public void rollback() throws SQLServerException {
checkClosed();
wrappedConnection.rollback();
}
@Override
public void abort(Executor executor) throws SQLException {
if (!bIsOpen || (null == wrappedConnection))
return;
if (null == executor) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidArgument"));
Object[] msgArgs = {"executor"};
SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, false);
}
// check for callAbort permission
SecurityManager secMgr = System.getSecurityManager();
if (secMgr != null) {
try {
java.sql.SQLPermission perm = new java.sql.SQLPermission(callAbortPerm);
secMgr.checkPermission(perm);
} catch (SecurityException ex) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_permissionDenied"));
Object[] msgArgs = {callAbortPerm};
throw new SQLServerException(form.format(msgArgs), null, 0, ex);
}
}
bIsOpen = false;
executor.execute(new Runnable() {
public void run() {
if (wrappedConnection.getConnectionLogger().isLoggable(java.util.logging.Level.FINER))
wrappedConnection.getConnectionLogger().finer(toString() + " Connection proxy aborted ");
try {
wrappedConnection.poolCloseEventNotify();
wrappedConnection = null;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
});
}
@Override
public void close() throws SQLServerException {
if (bIsOpen && (null != wrappedConnection)) {
if (wrappedConnection.getConnectionLogger().isLoggable(java.util.logging.Level.FINER))
wrappedConnection.getConnectionLogger().finer(toString() + " Connection proxy closed ");
wrappedConnection.poolCloseEventNotify();
wrappedConnection = null;
}
bIsOpen = false;
}
void internalClose() {
bIsOpen = false;
wrappedConnection = null;
}
@Override
public boolean isClosed() throws SQLServerException {
return !bIsOpen;
}
@Override
public java.sql.DatabaseMetaData getMetaData() throws SQLServerException {
checkClosed();
return wrappedConnection.getMetaData();
}
@Override
public void setReadOnly(boolean readOnly) throws SQLServerException {
checkClosed();
wrappedConnection.setReadOnly(readOnly);
}
@Override
public boolean isReadOnly() throws SQLServerException {
checkClosed();
return wrappedConnection.isReadOnly();
}
@Override
public void setCatalog(String catalog) throws SQLServerException {
checkClosed();
wrappedConnection.setCatalog(catalog);
}
@Override
public String getCatalog() throws SQLServerException {
checkClosed();
return wrappedConnection.getCatalog();
}
@Override
public void setTransactionIsolation(int level) throws SQLServerException {
checkClosed();
wrappedConnection.setTransactionIsolation(level);
}
@Override
public int getTransactionIsolation() throws SQLServerException {
checkClosed();
return wrappedConnection.getTransactionIsolation();
}
@Override
public java.sql.SQLWarning getWarnings() throws SQLServerException {
checkClosed();
return wrappedConnection.getWarnings(); // Warnings support added
}
@Override
public void clearWarnings() throws SQLServerException {
checkClosed();
wrappedConnection.clearWarnings();
}
// --------------------------JDBC 2.0-----------------------------
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
checkClosed();
return wrappedConnection.createStatement(resultSetType, resultSetConcurrency);
}
@Override
public PreparedStatement prepareStatement(String sSql, int resultSetType,
int resultSetConcurrency) throws SQLException {
checkClosed();
return wrappedConnection.prepareStatement(sSql, resultSetType, resultSetConcurrency);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
checkClosed();
return wrappedConnection.prepareCall(sql, resultSetType, resultSetConcurrency);
}
@Override
public void setTypeMap(java.util.Map<String, Class<?>> map) throws SQLException {
checkClosed();
wrappedConnection.setTypeMap(map);
}
@Override
public java.util.Map<String, Class<?>> getTypeMap() throws SQLServerException {
checkClosed();
return wrappedConnection.getTypeMap();
}
@Override
public Statement createStatement(int nType, int nConcur, int nHold) throws SQLServerException {
checkClosed();
return wrappedConnection.createStatement(nType, nConcur, nHold);
}
@Override
public Statement createStatement(int nType, int nConcur, int nHold,
SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException {
checkClosed();
return wrappedConnection.createStatement(nType, nConcur, nHold, stmtColEncSetting);
}
@Override
public PreparedStatement prepareStatement(java.lang.String sql, int nType, int nConcur,
int nHold) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, nType, nConcur, nHold);
}
@Override
public PreparedStatement prepareStatement(String sql, int nType, int nConcur, int nHold,
SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, nType, nConcur, nHold, stmtColEncSetting);
}
@Override
public CallableStatement prepareCall(String sql, int nType, int nConcur, int nHold) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareCall(sql, nType, nConcur, nHold);
}
@Override
public CallableStatement prepareCall(String sql, int nType, int nConcur, int nHold,
SQLServerStatementColumnEncryptionSetting stmtColEncSetiing) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareCall(sql, nType, nConcur, nHold, stmtColEncSetiing);
}
/* JDBC 3.0 Auto generated keys */
@Override
public PreparedStatement prepareStatement(String sql, int flag) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, flag);
}
@Override
public PreparedStatement prepareStatement(String sql, int flag,
SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, flag, stmtColEncSetting);
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, columnIndexes);
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes,
SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, columnIndexes, stmtColEncSetting);
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, columnNames);
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames,
SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException {
checkClosed();
return wrappedConnection.prepareStatement(sql, columnNames, stmtColEncSetting);
}
/* JDBC 3.0 Savepoints */
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
checkClosed();
wrappedConnection.releaseSavepoint(savepoint);
}
@Override
public Savepoint setSavepoint(String sName) throws SQLServerException {
checkClosed();
return wrappedConnection.setSavepoint(sName);
}
@Override
public Savepoint setSavepoint() throws SQLServerException {
checkClosed();
return wrappedConnection.setSavepoint();
}
@Override
public void rollback(Savepoint s) throws SQLServerException {
checkClosed();
wrappedConnection.rollback(s);
}
@Override
public int getHoldability() throws SQLServerException {
checkClosed();
return wrappedConnection.getHoldability();
}
@Override
public void setHoldability(int nNewHold) throws SQLServerException {
checkClosed();
wrappedConnection.setHoldability(nNewHold);
}
@Override
public int getNetworkTimeout() throws SQLException {
checkClosed();
return wrappedConnection.getNetworkTimeout();
}
@Override
public void setNetworkTimeout(Executor executor, int timeout) throws SQLException {
checkClosed();
wrappedConnection.setNetworkTimeout(executor, timeout);
}
@Override
public String getSchema() throws SQLException {
checkClosed();
return wrappedConnection.getSchema();
}
@Override
public void setSchema(String schema) throws SQLException {
checkClosed();
wrappedConnection.setSchema(schema);
}
@Override
public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException {
checkClosed();
return wrappedConnection.createArrayOf(typeName, elements);
}
@Override
public java.sql.Blob createBlob() throws SQLException {
checkClosed();
return wrappedConnection.createBlob();
}
@Override
public java.sql.Clob createClob() throws SQLException {
checkClosed();
return wrappedConnection.createClob();
}
@Override
public java.sql.NClob createNClob() throws SQLException {
checkClosed();
return wrappedConnection.createNClob();
}
@Override
public java.sql.SQLXML createSQLXML() throws SQLException {
checkClosed();
return wrappedConnection.createSQLXML();
}
@Override
public java.sql.Struct createStruct(String typeName, Object[] attributes) throws SQLException {
checkClosed();
return wrappedConnection.createStruct(typeName, attributes);
}
@Override
public java.util.Properties getClientInfo() throws SQLException {
checkClosed();
return wrappedConnection.getClientInfo();
}
@Override
public String getClientInfo(String name) throws SQLException {
checkClosed();
return wrappedConnection.getClientInfo(name);
}
@Override
public void setClientInfo(java.util.Properties properties) throws SQLClientInfoException {
// No checkClosed() call since we can only throw SQLClientInfoException
// from here
wrappedConnection.setClientInfo(properties);
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
// No checkClosed() call since we can only throw SQLClientInfoException
// from here
wrappedConnection.setClientInfo(name, value);
}
@Override
public boolean isValid(int timeout) throws SQLException {
checkClosed();
return wrappedConnection.isValid(timeout);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
wrappedConnection.getConnectionLogger().entering(toString(), "isWrapperFor", iface);
boolean f = iface.isInstance(this);
wrappedConnection.getConnectionLogger().exiting(toString(), "isWrapperFor", f);
return f;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
wrappedConnection.getConnectionLogger().entering(toString(), "unwrap", iface);
T t;
try {
t = iface.cast(this);
} catch (ClassCastException e) {
SQLServerException newe = new SQLServerException(e.getMessage(), e);
throw newe;
}
wrappedConnection.getConnectionLogger().exiting(toString(), "unwrap", t);
return t;
}
@Override
public java.util.UUID getClientConnectionId() throws SQLServerException {
checkClosed();
return wrappedConnection.getClientConnectionId();
}
@Override
public void setSendTimeAsDatetime(boolean sendTimeAsDateTimeValue) throws SQLServerException {
checkClosed();
wrappedConnection.setSendTimeAsDatetime(sendTimeAsDateTimeValue);
}
@Override
public boolean getSendTimeAsDatetime() throws SQLServerException {
checkClosed();
return wrappedConnection.getSendTimeAsDatetime();
}
@Override
public int getDiscardedServerPreparedStatementCount() {
return wrappedConnection.getDiscardedServerPreparedStatementCount();
}
@Override
public void closeUnreferencedPreparedStatementHandles() {
wrappedConnection.closeUnreferencedPreparedStatementHandles();
}
@Override
public boolean getEnablePrepareOnFirstPreparedStatementCall() {
return wrappedConnection.getEnablePrepareOnFirstPreparedStatementCall();
}
@Override
public void setEnablePrepareOnFirstPreparedStatementCall(boolean value) {
wrappedConnection.setEnablePrepareOnFirstPreparedStatementCall(value);
}
@Override
public int getServerPreparedStatementDiscardThreshold() {
return wrappedConnection.getServerPreparedStatementDiscardThreshold();
}
@Override
public void setServerPreparedStatementDiscardThreshold(int value) {
wrappedConnection.setServerPreparedStatementDiscardThreshold(value);
}
@Override
public void setStatementPoolingCacheSize(int value) {
wrappedConnection.setStatementPoolingCacheSize(value);
}
@Override
public int getStatementPoolingCacheSize() {
return wrappedConnection.getStatementPoolingCacheSize();
}
@Override
public boolean isStatementPoolingEnabled() {
return wrappedConnection.isStatementPoolingEnabled();
}
@Override
public int getStatementHandleCacheEntryCount() {
return wrappedConnection.getStatementHandleCacheEntryCount();
}
@Override
public void setDisableStatementPooling(boolean value) {
wrappedConnection.setDisableStatementPooling(value);
}
@Override
public boolean getDisableStatementPooling() {
return wrappedConnection.getDisableStatementPooling();
}
@Override
public void setUseFmtOnly(boolean useFmtOnly) {
wrappedConnection.setUseFmtOnly(useFmtOnly);
}
@Override
public boolean getUseFmtOnly() {
return wrappedConnection.getUseFmtOnly();
}
@Override
public boolean getDelayLoadingLobs() {
return wrappedConnection.getDelayLoadingLobs();
}
@Override
public void setDelayLoadingLobs(boolean delayLoadingLobs) {
wrappedConnection.setDelayLoadingLobs(delayLoadingLobs);
}
}