package javastory.db; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.logging.Level; import java.util.logging.Logger; import com.google.common.collect.Maps; import com.mysql.jdbc.Driver; public final class Database implements ConnectionPool { private static final Database instance = new Database(); private final ConcurrentLinkedQueue<Connection> connections; private final String url; private final String username; private final String password; private static final int POOLING_CAPACITY = 20; private Database() { try { DriverManager.registerDriver(new Driver()); } catch (final SQLException ex) { Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex); } this.connections = new ConcurrentLinkedQueue<>(); final Map<String, String> properties = this.loadDbProperties(); this.url = properties.get("url"); this.username = properties.get("username"); this.password = properties.get("password"); } private Map<String, String> loadDbProperties() { final String dbConfigFilename = System.getProperty("dbConfigFilename", "database.properties"); final Properties properties = new Properties(); try (InputStreamReader reader = new FileReader(dbConfigFilename)) { properties.load(reader); } catch (final IOException ex) { Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex); } return Maps.fromProperties(properties); } public static Connection getConnection() { return instance.getConnectionInternal(); } private synchronized Connection getConnectionInternal() { final Connection fromQueue = this.connections.poll(); if (fromQueue == null) { try { final Connection newConnection = DriverManager.getConnection(this.url, this.username, this.password); return new PooledConnection(newConnection, this); } catch (final SQLException exception) { Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, exception); return null; } } else { return fromQueue; } } @Override public synchronized void reclaim(final PooledConnection connection) throws SQLException { if (this.connections.size() >= POOLING_CAPACITY) { connection.getInnerConnection().close(); return; } this.connections.add(connection); } }