package org.apache.commons.dbcp2.datasources;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import org.apache.commons.dbcp2.ListException;
abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
private static final Map<String, InstanceKeyDataSource> instanceMap = new ConcurrentHashMap<>();
static synchronized String registerNewInstance(final InstanceKeyDataSource ds) {
int max = 0;
final Iterator<String> iterator = instanceMap.keySet().iterator();
while (iterator.hasNext()) {
final String s = iterator.next();
if (s != null) {
try {
max = Math.max(max, Integer.parseInt(s));
} catch (final NumberFormatException e) {
}
}
}
final String instanceKey = String.valueOf(max + 1);
instanceMap.put(instanceKey, ds);
return instanceKey;
}
static void removeInstance(final String key) {
if (key != null) {
instanceMap.remove(key);
}
}
public static void closeAll() throws Exception {
final List<Throwable> exceptionList = new ArrayList<>(instanceMap.size());
final Iterator<Entry<String, InstanceKeyDataSource>> instanceIterator = instanceMap.entrySet().iterator();
while (instanceIterator.hasNext()) {
final Entry<String, InstanceKeyDataSource> next = instanceIterator.next();
if (next != null) {
@SuppressWarnings("resource")
final InstanceKeyDataSource value = next.getValue();
if (value != null) {
try {
value.close();
} catch (final Exception e) {
exceptionList.add(e);
}
}
}
}
instanceMap.clear();
if (!exceptionList.isEmpty()) {
throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList);
}
}
@Override
public Object getObjectInstance(final Object refObj, final Name name, final Context context,
final Hashtable<?, ?> env) throws IOException, ClassNotFoundException {
Object obj = null;
if (refObj instanceof Reference) {
final Reference ref = (Reference) refObj;
if (isCorrectClass(ref.getClassName())) {
final RefAddr refAddr = ref.get("instanceKey");
if (refAddr != null && refAddr.getContent() != null) {
obj = instanceMap.get(refAddr.getContent());
} else {
String key = null;
if (name != null) {
key = name.toString();
obj = instanceMap.get(key);
}
if (obj == null) {
final InstanceKeyDataSource ds = getNewInstance(ref);
setCommonProperties(ref, ds);
obj = ds;
if (key != null) {
instanceMap.put(key, ds);
}
}
}
}
}
return obj;
}
private void setCommonProperties(final Reference ref, final InstanceKeyDataSource ikds)
throws IOException, ClassNotFoundException {
RefAddr refAddr = ref.get("dataSourceName");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDataSourceName(refAddr.getContent().toString());
}
refAddr = ref.get("description");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDescription(refAddr.getContent().toString());
}
refAddr = ref.get("jndiEnvironment");
if (refAddr != null && refAddr.getContent() != null) {
final byte[] serialized = (byte[]) refAddr.getContent();
ikds.setJndiEnvironment((Properties) deserialize(serialized));
}
refAddr = ref.get("loginTimeout");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setLoginTimeout(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("blockWhenExhausted");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultBlockWhenExhausted(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("evictionPolicyClassName");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultEvictionPolicyClassName(refAddr.getContent().toString());
}
refAddr = ref.get("lifo");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultLifo(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("maxIdlePerKey");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultMaxIdle(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("maxTotalPerKey");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultMaxTotal(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("maxWaitMillis");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultMaxWaitMillis(Long.parseLong(refAddr.getContent().toString()));
}
refAddr = ref.get("minEvictableIdleTimeMillis");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultMinEvictableIdleTimeMillis(Long.parseLong(refAddr.getContent().toString()));
}
refAddr = ref.get("minIdlePerKey");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultMinIdle(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("numTestsPerEvictionRun");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultNumTestsPerEvictionRun(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("softMinEvictableIdleTimeMillis");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultSoftMinEvictableIdleTimeMillis(Long.parseLong(refAddr.getContent().toString()));
}
refAddr = ref.get("testOnCreate");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultTestOnCreate(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("testOnBorrow");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultTestOnBorrow(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("testOnReturn");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultTestOnReturn(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("testWhileIdle");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultTestWhileIdle(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("timeBetweenEvictionRunsMillis");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultTimeBetweenEvictionRunsMillis(Long.parseLong(refAddr.getContent().toString()));
}
refAddr = ref.get("validationQuery");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setValidationQuery(refAddr.getContent().toString());
}
refAddr = ref.get("validationQueryTimeout");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setValidationQueryTimeout(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("rollbackAfterValidation");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setRollbackAfterValidation(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
}
refAddr = ref.get("maxConnLifetimeMillis");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setMaxConnLifetimeMillis(Long.parseLong(refAddr.getContent().toString()));
}
refAddr = ref.get("defaultAutoCommit");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultAutoCommit(Boolean.valueOf(refAddr.getContent().toString()));
}
refAddr = ref.get("defaultTransactionIsolation");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultTransactionIsolation(Integer.parseInt(refAddr.getContent().toString()));
}
refAddr = ref.get("defaultReadOnly");
if (refAddr != null && refAddr.getContent() != null) {
ikds.setDefaultReadOnly(Boolean.valueOf(refAddr.getContent().toString()));
}
}
protected abstract boolean isCorrectClass(String className);
protected abstract InstanceKeyDataSource getNewInstance(Reference ref) throws IOException, ClassNotFoundException;
protected static final Object deserialize(final byte[] data) throws IOException, ClassNotFoundException {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new ByteArrayInputStream(data));
return in.readObject();
} finally {
if (in != null) {
try {
in.close();
} catch (final IOException ex) {
}
}
}
}
}