Package org.wso2.carbon.dataservices.core

Source Code of org.wso2.carbon.dataservices.core.DBCPConnectionManager

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you under the Apache License,
*  Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*
*/
package org.wso2.carbon.dataservices.core;

import javax.sql.DataSource;
import javax.sql.XADataSource;

import org.apache.commons.dbcp.AbandonedConfig;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DataSourceConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.dbcp.managed.DataSourceXAConnectionFactory;
import org.apache.commons.dbcp.managed.LocalXAConnectionFactory;
import org.apache.commons.dbcp.managed.ManagedDataSource;
import org.apache.commons.dbcp.managed.XAConnectionFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.wso2.carbon.dataservices.common.DBConstants.RDBMS;
import org.wso2.carbon.dataservices.common.DBConstants;
import org.wso2.carbon.dataservices.common.RDBMSUtils;
import org.wso2.carbon.dataservices.core.description.config.Config;
import org.wso2.carbon.dataservices.core.description.config.RDBMSConfig;
import org.wso2.carbon.dataservices.core.description.xa.XADataSourceInfo;
import org.wso2.carbon.dataservices.core.engine.DataService;

/**
* Helper for DBCP library based JDBC connection pooling.
*/
public class DBCPConnectionManager {
 
  private static final Log log = LogFactory.getLog(DBCPConnectionManager.class);
 
  /** Encapsulated data source object */
  private DataSource datasource;
 
  /** Connection pool */
  private GenericObjectPool pool;
 
  /**
   * Returns the DataSource object created by the pooling manager,
   * this object is used for retrieving pooled JDBC connections.
   * @see DataSourcedatasource
   */
  public DataSource getDatasource() {
    return datasource;
  }
 
  public void close() {
    try {
      this.getObjectPool().close();
    } catch (Exception e) {
      log.error("Error in closing DBCPConnectionManager: " + e.getMessage(), e);
    }
  }
 
  /**
   * Creates an instance using the information in the given Config object.
   */
  public DBCPConnectionManager(Config config) throws DataServiceFault {
    this(config, null);
  }
 
  /**
   * Creates a DBCPConnectionManager with the given configuration and an external data source,
   * the external data source will be usually retrieved from JNDI.
   * @param config The data source configuration
   * @param externalDS External data source
   * @throws DataServiceFault
   */
  public DBCPConnectionManager(Config config, DataSource externalDS) throws DataServiceFault {
    try {
      connectToDB(config, externalDS);
    } catch (Exception e) {
      throw new DataServiceFault(e,
          "Error occured connecting to database using connection pooling manager");
    }
  }

  protected void finalize() {
    try {
      super.finalize();
    } catch (Throwable e) {
      log.error("Error occured when finalizing.", e);
    }
  }
 
