/*
* Copyright 1999-2017 Alibaba Group Holding Ltd.
*
* Licensed 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 com.alibaba.druid.pool;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import javax.sql.DataSource;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
public class DruidDataSourceFactory implements ObjectFactory {
private final static Log LOG = LogFactory.getLog(DruidDataSourceFactory.class);
static final int UNKNOWN_TRANSACTIONISOLATION = -1;
public final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
public final static String PROP_DEFAULTREADONLY = "defaultReadOnly";
public final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
public final static String PROP_DEFAULTCATALOG = "defaultCatalog";
public final static String PROP_DRIVERCLASSNAME = "driverClassName";
public final static String PROP_MAXACTIVE = "maxActive";
public final static String PROP_MAXIDLE = "maxIdle";
public final static String PROP_MINIDLE = "minIdle";
public final static String PROP_INITIALSIZE = "initialSize";
public final static String PROP_MAXWAIT = "maxWait";
public final static String PROP_TESTONBORROW = "testOnBorrow";
public final static String PROP_TESTONRETURN = "testOnReturn";
public final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
public final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
public final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
public final static String PROP_PHY_TIMEOUT_MILLIS = "phyTimeoutMillis";
public final static String PROP_TESTWHILEIDLE = "testWhileIdle";
public final static String PROP_PASSWORD = "password";
public final static String PROP_URL = "url";
public final static String PROP_USERNAME = "username";
public final static String PROP_VALIDATIONQUERY = "validationQuery";
public final static String PROP_VALIDATIONQUERY_TIMEOUT = "validationQueryTimeout";
public final static String PROP_INITCONNECTIONSQLS = "initConnectionSqls";
public final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
public final static String PROP_REMOVEABANDONED = "removeAbandoned";
public final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
public final static String PROP_LOGABANDONED = "logAbandoned";
public final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
public final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
public final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";
public final static String PROP_FILTERS = "filters";
public final static String PROP_EXCEPTION_SORTER = "exceptionSorter";
public final static String PROP_EXCEPTION_SORTER_CLASS_NAME = "exception-sorter-class-name";
public final static String PROP_NAME = "name";
public final static String PROP_INIT = "init";
private final static String[] ALL_PROPERTIES = {PROP_DEFAULTAUTOCOMMIT,
PROP_DEFAULTREADONLY, PROP_DEFAULTTRANSACTIONISOLATION, PROP_DEFAULTCATALOG, PROP_DRIVERCLASSNAME,
PROP_MAXACTIVE, PROP_MAXIDLE, PROP_MINIDLE, PROP_INITIALSIZE, PROP_MAXWAIT, PROP_TESTONBORROW,
PROP_TESTONRETURN, PROP_TIMEBETWEENEVICTIONRUNSMILLIS, PROP_NUMTESTSPEREVICTIONRUN,
PROP_MINEVICTABLEIDLETIMEMILLIS, PROP_TESTWHILEIDLE, PROP_PASSWORD, PROP_FILTERS, PROP_URL, PROP_USERNAME,
PROP_VALIDATIONQUERY, PROP_VALIDATIONQUERY_TIMEOUT, PROP_INITCONNECTIONSQLS,
PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED, PROP_REMOVEABANDONED, PROP_REMOVEABANDONEDTIMEOUT,
PROP_LOGABANDONED, PROP_POOLPREPAREDSTATEMENTS, PROP_MAXOPENPREPAREDSTATEMENTS, PROP_CONNECTIONPROPERTIES,
PROP_EXCEPTION_SORTER, PROP_EXCEPTION_SORTER_CLASS_NAME, PROP_INIT, PROP_NAME, //
"druid.timeBetweenLogStatsMillis", //
"druid.stat.sql.MaxSize", //
"druid.clearFiltersEnable", //
"druid.resetStatEnable", //
"druid.notFullTimeoutRetryCount", //
"druid.maxWaitThreadCount", //
"druid.failFast", //
"druid.phyTimeoutMillis", //
"druid.wall.tenantColumn", //
"druid.wall.updateAllow", //
"druid.wall.deleteAllow", //
"druid.wall.insertAllow", //
"druid.wall.selelctAllow", //
"druid.wall.multiStatementAllow", //
};
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
throws Exception {
// We only know how to deal with <code>javax.naming.Reference</code>s
// that specify a class name of "javax.sql.DataSource"
if ((obj == null) || !(obj instanceof Reference)) {
return null;
}
Reference ref = (Reference) obj;
if ((!"javax.sql.DataSource".equals(ref.getClassName())) //
&& (!"com.alibaba.druid.pool.DruidDataSource".equals(ref.getClassName())) //
) {
return null;
}
Properties properties = new Properties();
for (int i = 0; i < ALL_PROPERTIES.length; i++) {
String propertyName = ALL_PROPERTIES[i];
RefAddr ra = ref.get(propertyName);
if (ra != null) {
String propertyValue = ra.getContent().toString();
properties.setProperty(propertyName, propertyValue);
}
}
return createDataSourceInternal(properties);
}
protected DataSource createDataSourceInternal(Properties properties) throws Exception {
DruidDataSource dataSource = new DruidDataSource();
config(dataSource, properties);
return dataSource;
}
@SuppressWarnings("rawtypes")
public static DataSource createDataSource(Properties properties) throws Exception {
return createDataSource((Map) properties);
}
@SuppressWarnings("rawtypes")
public static DataSource createDataSource(Map properties) throws Exception {
DruidDataSource dataSource = new DruidDataSource();
config(dataSource, properties);
return dataSource;
}
@SuppressWarnings({"deprecation", "rawtypes"})
public static void config(DruidDataSource dataSource, Map<?, ?> properties) throws SQLException {
String value = null;
value = (String) properties.get(PROP_DEFAULTAUTOCOMMIT);
if (value != null) {
dataSource.setDefaultAutoCommit(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_DEFAULTREADONLY);
if (value != null) {
dataSource.setDefaultReadOnly(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_DEFAULTTRANSACTIONISOLATION);
if (value != null) {
int level = UNKNOWN_TRANSACTIONISOLATION;
if ("NONE".equalsIgnoreCase(value)) {
level = Connection.TRANSACTION_NONE;
} else if ("READ_COMMITTED".equalsIgnoreCase(value)) {
level = Connection.TRANSACTION_READ_COMMITTED;
} else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {
level = Connection.TRANSACTION_READ_UNCOMMITTED;
} else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {
level = Connection.TRANSACTION_REPEATABLE_READ;
} else if ("SERIALIZABLE".equalsIgnoreCase(value)) {
level = Connection.TRANSACTION_SERIALIZABLE;
} else {
try {
level = Integer.parseInt(value);
} catch (NumberFormatException e) {
LOG.error("Could not parse defaultTransactionIsolation: " + value);
LOG.error("WARNING: defaultTransactionIsolation not set");
LOG.error("using default value of database driver");
level = UNKNOWN_TRANSACTIONISOLATION;
}
}
dataSource.setDefaultTransactionIsolation(level);
}
value = (String) properties.get(PROP_DEFAULTCATALOG);
if (value != null) {
dataSource.setDefaultCatalog(value);
}
value = (String) properties.get(PROP_DRIVERCLASSNAME);
if (value != null) {
dataSource.setDriverClassName(value);
}
value = (String) properties.get(PROP_MAXACTIVE);
if (value != null) {
dataSource.setMaxActive(Integer.parseInt(value));
}
value = (String) properties.get(PROP_MAXIDLE);
if (value != null) {
dataSource.setMaxIdle(Integer.parseInt(value));
}
value = (String) properties.get(PROP_MINIDLE);
if (value != null) {
dataSource.setMinIdle(Integer.parseInt(value));
}
value = (String) properties.get(PROP_INITIALSIZE);
if (value != null) {
dataSource.setInitialSize(Integer.parseInt(value));
}
value = (String) properties.get(PROP_MAXWAIT);
if (value != null) {
dataSource.setMaxWait(Long.parseLong(value));
}
value = (String) properties.get(PROP_TESTONBORROW);
if (value != null) {
dataSource.setTestOnBorrow(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_TESTONRETURN);
if (value != null) {
dataSource.setTestOnReturn(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);
if (value != null) {
dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(value));
}
value = (String) properties.get(PROP_NUMTESTSPEREVICTIONRUN);
if (value != null) {
dataSource.setNumTestsPerEvictionRun(Integer.parseInt(value));
}
value = (String) properties.get(PROP_MINEVICTABLEIDLETIMEMILLIS);
if (value != null) {
dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(value));
}
value = (String) properties.get(PROP_PHY_TIMEOUT_MILLIS);
if (value != null) {
dataSource.setPhyTimeoutMillis(Long.parseLong(value));
}
value = (String) properties.get(PROP_TESTWHILEIDLE);
if (value != null) {
dataSource.setTestWhileIdle(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_PASSWORD);
if (value != null) {
dataSource.setPassword(value);
}
value = (String) properties.get(PROP_URL);
if (value != null) {
dataSource.setUrl(value);
}
value = (String) properties.get(PROP_USERNAME);
if (value != null) {
dataSource.setUsername(value);
}
value = (String) properties.get(PROP_VALIDATIONQUERY);
if (value != null) {
dataSource.setValidationQuery(value);
}
value = (String) properties.get(PROP_VALIDATIONQUERY_TIMEOUT);
if (value != null) {
dataSource.setValidationQueryTimeout(Integer.parseInt(value));
}
value = (String) properties.get(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);
if (value != null) {
dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_REMOVEABANDONED);
if (value != null) {
dataSource.setRemoveAbandoned(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_REMOVEABANDONEDTIMEOUT);
if (value != null) {
dataSource.setRemoveAbandonedTimeout(Integer.parseInt(value));
}
value = (String) properties.get(PROP_LOGABANDONED);
if (value != null) {
dataSource.setLogAbandoned(Boolean.valueOf(value).booleanValue());
}
value = (String) properties.get(PROP_POOLPREPAREDSTATEMENTS);
if (value != null) {
boolean poolPreparedStatements = Boolean.valueOf(value).booleanValue();
dataSource.setPoolPreparedStatements(poolPreparedStatements);
if (poolPreparedStatements) {
value = (String) properties.get(PROP_MAXOPENPREPAREDSTATEMENTS);
if (value != null) {
dataSource.setMaxOpenPreparedStatements(Integer.parseInt(value));
}
}
}
value = (String) properties.get(PROP_FILTERS);
if (value != null) {
dataSource.setFilters(value);
}
value = (String) properties.get(PROP_EXCEPTION_SORTER);
if (value != null) {
dataSource.setExceptionSorter(value);
}
value = (String) properties.get(PROP_EXCEPTION_SORTER_CLASS_NAME);
if (value != null) {
dataSource.setExceptionSorter(value);
}
value = (String) properties.get(PROP_INITCONNECTIONSQLS);
if (value != null) {
StringTokenizer tokenizer = new StringTokenizer(value, ";");
dataSource.setConnectionInitSqls(Collections.list(tokenizer));
}
value = (String) properties.get(PROP_CONNECTIONPROPERTIES);
if (value != null) {
dataSource.setConnectionProperties(value);
}
{
Properties dataSourceProperties = null;
for (Map.Entry entry : properties.entrySet()) {
String entryKey = (String) entry.getKey();
if (entryKey.startsWith("druid.")) {
if (dataSourceProperties == null) {
dataSourceProperties = new Properties();
}
String entryValue = (String) entry.getValue();
dataSourceProperties.put(entryKey, entryValue);
}
}
if (dataSourceProperties != null) {
dataSource.configFromPropety(dataSourceProperties);
}
}
value = (String) properties.get(PROP_INIT);
if ("true".equals(value)) {
dataSource.init();
}
}
}