/*
* 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
*
* $Id: cfDataSource.java 2379 2013-06-14 23:37:53Z alan $
* http://openbd.org/
*/
package com.naryx.tagfusion.cfm.sql;
/**
* This class handles the ColdFusion DATASOURCE used for accessing database resources.
*/
import java.sql.Connection;
import java.sql.SQLException;
import com.naryx.tagfusion.cfm.engine.cfEngine;
import com.naryx.tagfusion.cfm.engine.cfSession;
import com.naryx.tagfusion.cfm.engine.cfmRunTimeException;
public class cfDataSource extends Object implements java.io.Serializable {
private static final long serialVersionUID = 1;
protected cfDataSourceDetails dsDetails;
protected cfSession Session;
protected String username, password;
// WARNING! don't reference key directly, but only via the getKey() method
protected String key;
protected cfDataSource() {}
public cfDataSource( String _DataSource ) throws cfmRunTimeException {
this( _DataSource, null );
}
public cfDataSource( String _DataSource, cfSession _Session ) throws cfmRunTimeException {
Session = _Session;
dsDetails = cfDataSourceDetailsFactory.get( _DataSource );
username = dsDetails.getUsername();
password = dsDetails.getPassword();
}
/**
* Code that can run inside a CFTRANSACTION must call this method
* instead of getConnection(). When the code is done with the
* connection, it must call returnConnection().
*
* @return
* @throws SQLException
*/
public Connection takeConnection() throws SQLException {
// Check to see if we are running inside a CFTRANSACTION
cfTransactionCache tCache = (cfTransactionCache)Session.getDataBin( cfTRANSACTION.DATA_BIN_KEY );
if ( tCache == null ) {
Connection con = getPooledConnection();
try {
con.setAutoCommit( true );
} catch ( SQLException ignore ) {} // this will be handled better later when we try to use the connection
return con;
} else {
return tCache.pop( this );
}
}
/**
* Code that can run inside a CFTRANSACTION must call this
* method to release a connection when they are done with it.
* The code must not call connection.close() to release it.
*
* @param Con
*/
public void returnConnection( Connection Con ) {
// Check to see if we are running inside a CFTRANSACTION
cfTransactionCache tCache = (cfTransactionCache)Session.getDataBin( cfTRANSACTION.DATA_BIN_KEY );
if ( tCache == null ) {
close( Con );
} else {
tCache.push( this, Con );
}
}
/**
* close or reset the connection for reuse
* @param con
*/
public void close( Connection con ) {
if ( con != null ) {
try {
if ( dsDetails.perRequestConnections || dsDetails.isUnlimitedPool() ) { // reset for reuse within this request
con.clearWarnings();
con.setAutoCommit( true );
} else {
con.close(); // put back into the connection pool
}
} catch ( SQLException ignore ) {}
}
}
/**
* Connections can be saved in a per-request cache managed by the cfSession instance. This
* allows connections for the same datasource to be re-used within a single request.
* This is necessary to support MySQL temporary tables (see bug #2670). This can also
* provide a performance benefit since we don't have to go back to the connection pool
* every time if the same datasource is used multiple times within a single request (a
* common usage scenario).
*
* @return
* @throws SQLException
*/
public Connection getPooledConnection() throws SQLException {
if ( dsDetails.perRequestConnections || dsDetails.isUnlimitedPool() ) {
Connection con = Session.getConnection( getKey() ); // look for a connection in the per-request cache
if ( con == null ) {
con = cfEngine.dataSourcePoolFactory.getConnection(dsDetails); // get a connection from the connection pool
Session.putConnection( getKey(), con ); // save the connection in the per-request cache
}
return con;
}else
return cfEngine.dataSourcePoolFactory.getConnection(dsDetails);
}
/**
* Get a connection from the connection pool. This method must be called by code that cannot run inside a CFTRANSACTION.
* The code must call connection.close() and not returnConnection() or this.close() to release the connection.
*
* @return
* @throws SQLException
*/
public Connection getConnection() throws SQLException {
return cfEngine.dataSourcePoolFactory.getConnection(dsDetails);
}
public String getKey() {
if ( key == null ) {
key = dsDetails.getDataSourceName() + "." + username + "." + password;
}
return key;
}
public String toString(){
return dsDetails.toString() + "\r\n" +
"Username = " + username +"\r\n" +
"Password = " + password;
}
public final String getUsername(){ return username; }
public final String getPassword(){ return password; }
public void setUsername( String _username ) {
if ( ( _username != null ) && ( _username.length() > 0 ) ) {
username = _username;
dsDetails.username = _username;
}
}
public void setPassword( String _password ) {
if ( ( _password != null ) && ( _password.length() > 0 ) ) {
password = _password;
dsDetails.password = _password;
}
}
public final String getCatalog(){ return dsDetails.getCatalog(); }
public final String getDataSourceName(){ return dsDetails.getDataSourceName(); }
public final boolean isSql_delete() { return dsDetails.sql_delete; }
public final boolean isSql_insert() { return dsDetails.sql_insert; }
public final boolean isSql_select() { return dsDetails.sql_select; }
public final boolean isSql_storedprocedures() { return dsDetails.sql_storedprocedures; }
public final boolean isSql_update() { return dsDetails.sql_update; }
}