  /**
   * Creates the poolable DataSource object with the given parameters.
   */
  private void connectToDB(Config config, DataSource externalDS) throws DataServiceFault
    String driverClass = config.getProperty(RDBMS.DRIVER);
    try {
      if (!DBUtils.isEmptyString(driverClass)) {
        java.lang.Class.forName(driverClass);
      }
    } catch (ClassNotFoundException e) {
      throw new DataServiceFault(e, "Error locating class " + driverClass);
    }
    try {
      this.datasource = setupDataSource(config, externalDS);
    } catch (Exception e) {
      throw new DataServiceFault(e, "Error occured while creating datasource.");
    }
  }

  public ObjectPool getObjectPool() {
    return this.pool;
  }

  /**
   * Create a generic non-XA connection factory.
   *
   * @param config
   *            Configuration which contains the connection properties
   * @return Newly created pool connection
   * @throws Exception
   *             Error occurred when parsing properties to create the
   *             connection factory
   */
  private GenericObjectPool createGenericConnectionFactory(Config config) throws Exception {
    GenericObjectPool poolConnection = new GenericObjectPool();

    String maxPool = config.getProperty(RDBMS.MAX_POOL_SIZE);
    String maxIdle = config.getProperty(RDBMS.MAX_IDLE);
    String minPool = config.getProperty(RDBMS.MIN_POOL_SIZE);
    String maxWait = config.getProperty(RDBMS.MAX_WAIT);
    String testOnReturn = config.getProperty(RDBMS.TEST_ON_RETURN);
    String testOnBorrow = config.getProperty(RDBMS.TEST_ON_BORROW);
    String testWhileIdle = config.getProperty(RDBMS.TEST_WHILE_IDLE);
    String timeBetweenEvictionRunsMillis = config.getProperty(
        RDBMS.TIME_BETWEEN_EVICTION_RUNS_MILLS);
    String numTestsPerEvictionRun = config.getProperty(RDBMS.NUM_TESTS_PER_EVICTION_RUN);
    String minEvictableIdleTimeMillis = config.getProperty(
        RDBMS.MIN_EVICTABLE_IDLE_TIME_MILLIS);

    int minPoolSize = DBConstants.DEFAULT_DBCP_MIN_POOL_SIZE;
    int maxPoolSize = DBConstants.DEFAULT_DBCP_MAX_POOL_SIZE;
    try {
      if (!DBUtils.isEmptyString(maxPool)) {
        maxPoolSize = Integer.valueOf(maxPool).intValue();
        poolConnection.setMaxActive(maxPoolSize);
      }
      if (!DBUtils.isEmptyString(minPool)) {
        minPoolSize = Integer.valueOf(minPool).intValue();
        poolConnection.setMinIdle(minPoolSize);
      }
      int maxPoolIdle = poolConnection.getMaxIdle();
      if (!DBUtils.isEmptyString(maxIdle)) {
        maxPoolIdle = Integer.valueOf(maxIdle).intValue();
        poolConnection.setMaxIdle(maxPoolIdle);
      }
      if (!DBUtils.isEmptyString(maxWait)) {
        int maxPoolWait = Integer.valueOf(maxWait).intValue();
        poolConnection.setMaxWait(maxPoolWait);
      }
      if (!DBUtils.isEmptyString(testOnBorrow)) {
        poolConnection.setTestOnBorrow(Boolean.parseBoolean(testOnBorrow));
      }
      if (!DBUtils.isEmptyString(testOnReturn)) {
        poolConnection.setTestOnReturn(Boolean.parseBoolean(testOnReturn));
      }
      if (!DBUtils.isEmptyString(testWhileIdle)) {
        poolConnection.setTestWhileIdle(Boolean.parseBoolean(testWhileIdle));
      }
      if (!DBUtils.isEmptyString(timeBetweenEvictionRunsMillis)) {
        long timeBetweenPoolEvictionRunsMillis = Long
            .valueOf(timeBetweenEvictionRunsMillis).longValue();
        poolConnection.setTimeBetweenEvictionRunsMillis(timeBetweenPoolEvictionRunsMillis);
      }
      if (!DBUtils.isEmptyString(numTestsPerEvictionRun)) {
        int numTestsPerPoolEvictionRun = Integer.valueOf(numTestsPerEvictionRun).intValue();
        poolConnection.setNumTestsPerEvictionRun(numTestsPerPoolEvictionRun);
      }
      if (!DBUtils.isEmptyString(minEvictableIdleTimeMillis)) {
        long minPoolEvictableIdleTimeMillis = Long.valueOf(minEvictableIdleTimeMillis)
            .longValue();
        poolConnection.setMinEvictableIdleTimeMillis(minPoolEvictableIdleTimeMillis);
      }
      return poolConnection;
    } catch (NumberFormatException e) {
      log.error("Non-numeric value found for numeric pool configuration property", e);
      throw e;
    }

  }
   
  /**
   * Creates a DBCP pooled data source with the given parameters and a data source.
   * @param config Connection parameters
   * @param externalDS The data source to be used
   * @return Pooled data source
   * @throws Exception
   */
  private DataSource setupDataSource(Config config, DataSource externalDS) throws Exception {
    ConnectionFactory connectionFactory;
    DataService dataService = config.getDataService();
    String jdbcURL = config.getProperty(RDBMS.PROTOCOL);
    String userName = config.getProperty(RDBMS.USER);
    String password = DBUtils.resolvePasswordValue(config.getDataService(),
        config.getProperty(RDBMS.PASSWORD));
    String removeAbandoned = config.getProperty(RDBMS.REMOVE_ABANDONED);
    String removeAbandonedTimeout = config.getProperty(RDBMS.REMOVE_ABONDONED_TIMEOUT);
    String logAbandoned = config.getProperty(RDBMS.LOG_ABANDONED);
    String transactionIsolation = config.getProperty(RDBMS.TRANSACTION_ISOLATION);
    int defaultTransactionIsolation = RDBMSUtils.toIntTransactionIsolation(transactionIsolation);
   
    /* XA data source */
    boolean isXADS = (config instanceof RDBMSConfig) && ((RDBMSConfig) config).hasXADS();

    if (isXADS) {
      if (!dataService.isEnableXA()) {
        throw new DataServiceFault(
            "Internal XADataSource: XA transaction support must be enabled to use XADataSources");
      }
      XADataSourceInfo xaInfo = ((RDBMSConfig) config).getXADataSourceInfo()
      connectionFactory = new DataSourceXAConnectionFactory(
          dataService.getDSSTxManager().getTransactionManager(), xaInfo.getXADataSource());
    } else if (externalDS != null) {
      if (externalDS instanceof XADataSource) {
        if (!dataService.isEnableXA()) {
          throw new DataServiceFault(
              "External XADataSource: XA transaction support must be enabled to use XADataSources");
        }
        connectionFactory = new DataSourceXAConnectionFactory(
            dataService.getDSSTxManager().getTransactionManager(), (XADataSource) externalDS);
      } else {
        connectionFactory = new DataSourceConnectionFactory(externalDS);
      }
    } else {
      connectionFactory = new DriverManagerConnectionFactory(jdbcURL, userName, password);
      if (dataService.isEnableXA()) {
        connectionFactory = new LocalXAConnectionFactory(
            dataService.getDSSTxManager().getTransactionManager(), connectionFactory);       
      }
    }
    this.pool = createGenericConnectionFactory(config);
    AbandonedConfig abandonedConfig = new AbandonedConfig();
    if (!DBUtils.isEmptyString(logAbandoned)) {
      abandonedConfig.setLogAbandoned(Boolean.parseBoolean(logAbandoned));
    }
    if (!DBUtils.isEmptyString(removeAbandonedTimeout)) {
      abandonedConfig.setRemoveAbandonedTimeout(Integer.parseInt(removeAbandonedTimeout));
    }
    if (!DBUtils.isEmptyString(removeAbandoned)) {
      abandonedConfig.setRemoveAbandoned(Boolean.parseBoolean(removeAbandoned));
    }

    String validationQuery = config.getProperty(RDBMS.VALIDATION_QUERY);
    boolean hasValQuery = validationQuery != null && validationQuery.trim().length() > 0;
    PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory,
        this.pool, null, hasValQuery ? validationQuery : null, false, true,
        defaultTransactionIsolation, abandonedConfig);

    this.pool.setFactory(factory);
    PoolingDataSource dataSource;
    if (dataService.isEnableXA()) {
      /* for XA-transactions */
      dataSource = new ManagedDataSource(this.pool,
          ((XAConnectionFactory) connectionFactory).getTransactionRegistry());
    } else {
      dataSource = new PoolingDataSource(this.pool);
    }
    dataSource.setAccessToUnderlyingConnectionAllowed(true);
    return dataSource;
  }

}
TOP

Related Classes of org.wso2.carbon.dataservices.core.DBCPConnectionManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.