/*- * ============LICENSE_START======================================================= * openecomp * ================================================================================ * Copyright (C) 2016 - 2017 AT&T * ================================================================================ * 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. * ============LICENSE_END========================================================= */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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.apache.tomcat.jdbc.pool; import java.sql.Connection; import java.util.Hashtable; import java.util.Properties; import javax.management.ObjectName; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.NamingException; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import javax.sql.DataSource; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; /** *
JNDI object factory that creates an instance of
* BasicDataSource
that has been configured based on the
* RefAddr
values of the specified Reference
,
* which must match the names and data types of the
* BasicDataSource
bean properties.
Create and return a new BasicDataSource
instance. If no
* instance can be created, return null
instead.
nameCtx
* @param nameCtx The context relative to which the name
* parameter is specified, or null
if name
* is relative to the default initial context
* @param environment The possibly null environment that is used in
* creating this object
*
* @exception Exception if an exception occurs creating the instance
*/
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable,?> environment) throws Exception {
// We only know how to deal with javax.naming.Reference
s
// that specify a class name of "javax.sql.DataSource"
if ((obj == null) || !(obj instanceof Reference)) {
return null;
}
Reference ref = (Reference) obj;
boolean XA = false;
boolean ok = false;
if ("javax.sql.DataSource".equals(ref.getClassName())) {
ok = true;
}
if ("javax.sql.XADataSource".equals(ref.getClassName())) {
ok = true;
XA = true;
}
if (org.apache.tomcat.jdbc.pool.DataSource.class.getName().equals(ref.getClassName())) {
ok = true;
}
if (!ok) {
log.warn(ref.getClassName()+" is not a valid class name/type for this JNDI factory.");
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 createDataSource(properties,nameCtx,XA);
}
public static PoolConfiguration parsePoolProperties(Properties properties) {
PoolConfiguration poolProperties = new PoolProperties();
String value = null;
value = properties.getProperty(PROP_DEFAULTAUTOCOMMIT);
if (value != null) {
poolProperties.setDefaultAutoCommit(Boolean.valueOf(value));
}
value = properties.getProperty(PROP_DEFAULTREADONLY);
if (value != null) {
poolProperties.setDefaultReadOnly(Boolean.valueOf(value));
}
value = properties.getProperty(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) {
System.err.println("Could not parse defaultTransactionIsolation: " + value);
System.err.println("WARNING: defaultTransactionIsolation not set");
System.err.println("using default value of database driver");
level = UNKNOWN_TRANSACTIONISOLATION;
}
}
poolProperties.setDefaultTransactionIsolation(level);
}
value = properties.getProperty(PROP_DEFAULTCATALOG);
if (value != null) {
poolProperties.setDefaultCatalog(value);
}
value = properties.getProperty(PROP_DRIVERCLASSNAME);
if (value != null) {
poolProperties.setDriverClassName(value);
}
value = properties.getProperty(PROP_MAXACTIVE);
if (value != null) {
poolProperties.setMaxActive(Integer.parseInt(value));
}
value = properties.getProperty(PROP_MAXIDLE);
if (value != null) {
poolProperties.setMaxIdle(Integer.parseInt(value));
}
value = properties.getProperty(PROP_MINIDLE);
if (value != null) {
poolProperties.setMinIdle(Integer.parseInt(value));
}
value = properties.getProperty(PROP_INITIALSIZE);
if (value != null) {
poolProperties.setInitialSize(Integer.parseInt(value));
}
value = properties.getProperty(PROP_MAXWAIT);
if (value != null) {
poolProperties.setMaxWait(Integer.parseInt(value));
}
value = properties.getProperty(PROP_TESTONBORROW);
if (value != null) {
poolProperties.setTestOnBorrow(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_TESTONRETURN);
if (value != null) {
poolProperties.setTestOnReturn(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_TESTONCONNECT);
if (value != null) {
poolProperties.setTestOnConnect(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);
if (value != null) {
poolProperties.setTimeBetweenEvictionRunsMillis(Integer.parseInt(value));
}
value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN);
if (value != null) {
poolProperties.setNumTestsPerEvictionRun(Integer.parseInt(value));
}
value = properties.getProperty(PROP_MINEVICTABLEIDLETIMEMILLIS);
if (value != null) {
poolProperties.setMinEvictableIdleTimeMillis(Integer.parseInt(value));
}
value = properties.getProperty(PROP_TESTWHILEIDLE);
if (value != null) {
poolProperties.setTestWhileIdle(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_PASSWORD);
if (value != null) {
poolProperties.setPassword(value);
}
value = properties.getProperty(PROP_URL);
if (value != null) {
poolProperties.setUrl(value);
}
value = properties.getProperty(PROP_USERNAME);
if (value != null) {
poolProperties.setUsername(value);
}
value = properties.getProperty(PROP_VALIDATIONQUERY);
if (value != null) {
poolProperties.setValidationQuery(value);
}
value = properties.getProperty(PROP_VALIDATIONQUERY_TIMEOUT);
if (value != null) {
poolProperties.setValidationQueryTimeout(Integer.parseInt(value));
}
value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME);
if (value != null) {
poolProperties.setValidatorClassName(value);
}
value = properties.getProperty(PROP_VALIDATIONINTERVAL);
if (value != null) {
poolProperties.setValidationInterval(Long.parseLong(value));
}
value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);
if (value != null) {
poolProperties.setAccessToUnderlyingConnectionAllowed(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_REMOVEABANDONED);
if (value != null) {
poolProperties.setRemoveAbandoned(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_REMOVEABANDONEDTIMEOUT);
if (value != null) {
poolProperties.setRemoveAbandonedTimeout(Integer.parseInt(value));
}
value = properties.getProperty(PROP_LOGABANDONED);
if (value != null) {
poolProperties.setLogAbandoned(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS);
if (value != null) {
log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");
}
value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS);
if (value != null) {
log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");
}
value = properties.getProperty(PROP_CONNECTIONPROPERTIES);
if (value != null) {
Properties p = getProperties(value);
poolProperties.setDbProperties(p);
} else {
poolProperties.setDbProperties(new Properties());
}
if (poolProperties.getUsername()!=null) {
poolProperties.getDbProperties().setProperty("user",poolProperties.getUsername());
}
if (poolProperties.getPassword()!=null) {
poolProperties.getDbProperties().setProperty("password",poolProperties.getPassword());
}
value = properties.getProperty(PROP_INITSQL);
if (value != null) {
poolProperties.setInitSQL(value);
}
value = properties.getProperty(PROP_INTERCEPTORS);
if (value != null) {
poolProperties.setJdbcInterceptors(value);
}
value = properties.getProperty(PROP_JMX_ENABLED);
if (value != null) {
poolProperties.setJmxEnabled(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_FAIR_QUEUE);
if (value != null) {
poolProperties.setFairQueue(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_USE_EQUALS);
if (value != null) {
poolProperties.setUseEquals(Boolean.parseBoolean(value));
}
value = properties.getProperty(OBJECT_NAME);
if (value != null) {
poolProperties.setName(ObjectName.quote(value));
}
value = properties.getProperty(PROP_ABANDONWHENPERCENTAGEFULL);
if (value != null) {
poolProperties.setAbandonWhenPercentageFull(Integer.parseInt(value));
}
value = properties.getProperty(PROP_MAXAGE);
if (value != null) {
poolProperties.setMaxAge(Long.parseLong(value));
}
value = properties.getProperty(PROP_USE_CON_LOCK);
if (value != null) {
poolProperties.setUseLock(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_DATASOURCE);
if (value != null) {
//this should never happen
throw new IllegalArgumentException("Can't set dataSource property as a string, this must be a javax.sql.DataSource object.");
}
value = properties.getProperty(PROP_DATASOURCE_JNDI);
if (value != null) {
poolProperties.setDataSourceJNDI(value);
}
value = properties.getProperty(PROP_SUSPECT_TIMEOUT);
if (value != null) {
poolProperties.setSuspectTimeout(Integer.parseInt(value));
}
value = properties.getProperty(PROP_ALTERNATE_USERNAME_ALLOWED);
if (value != null) {
poolProperties.setAlternateUsernameAllowed(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_COMMITONRETURN);
if (value != null) {
poolProperties.setCommitOnReturn(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_ROLLBACKONRETURN);
if (value != null) {
poolProperties.setRollbackOnReturn(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_USEDISPOSABLECONNECTIONFACADE);
if (value != null) {
poolProperties.setUseDisposableConnectionFacade(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_LOGVALIDATIONERRORS);
if (value != null) {
poolProperties.setLogValidationErrors(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_PROPAGATEINTERRUPTSTATE);
if (value != null) {
poolProperties.setPropagateInterruptState(Boolean.parseBoolean(value));
}
value = properties.getProperty(PROP_IGNOREEXCEPTIONONPRELOAD);
if (value != null) {
poolProperties.setIgnoreExceptionOnPreLoad(Boolean.parseBoolean(value));
}
return poolProperties;
}
/**
* Creates and configures a {@link DataSource} instance based on the
* given properties.
*
* @param properties the datasource configuration properties
* @return the datasource
* @throws Exception if an error occurs creating the data source
*/
public DataSource createDataSource(Properties properties) throws Exception {
return createDataSource(properties,null,false);
}
public DataSource createDataSource(Properties properties,Context context, boolean XA) throws Exception {
PoolConfiguration poolProperties = DataSourceFactory.parsePoolProperties(properties);
if (poolProperties.getDataSourceJNDI()!=null && poolProperties.getDataSource()==null) {
performJNDILookup(context, poolProperties);
}
org.apache.tomcat.jdbc.pool.DataSource dataSource = XA?
new org.apache.tomcat.jdbc.pool.XADataSource(poolProperties) :
new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
//initialise the pool itself
dataSource.createPool();
// Return the configured DataSource instance
return dataSource;
}
public void performJNDILookup(Context context, PoolConfiguration poolProperties) {
Object jndiDS = null;
try {
if (context!=null) {
jndiDS = context.lookup(poolProperties.getDataSourceJNDI());
} else {
log.warn("dataSourceJNDI property is configured, but local JNDI context is null.");
}
} catch (NamingException e) {
log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" cannot be found in the local context.");
}
if (jndiDS==null) {
try {
context = new InitialContext();
jndiDS = context.lookup(poolProperties.getDataSourceJNDI());
} catch (NamingException e) {
log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" cannot be found in the InitialContext.");
}
}
if (jndiDS!=null) {
poolProperties.setDataSource(jndiDS);
}
}
/**
* Parse properties from the string. Format of the string must be [propertyName=property;]*.
* @param propText The properties string
* @return the properties
*/
protected static Properties getProperties(String propText) {
return PoolProperties.getProperties(propText,null);
}
}