/*
* This software is distributed under the terms of the FSF
* Gnu Lesser General Public License (see lgpl.txt).
*
* This program is distributed WITHOUT ANY WARRANTY. See the
* GNU General Public License for more details.
*/
package com.scooterframework.orm.sqldataexpress.connection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import com.scooterframework.common.logging.LogUtil;
import com.scooterframework.orm.sqldataexpress.config.DatabaseConfig;
import com.scooterframework.orm.sqldataexpress.exception.CreateConnectionFailureException;
import com.scooterframework.orm.sqldataexpress.util.OrmObjectFactory;
import com.scooterframework.security.LoginHelper;
/**
* ConnectionUtil class
*
* @author (Fei) John Chen
*
*/
public class ConnectionUtil {
/**
* Helper method to create a connection to database with given
* DataSourceConnectionContext instance.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createConnection(DataSourceConnectionContext dcc)
throws CreateConnectionFailureException {
if (dcc == null)
throw new CreateConnectionFailureException(
"createConnection failure: dcc is null.");
beforeConnection(dcc);
Connection connection = null;
if (dcc.useLoginForConnection()) {
connection = createConnection(dcc.getDataSourceName(),
loginUsername(), loginPassword(), dcc.getLoginTimeout());
}
else {
if (dcc.getUsername() == null) {
connection = createConnection(dcc.getDataSourceName(), dcc
.getLoginTimeout());
} else {
connection = createConnection(dcc.getDataSourceName(), dcc
.getUsername(), dcc.getPassword(), dcc.getLoginTimeout());
}
}
if (connection == null)
throw new CreateConnectionFailureException(
"createConnection() failed for connection name: "
+ dcc.getConnectionName());
checkReadonly(connection, dcc);
checkAutoCommit(connection, dcc);
checkTransactionIsolationLevel(connection, dcc);
afterConnection(connection, dcc);
return connection;
}
/**
* Helper method to create a connection to database with given data source
* name.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createConnection(String jndiDataSourceName,
Integer loginTimeout) throws CreateConnectionFailureException {
Connection connection = null;
try {
log.debug("connecting to datasource " + jndiDataSourceName);
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(jndiDataSourceName);
if (loginTimeout != null)
ds.setLoginTimeout(loginTimeout.intValue());
connection = ds.getConnection();
} catch (Exception ex) {
String errorMessage = "ConnectionUtil.createConnection " +
"failed for dataSourceName \"" + jndiDataSourceName + "\"";
throw new CreateConnectionFailureException(errorMessage +
" because " + ex.getMessage(), ex);
}
return connection;
}
/**
* Helper method to create a connection to database with given data source
* name, username and password.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createConnection(String jndiDataSourceName,
String username, String password, Integer loginTimeout) {
Connection connection = null;
try {
log.debug("connecting to datasource " + jndiDataSourceName
+ " for " + username);
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(jndiDataSourceName);
if (loginTimeout != null)
ds.setLoginTimeout(loginTimeout.intValue());
connection = ds.getConnection(username, password);
} catch (Exception ex) {
String errorMessage = "ConnectionUtil.createConnection " +
"failed for dataSourceName \"" + jndiDataSourceName +
"\" and user \"" + username + "\"";
throw new CreateConnectionFailureException(errorMessage
+ " because " + ex.getMessage(), ex);
}
return connection;
}
/**
* Helper method to create a connection to database with given
* JdbcConnectionContext instance.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createConnection(JdbcConnectionContext dcc) {
if (dcc == null)
throw new CreateConnectionFailureException(
"createConnection failure: dcc is null.");
beforeConnection(dcc);
Connection connection = null;
if (dcc.useLoginForConnection()) {
connection = createConnection(dcc.getDriverClassName(), dcc.getUrl(),
loginUsername(), loginPassword(), dcc.getLoginTimeout());
}
else {
if (dcc.getUsername() == null) {
connection = createConnection(dcc.getDriverClassName(), dcc
.getUrl(), dcc.getLoginTimeout());
} else {
connection = createConnection(dcc.getDriverClassName(), dcc
.getUrl(), dcc.getUsername(), dcc.getPassword(), dcc
.getLoginTimeout());
}
}
if (connection == null)
throw new CreateConnectionFailureException(
"createConnection() failed for connection name: "
+ dcc.getConnectionName());
checkReadonly(connection, dcc);
checkAutoCommit(connection, dcc);
checkTransactionIsolationLevel(connection, dcc);
afterConnection(connection, dcc);
return connection;
}
/**
* Helper method to create a connection to database with given url, username
* and password.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createConnection(String driver, String url, Integer loginTimeout) {
Connection connection = null;
try {
log.debug("connecting to database " + url);
try {
Class.forName(driver);
} catch (Exception ex) {
throw new Exception("Failed to load driver \"" + driver + "\".");
}
if (loginTimeout != null)
DriverManager.setLoginTimeout(loginTimeout.intValue());
connection = DriverManager.getConnection(url);
} catch (Exception ex) {
throw new CreateConnectionFailureException(
"ConnectionUtil.createConnection failed for url \"" + url
+ "\" because " + ex.getMessage(), ex);
}
return connection;
}
/**
* Helper method to create a connection to database with given url, username
* and password.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createConnection(String driver, String url,
String username, String password, Integer loginTimeout) {
Connection connection = null;
try {
log.debug("connecting to database " + url + " for " + username);
try {
Class.forName(driver);
} catch (Exception ex) {
throw new Exception("Failed to load driver \"" + driver + "\".");
}
if (loginTimeout != null)
DriverManager.setLoginTimeout(loginTimeout.intValue());
connection = DriverManager.getConnection(url, username, password);
} catch (Exception ex) {
throw new CreateConnectionFailureException(
"ConnectionUtil.createConnection failed for url \"" + url
+ "\" and user \"" + username + "\" because "
+ ex.getMessage(), ex);
}
return connection;
}
/**
* Helper method to create a pooled connection to database with given
* JdbcConnectionContext instance.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createPooledConnection(JdbcConnectionContext dcc) {
if (dcc == null)
throw new CreateConnectionFailureException(
"createPooledConnection failure: dcc is null.");
beforeConnection(dcc);
Connection connection = null;
if (dcc.useLoginForConnection()) {
connection = createPooledConnection(dcc.getConnectionName(),
loginUsername(), loginPassword(), dcc.getLoginTimeout());
}
else {
if (dcc.getUsername() == null) {
connection = createPooledConnection(dcc.getConnectionName(), dcc.getLoginTimeout());
} else {
connection = createPooledConnection(dcc.getConnectionName(),
dcc.getUsername(), dcc.getPassword(), dcc.getLoginTimeout());
}
}
if (connection == null)
throw new CreateConnectionFailureException(
"createPooledConnection() failed for connection name: "
+ dcc.getConnectionName());
checkReadonly(connection, dcc);
checkAutoCommit(connection, dcc);
checkTransactionIsolationLevel(connection, dcc);
afterConnection(connection, dcc);
return connection;
}
/**
* Helper method to create a pooled connection to database with given connection name.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createPooledConnection(String connectionName, Integer loginTimeout) {
Connection connection = null;
try {
log.debug("pool connecting to database represented by " + connectionName);
DataSource ds = (DataSource) DatabaseConfig.getInstance().getPooledDataSource(connectionName);
if (ds == null) throw new IllegalArgumentException("No data source for " + connectionName);
if (loginTimeout != null)
ds.setLoginTimeout(loginTimeout.intValue());
connection = ds.getConnection();
} catch (SQLException ex) {
throw new CreateConnectionFailureException(
"ConnectionUtil.createPooledConnection failed for conectionName \"" + connectionName
+ "\" because " + ex.getMessage(), ex);
}
return connection;
}
/**
* Helper method to create a pooled connection to database with given connection name.
*
* @return Connection
* @exception CreateConnectionFailureException
*/
public static Connection createPooledConnection(String connectionName,
String username, String password, Integer loginTimeout) {
Connection connection = null;
try {
log.debug("pool connecting to database represented by " + connectionName);
DataSource ds = (DataSource) DatabaseConfig.getInstance().getPooledDataSource(connectionName);
if (ds == null) throw new IllegalArgumentException("No data source for " + connectionName);
if (loginTimeout != null)
ds.setLoginTimeout(loginTimeout.intValue());
connection = ds.getConnection(username, password);
} catch (SQLException ex) {
throw new CreateConnectionFailureException(
"ConnectionUtil.createPooledConnection failed for conectionName \"" + connectionName
+ "\" because " + ex.getMessage(), ex);
}
return connection;
}
public static String getSetRoleStatement(Properties roles) {
String roleStr = "";
for(Map.Entry<Object, Object> entry : roles.entrySet()) {
String key = (String) entry.getKey();
String pwd = (String) entry.getValue();
if (pwd != null) {
roleStr = roleStr + " " + key + " identified by ? ,";
} else {
roleStr = roleStr + " " + key + ",";
}
}
// remove the last ,
roleStr = roleStr.substring(0, roleStr.length() - 1);
return "SET ROLE " + roleStr;
}
/**
* If the database connection context specifies <tt>readonly</tt>, set the
* <tt>connection</tt> to be read only.
*
* @param connection a database connection instance
* @param dcc a <tt>DatabaseConnectionContext</tt> instance
*/
public static void checkReadonly(Connection connection,
DatabaseConnectionContext dcc) {
try {
if (dcc.isReadonly())
connection.setReadOnly(true);
} catch (SQLException ex) {
throw new CreateConnectionFailureException(
"Faied to set readonly property for connection \""
+ dcc.getConnectionName() + "\" because " + ex.getMessage(), ex);
}
}
/**
* If the database connection context specifies <tt>autocommit</tt> to be
* true, set the <tt>connection</tt> to be auto commit.
*
* @param connection a database connection instance
* @param dcc a <tt>DatabaseConnectionContext</tt> instance
*/
public static void checkAutoCommit(Connection connection,
DatabaseConnectionContext dcc) {
try {
if (!dcc.isAutoCommit())
connection.setAutoCommit(false);
} catch (SQLException ex) {
throw new CreateConnectionFailureException(
"Faied to set readonly property for connection \""
+ dcc.getConnectionName() + "\" because " + ex.getMessage(), ex);
}
}
/**
* If the database connection context specifies <tt>transaction_isolation_level</tt>,
* set the transaction isolation level of the <tt>connection</tt>.
*
* @param connection a database connection instance
* @param dcc a <tt>DatabaseConnectionContext</tt> instance
*/
public static void checkTransactionIsolationLevel(Connection connection,
DatabaseConnectionContext dcc) {
try {
if (dcc.hasSpecifiedTransactionIsolationLevel())
connection.setTransactionIsolation(dcc.getTransactionIsolationLevel());
} catch (SQLException ex) {
throw new CreateConnectionFailureException(
"Faied to set transaction isolation property for connection \""
+ dcc.getConnectionName() + "\" because " + ex.getMessage(), ex);
}
}
/**
* If the database connection context specifies <tt>beforeConnection</tt>
* class name, execute the <tt>beforeConnectionMethodName</tt>.
*
* @param dcc a <tt>DatabaseConnectionContext</tt> instance
*/
public static void beforeConnection(DatabaseConnectionContext dcc) {
String beforeClassName = dcc.getBeforeConnectionClassName();
if (beforeClassName != null) {
OrmObjectFactory.getInstance().execute(beforeClassName,
dcc.getBeforeConnectionMethodName(), null);
}
}
/**
* If the database connection context specifies <tt>afterConnection</tt>
* class name, execute the <tt>afterConnectionMethodName</tt>.
*
* @param dcc a <tt>DatabaseConnectionContext</tt> instance
*/
public static void afterConnection(Connection connection,
DatabaseConnectionContext dcc) {
String afterClassName = dcc.getAfterConnectionClassName();
if (afterClassName != null) {
OrmObjectFactory.getInstance().execute(afterClassName,
dcc.getAfterConnectionMethodName(),
new Object[] { connection });
}
}
private static String loginUsername() {
return LoginHelper.loginUserId();
}
private static String loginPassword() {
return LoginHelper.loginPassword();
}
private static LogUtil log = LogUtil.getLogger(ConnectionUtil.class
.getName());
}