package launchserver.auth; import org.postgresql.ds.PGSimpleDataSource; import com.zaxxer.hikari.HikariDataSource; import launcher.LauncherAPI; import launcher.helper.LogHelper; import launcher.helper.VerifyHelper; import launcher.serialize.config.ConfigObject; import launcher.serialize.config.entry.BlockConfigEntry; import launcher.serialize.config.entry.IntegerConfigEntry; import launcher.serialize.config.entry.StringConfigEntry; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; public final class PostgreSQLSourceConfig extends ConfigObject implements AutoCloseable, SQLSourceConfig { @LauncherAPI public static final int TIMEOUT = VerifyHelper.verifyInt( Integer.parseInt(System.getProperty("launcher.postgresql.idleTimeout", Integer.toString(5000))), VerifyHelper.POSITIVE, "launcher.postgresql.idleTimeout can't be <= 5000"); private static final int MAX_POOL_SIZE = VerifyHelper.verifyInt( Integer.parseInt(System.getProperty("launcher.postgresql.maxPoolSize", Integer.toString(3))), VerifyHelper.POSITIVE, "launcher.postgresql.maxPoolSize can't be <= 0"); // Instance private final String poolName; // Config private final String address; private final int port; private final String username; private final String password; private final String database; // Cache private DataSource source; private boolean hikari; @LauncherAPI public PostgreSQLSourceConfig(String poolName, BlockConfigEntry block) { super(block); this.poolName = poolName; address = VerifyHelper.verify(block.getEntryValue("address", StringConfigEntry.class), VerifyHelper.NOT_EMPTY, "PostgreSQL address can't be empty"); port = VerifyHelper.verifyInt(block.getEntryValue("port", IntegerConfigEntry.class), VerifyHelper.range(0, 65535), "Illegal PostgreSQL port"); username = VerifyHelper.verify(block.getEntryValue("username", StringConfigEntry.class), VerifyHelper.NOT_EMPTY, "PostgreSQL username can't be empty"); password = block.getEntryValue("password", StringConfigEntry.class); database = VerifyHelper.verify(block.getEntryValue("database", StringConfigEntry.class), VerifyHelper.NOT_EMPTY, "PostgreSQL database can't be empty"); // Password shouldn't be verified } @Override public synchronized void close() { if (hikari) { // Shutdown hikari pool ((HikariDataSource) source).close(); } } @LauncherAPI @SuppressWarnings("deprecation") // Временный фикс Warnings public synchronized Connection getConnection() throws SQLException { if (source == null) { // New data source PGSimpleDataSource postgresqlSource = new PGSimpleDataSource(); // Set credentials postgresqlSource.setServerName(address); postgresqlSource.setPortNumber(port); // TODO: Нужно переделать под несколько серверов: //postgresqlSource.setServerNames(address); //postgresqlSource.setPortNumbers(port); postgresqlSource.setUser(username); postgresqlSource.setPassword(password); postgresqlSource.setDatabaseName(database); // Try using HikariCP source = postgresqlSource; try { Class.forName("com.zaxxer.hikari.HikariDataSource"); hikari = true; // Used for shutdown. Not instanceof because of possible classpath error // Set HikariCP pool HikariDataSource hikariSource = new HikariDataSource(); hikariSource.setDataSource(source); // Set pool settings hikariSource.setPoolName(poolName); hikariSource.setMinimumIdle(0); hikariSource.setMaximumPoolSize(MAX_POOL_SIZE); hikariSource.setIdleTimeout(TIMEOUT * 1000L); // Replace source with hds source = hikariSource; LogHelper.info("HikariCP pooling enabled for '%s'", poolName); } catch (ClassNotFoundException ignored) { LogHelper.warning("HikariCP isn't in classpath for '%s'", poolName); } } return source.getConnection(); } }