/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA 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 OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.webgate.api.jdbc.custom;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.webgate.api.WGInvalidDatabaseException;
import de.innovationgate.webgate.api.jdbc.pool.DBCPConnectionProvider;
public class JDBCConnectionProvider {
private Driver _driver;
private DataSource _dataSource;
private String _path;
private Properties _props;
private DBCPConnectionProvider _connectionProvider;
public JDBCConnectionProvider(String path, String driverClass, Properties props, boolean pool) throws JDBCConnectionException {
_path = path;
_props = props;
// Get DataSource or Driver object
if (path.startsWith("jdbc:")) {
if (pool) {
setupDBCPDataSource(path, driverClass, props);
}
else {
setupNonpoolingDriver(path, driverClass);
}
}
else {
setupJNDIDataSource(path);
}
}
private void setupDBCPDataSource(String path, String driverClass, Properties props) throws JDBCConnectionException {
try {
// Load driver so it registers with driver manager
if (driverClass != null) {
Class.forName(driverClass);
}
// Divide properties up between JDBC properties and DBCP properties, store them as hibernate properties so the hibernate DBCP connection provider understands them
Properties providerProps = new Properties();
providerProps.put(Environment.URL, path);
Iterator<Map.Entry<Object,Object>> propsIt = props.entrySet().iterator();
while (propsIt.hasNext()) {
Map.Entry<java.lang.Object, java.lang.Object> entry = (Map.Entry<java.lang.Object, java.lang.Object>) propsIt.next();
String key = (String) entry.getKey();
if (key.startsWith("dbcp.")) {
providerProps.put("hibernate." + key, (String) entry.getValue());
}
else {
providerProps.put("hibernate.connection." + key, (String) entry.getValue());
}
}
// Create a DBCPConnectionProvider with the created hibernate properties
_connectionProvider = new DBCPConnectionProvider();
_connectionProvider.configure(providerProps);
}
catch (HibernateException e) {
throw new JDBCConnectionException("Exception creating DBCP data source", e);
}
catch (ClassNotFoundException e) {
throw new JDBCConnectionException("Exception creating DBCP data source", e);
}
}
private void setupJNDIDataSource(String path) throws JDBCConnectionException {
try {
Context context = new InitialContext();
Object dataSourceObject = context.lookup(path);
_dataSource = (DataSource) javax.rmi.PortableRemoteObject.narrow(dataSourceObject, DataSource.class);
if (_dataSource == null) {
throw new JDBCConnectionException("Could not load data source under JNDI path " + path);
}
}
catch (ClassCastException e) {
throw new JDBCConnectionException("No data source object under JNDI path " + path);
}
catch (NamingException e) {
throw new JDBCConnectionException("JNDI error retrieving data source: " + e.getMessage());
}
}
private void setupNonpoolingDriver(String path, String driverClass) throws JDBCConnectionException {
_driver = null;
if (driverClass != null) {
try {
_driver = (Driver) Class.forName(driverClass).newInstance();
}
catch (ClassNotFoundException e1) {
throw new JDBCConnectionException("Unable to load driver class " + driverClass);
}
catch (InstantiationException e) {
throw new JDBCConnectionException("Unable to instantiate driver class " + driverClass);
}
catch (IllegalAccessException e) {
throw new JDBCConnectionException("No access to driver class " + driverClass);
}
}
else {
try {
_driver = DriverManager.getDriver(path);
}
catch (SQLException e) {
throw new JDBCConnectionException("SQL Error while determining driver: ", e);
}
}
if (_driver == null) {
throw new JDBCConnectionException("Cannot find JDBC driver for url: " + path);
}
}
public Connection getConnection() throws SQLException {
if (_driver != null) {
return _driver.connect(_path, _props);
}
else if (_connectionProvider != null) {
return _connectionProvider.getConnection();
}
else {
return _dataSource.getConnection();
}
}
public void close() throws JDBCConnectionException {
try {
if (_connectionProvider != null) {
_connectionProvider.close();
}
}
catch (Exception e) {
throw new JDBCConnectionException("Exception closing connection provider", e);
}
}
public List<String> getDatabaseTables() throws SQLException {
Connection conn = getConnection();
try {
return getDatabaseTables(conn);
}
finally {
try {
conn.close();
}
catch (SQLException e) {
}
}
}
public static List<String> getDatabaseTables(Connection conn) throws SQLException {
List<String> tables = new ArrayList<String>();
DatabaseMetaData dbMeta = conn.getMetaData();
ResultSet resultSet = dbMeta.getTables(null, null, null, new String[] {"TABLE"});
if (resultSet.getType() != ResultSet.TYPE_FORWARD_ONLY && !resultSet.isBeforeFirst()) {
resultSet.beforeFirst();
}
while (resultSet.next()) {
tables.add(resultSet.getString("TABLE_NAME").toLowerCase());
}
resultSet.close();
return tables;
}
}