package org.rakam.analysis; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.rakam.config.JDBCConfig; import javax.sql.DataSource; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; import static com.google.common.base.Preconditions.checkArgument; public class JDBCPoolDataSource implements DataSource { private static final Map<JDBCConfig, JDBCPoolDataSource> pools = new ConcurrentHashMap<>(); private final HikariDataSource dataSource; private final JDBCConfig config; private final boolean disablePool; private JDBCPoolDataSource(JDBCConfig config, Optional<String> initialQuery) { this.config = config; this.disablePool = config.getConnectionDisablePool(); checkArgument(config.getUrl() != null, "JDBC url is required"); HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setUsername(config.getUsername()); hikariConfig.setPassword(config.getPassword()); hikariConfig.setJdbcUrl(config.getUrl()); if (config.getConnectionIdleTimeout() != null) { hikariConfig.setIdleTimeout(config.getConnectionIdleTimeout()); } if (config.getMaxConnection() != null) { hikariConfig.setMaximumPoolSize(config.getMaxConnection()); } else { hikariConfig.setMaximumPoolSize(30); } hikariConfig.setAutoCommit(true); hikariConfig.setPoolName(config.toString()); if (initialQuery.isPresent()) { hikariConfig.setConnectionInitSql(initialQuery.get()); } dataSource = new HikariDataSource(hikariConfig); } public static JDBCPoolDataSource getOrCreateDataSource(JDBCConfig config, String initialQuery) { return pools.computeIfAbsent(config, key -> new JDBCPoolDataSource(config, Optional.of(initialQuery))); } public static JDBCPoolDataSource getOrCreateDataSource(JDBCConfig config) { return pools.computeIfAbsent(config, key -> new JDBCPoolDataSource(config, Optional.empty())); } @Override public Connection getConnection() throws SQLException { return getConnection(disablePool); } public Connection getConnection(boolean disablePool) throws SQLException { if (disablePool) { return DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword()); } return dataSource.getConnection(); } @Override public Connection getConnection(String username, String password) throws SQLException { return dataSource.getConnection(username, password); } @Override public PrintWriter getLogWriter() throws SQLException { return dataSource.getLogWriter(); } @Override public void setLogWriter(PrintWriter out) throws SQLException { dataSource.setLogWriter(out); } @Override public void setLoginTimeout(int seconds) throws SQLException { dataSource.setLoginTimeout(seconds); } @Override public int getLoginTimeout() throws SQLException { return dataSource.getLoginTimeout(); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return dataSource.getParentLogger(); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { return dataSource.unwrap(iface); } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return dataSource.isWrapperFor(iface); } public JDBCConfig getConfig() { return config; } }