/*
* Copyright (c) 2011-2015 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.ext.jdbc.spi.impl;
import com.jolbox.bonecp.BoneCPConfig;
import com.jolbox.bonecp.BoneCPDataSource;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.vertx.ext.jdbc.spi.DataSourceProvider;
import javax.sql.DataSource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.Map;
/**
* @author <a href="mailto:plopes@redhat.com">Paulo Lopes</a>
*/
public class BoneCPDataSourceProvider implements DataSourceProvider {
private static final Logger log = LoggerFactory.getLogger(BoneCPDataSourceProvider.class);
/**
* Since BoneCP has way to many knobs and due to the fact that this method is called only
* once per client instance it inspects the config object using reflection.
*/
private static void mergeConfig(BoneCPConfig config, JsonObject json) {
for (Map.Entry<String, Object> entry : json) {
String name = entry.getKey();
if ("provider_class".equals(name)) {
continue;
}
String mName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
try {
Method method = BoneCPConfig.class.getMethod(mName, entry.getValue().getClass());
method.invoke(config, entry.getValue());
} catch (NoSuchMethodException e) {
// ignore, means that the config object does not have this property
log.warn("no such property: " + name);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
private ClassLoader getClassLoader() {
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
return tccl == null ? getClass().getClassLoader() : tccl;
}
@Override
public DataSource getDataSource(JsonObject config) throws SQLException {
BoneCPConfig boneCPConfig = new BoneCPConfig();
mergeConfig(boneCPConfig, config);
// we now need to change the default class loader mostly for the cases where
// we do not use fat jars. In that case other connection pools will fail
// loading the drivers
boneCPConfig.setClassLoader(getClassLoader());
return new BoneCPDataSource(boneCPConfig);
}
@Override
public int maximumPoolSize(DataSource dataSource, JsonObject config) {
if (dataSource instanceof BoneCPDataSource) {
BoneCPConfig cfg = ((BoneCPDataSource) dataSource).getPool().getConfig();
return cfg.getMaxConnectionsPerPartition() * cfg.getPartitionCount();
}
return -1;
}
@Override
public void close(DataSource dataSource) throws SQLException {
if (dataSource instanceof BoneCPDataSource) {
((BoneCPDataSource) dataSource).close();
}
}
}