/*
* Copyright (C) 2000 - 2013 TagServlet Ltd
*
* This file is part of Open BlueDragon (OpenBD) CFML Server Engine.
*
* OpenBD is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Free Software Foundation,version 3.
*
* OpenBD is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenBD. If not, see http://www.gnu.org/licenses/
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with any of the JARS listed in the README.txt (or a modified version of
* (that library), containing parts covered by the terms of that JAR, the
* licensors of this Program grant you additional permission to convey the
* resulting work.
* README.txt @ http://www.openbluedragon.org/license/README.txt
*
* http://openbd.org/
* $Id: WrappedConnection.java 2404 2013-09-22 21:51:40Z alan $
*/
package com.naryx.tagfusion.cfm.sql.pool;
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.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.PooledConnection;
import javax.sql.StatementEventListener;
import com.naryx.tagfusion.cfm.engine.cfEngine;
/**
* This class is a proxy class to the underlying Connection class
* that allows us to manage the pool and collate various stats on
* this is being used. All interfaces implemented up to 1.4, although
* any calls to 1.4 specific methods will result in an SQLException
*/
public class WrappedConnection extends Object implements Connection, PooledConnection {
private Connection con;
private ConnectionEventListener activeListener;
private long startUsageTime, creationTime;
private int statsTotalStatments, statsTotalPrepareds, statsTotalCallable, totalUsage;
private String validationQuery;
private String lastQuery;
private static boolean validateConnections = true;
public static void setValidateConnections( boolean validate ) {
validateConnections = validate;
}
public static boolean isValidateConnections() {
return validateConnections;
}
public WrappedConnection( Connection con ){
this.con = con;
activeListener = null;
creationTime = System.currentTimeMillis();
validationQuery = null;
if ( !validateConnections ) {
return;
}
try {
// create validation query
DatabaseMetaData dbmd = con.getMetaData();
String dbProductName = dbmd.getDatabaseProductName().toLowerCase();
if ( ( dbProductName.indexOf( "microsoft" ) >= 0 ) ||
( dbProductName.indexOf( "sql server" ) >= 0 ) || // this value is also returned by the BEA driver for sybase
( dbProductName.indexOf( "access" ) >= 0 ) ||
( dbProductName.indexOf( "adaptive server enterprise" ) >= 0 ) || // sybase using jConnect 5.5 driver
( dbProductName.indexOf( "sybase" ) >= 0 ) ) { // this check may not be needed
validationQuery = "select 1";
} else if ( dbProductName.indexOf( "oracle" ) >= 0 ) {
validationQuery = "select sysdate from dual";
} else if ( ( dbProductName.indexOf( "mysql" ) >= 0 ) ||
( dbProductName.indexOf( "postgres" ) >= 0 ) ) {
validationQuery = "select now()";
} else if ( dbProductName.indexOf( "informix" ) >= 0 ) {
validationQuery = "select distinct current timestamp from informix.systables";
} else if ( ( dbProductName.indexOf( "db2" ) >= 0 ) ||
( dbProductName.indexOf( "ibm" ) >= 0 ) ) { // this check may not be needed
validationQuery = "select distinct(current timestamp) from sysibm.systables";
} else if ( dbProductName.indexOf( "pointbase" ) >= 0 ) {
validationQuery = "select count(*) from systables";
} else {
cfEngine.log( "Can't validate connections for " + dbProductName );
}
} catch ( SQLException ignore ) {}
}
public String getLastQuery(){
return lastQuery;
}
public void setLastQuery( String query ){
lastQuery = query;
}
public Connection getConnection() {
return con;
}
public boolean isOpen() {
try {
if ( con.isClosed() )
return false;
if ( validationQuery != null ) { // if we can't validate, just return true
Statement stmt = con.createStatement();
lastQuery = "STATEMENT: " + validationQuery;
stmt.execute( validationQuery );
stmt.close();
lastQuery = null;
}
return true;
} catch ( SQLException e ) {
try {
con.close(); // connection is bad, so try to close it
} catch ( SQLException ignore ) {}
return false;
}
}
public int getTotalHits(){
return totalUsage;
}
public long getAliveTime(){
return System.currentTimeMillis() - creationTime;
}
public void close() {
if ( activeListener != null )
activeListener.connectionClosed( new ConnectionEvent(this) );
}
public ConnectionEventListener getConnectionEventListener(){
return activeListener;
}
public void addConnectionEventListener(ConnectionEventListener listener){
if ( ( activeListener != null ) && ( activeListener != listener ) ) {
throw new IllegalArgumentException( "Only one listener allowed per nConnection" );
}
activeListener = listener;
startUsageTime = System.currentTimeMillis();
}
public void removeConnectionEventListener(ConnectionEventListener listener){
if ( activeListener != listener ) {
throw new IllegalArgumentException( "Invalid attempt to remove listener" );
}
activeListener = null;
startUsageTime = System.currentTimeMillis();
}
public long getUsageTime(){
return System.currentTimeMillis() - startUsageTime;
}
public void clearStats(){
totalUsage += statsTotalStatments + statsTotalPrepareds + statsTotalCallable;
statsTotalStatments = 0;
statsTotalPrepareds = 0;
statsTotalCallable = 0;
}
public int getTotalStatements(){ return statsTotalStatments; }
public int getTotalPrepareds(){ return statsTotalPrepareds; }
public int getTotalCallable(){ return statsTotalCallable; }
//-------------------------------------
//-- Methods from the Connection class
public Statement createStatement() throws SQLException{
lastQuery = "STATEMENT: unknown sql";
statsTotalStatments++;
return con.createStatement();
}
public PreparedStatement prepareStatement(String sql) throws SQLException{
lastQuery = "PREPARE STATEMENT: " + sql;
statsTotalPrepareds++;
return con.prepareStatement( sql );
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys ) throws SQLException{
lastQuery = "PREPARE STATEMENT: " + sql;
statsTotalPrepareds++;
return con.prepareStatement( sql, autoGeneratedKeys );
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes ) throws SQLException{
throw new SQLException( "method not supported" );
}
public PreparedStatement prepareStatement(String sql, String[] columnNames ) throws SQLException{
throw new SQLException( "method not supported" );
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability ) throws SQLException{
throw new SQLException( "method not supported" );
}
public CallableStatement prepareCall(String sql) throws SQLException {
lastQuery = "PREPARE CALL: " + sql;
statsTotalCallable++;
return con.prepareCall( sql );
}
public String nativeSQL(String sql) throws SQLException{
return con.nativeSQL( sql );
}
public void setAutoCommit(boolean autoCommit) throws SQLException{
con.setAutoCommit( autoCommit );
}
public boolean getAutoCommit()throws SQLException{
return con.getAutoCommit();
}
public void rollback() throws SQLException{
con.rollback();
}
public void rollback(Savepoint savepoint) throws SQLException{
throw new SQLException( "method not supported" );
}
public boolean isClosed() throws SQLException{
return con.isClosed();
}
public void commit() throws SQLException{
con.commit();
}
public DatabaseMetaData getMetaData() throws SQLException{
return con.getMetaData();
}
public void setReadOnly(boolean readOnly) throws SQLException{
con.setReadOnly( readOnly );
}
public boolean isReadOnly()throws SQLException {
return con.isReadOnly();
}
public void setCatalog(String catalog) throws SQLException{
con.setCatalog( catalog );
}
public String getCatalog() throws SQLException{
return con.getCatalog();
}
public void setTransactionIsolation(int level) throws SQLException{
con.setTransactionIsolation( level );
}
public int getTransactionIsolation() throws SQLException{
return con.getTransactionIsolation();
}
public SQLWarning getWarnings() throws SQLException{
return con.getWarnings();
}
public void clearWarnings() throws SQLException{
con.clearWarnings();
}
public Statement createStatement(int resultSetType,int resultSetConcurrency)throws SQLException{
throw new SQLException( "method not supported" );
}
public PreparedStatement prepareStatement(String sql,int resultSetType,int resultSetConcurrency) throws SQLException{
throw new SQLException( "method not supported" );
}
public CallableStatement prepareCall(String sql,int resultSetType,int resultSetConcurrency) throws SQLException{
throw new SQLException( "method not supported" );
}
public CallableStatement prepareCall(String sql,int resultSetType,int resultSetConcurrency, int resultSetHoldability) throws SQLException{
throw new SQLException( "method not supported" );
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Map getTypeMap() throws SQLException{
throw new SQLException( "method not supported" );
}
@Override
public void setTypeMap( Map<String, Class<?>> arg0 ) throws SQLException {
throw new SQLException( "method not supported" );
}
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
throw new SQLException( "method not supported" );
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
throw new SQLException( "method not supported" );
}
public int getHoldability() throws SQLException{
throw new SQLException( "method not supported" );
}
public void setHoldability(int holdability) throws SQLException{
throw new SQLException( "method not supported" );
}
public Savepoint setSavepoint(String name) throws SQLException {
throw new SQLException( "method not supported" );
}
public Savepoint setSavepoint() throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public Array createArrayOf( String arg0, Object[] arg1 ) throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public Blob createBlob() throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public Clob createClob() throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public NClob createNClob() throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public SQLXML createSQLXML() throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public Struct createStruct( String arg0, Object[] arg1 ) throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public Properties getClientInfo() throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public String getClientInfo( String arg0 ) throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public boolean isValid( int arg0 ) throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public void setClientInfo( Properties arg0 ) throws SQLClientInfoException {}
@Override
public boolean isWrapperFor( Class<?> iface ) throws SQLException {
return false;
}
@Override
public <T> T unwrap( Class<T> iface ) throws SQLException {
throw new SQLException( "method not supported" );
}
@Override
public void addStatementEventListener( StatementEventListener arg0 ) {}
@Override
public void removeStatementEventListener( StatementEventListener arg0 ) {}
@Override
public void setClientInfo(String arg0, String arg1) throws SQLClientInfoException {
}
private boolean bForceClosed = false;
public void setForceClose() {
bForceClosed = true;
}
public boolean getForceClose(){
return bForceClosed;
}
public void abort( Executor arg0 ) throws SQLException {
}
public int getNetworkTimeout() throws SQLException {
return 0;
}
public String getSchema() throws SQLException {
return null;
}
public void setNetworkTimeout( Executor arg0, int arg1 ) throws SQLException {
}
public void setSchema( String arg0 ) throws SQLException {
}
}