content: package com.taobao.yugong.common.db;
  
  import java.util.Map;
  import java.util.Properties;
  
  import javax.sql.DataSource;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import com.alibaba.druid.pool.DruidDataSource;
  import com.google.common.base.Function;
  import com.google.common.collect.MigrateMap;
  import com.taobao.yugong.common.lifecycle.AbstractYuGongLifeCycle;
  import com.taobao.yugong.common.lifecycle.YuGongLifeCycle;
  import com.taobao.yugong.common.model.DataSourceConfig;
  import com.taobao.yugong.common.model.DbType;
  import com.taobao.yugong.exception.YuGongException;
  
  /**
   * 获取数据库连接
   *
   * @author agapple 2013年2月25日 下午8:00:41
   * @since 1.0.0
   */
  public class DataSourceFactory extends AbstractYuGongLifeCycle implements YuGongLifeCycle {
  
      private static final Logger               logger      = LoggerFactory.getLogger(DataSourceFactory.class);
      private int                               maxWait     = 5 * 1000;
      private int                               minIdle     = 0;
      private int                               initialSize = 0;
      private int                               maxActive   = 32;
  
      private Map<DataSourceConfig, DataSource> dataSources;
  
      public void start() {
          super.start();
          dataSources = MigrateMap.makeComputingMap(new Function<DataSourceConfig, DataSource>() {
  
              public DataSource apply(DataSourceConfig config) {
                  return createDataSource(config.getUrl(),
                      config.getUsername(),
                      config.getPassword(),
                      config.getType(),
                      config.getProperties());
              }
          });
  
      }
  
      public void stop() {
          super.stop();
  
          for (DataSource source : dataSources.values()) {
              DruidDataSource basicDataSource = (DruidDataSource) source;
              basicDataSource.close();
          }
  
          dataSources.clear();
      }
  
      public DataSource getDataSource(DataSourceConfig config) {
          return dataSources.get(config);
      }
  
      public DataSource getDataSource(String url, String userName, String password, DbType dbType, Properties props) {
          return dataSources.get(new DataSourceConfig(url, userName, password, dbType, props));
      }
  
      private DataSource createDataSource(String url, String userName, String password, DbType dbType, Properties props) {
          try {
              int maxActive = Integer.valueOf(props.getProperty("maxActive", String.valueOf(this.maxActive)));
              if (maxActive < 0) {
                  maxActive = 200;
              }
              DruidDataSource dataSource = new DruidDataSource();
              dataSource.setUrl(url);
              dataSource.setUsername(userName);
              dataSource.setPassword(password);
              dataSource.setUseUnfairLock(true);
              dataSource.setNotFullTimeoutRetryCount(2);
              dataSource.setInitialSize(initialSize);
              dataSource.setMinIdle(minIdle);
              dataSource.setMaxActive(maxActive);
              dataSource.setMaxWait(maxWait);
              dataSource.setDriverClassName(dbType.getDriver());
              // 动态的参数
              if (props != null && props.size() > 0) {
                  for (Map.Entry<Object, Object> entry : props.entrySet()) {
                      dataSource.addConnectionProperty(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
                  }
              }
  
              if (dbType.isOracle()) {
                  dataSource.addConnectionProperty("restrictGetTables", "true");
                  dataSource.addConnectionProperty("oracle.jdbc.V8Compatible", "true");
                  dataSource.setValidationQuery("select 1 from dual");
                  dataSource.setExceptionSorter("com.alibaba.druid.pool.vendor.OracleExceptionSorter");
              } else if (dbType.isMysql() || dbType.isDRDS()) {
                  dataSource.addConnectionProperty("useServerPrepStmts", "false");
                  dataSource.addConnectionProperty("rewriteBatchedStatements", "true");
                  dataSource.addConnectionProperty("allowMultiQueries", "true");
                  dataSource.addConnectionProperty("readOnlyPropagatesToServer", "false");
                  dataSource.setValidationQuery("select 1");
                  dataSource.setExceptionSorter("com.alibaba.druid.pool.vendor.MySqlExceptionSorter");
                  dataSource.setValidConnectionCheckerClassName("com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker");
              } else {
                  logger.error("Unknow database type");
              }
              return dataSource;
          } catch (Throwable e) {
              throw new YuGongException("create dataSource error!", e);
          }
      }
  
      public void setMaxWait(int maxWait) {
          this.maxWait = maxWait;
      }
  
      public void setMinIdle(int minIdle) {
          this.minIdle = minIdle;
      }
  
      public void setInitialSize(int initialSize) {
          this.initialSize = initialSize;
      }
  
      public void setMaxActive(int maxActive) {
          this.maxActive = maxActive;
      }
  
  }
  