diff --git a/common/src/main/java/me/lucko/luckperms/common/dependencies/Dependency.java b/common/src/main/java/me/lucko/luckperms/common/dependencies/Dependency.java index 321cabc1b..3cd56d50e 100644 --- a/common/src/main/java/me/lucko/luckperms/common/dependencies/Dependency.java +++ b/common/src/main/java/me/lucko/luckperms/common/dependencies/Dependency.java @@ -141,15 +141,15 @@ public enum Dependency { MARIADB_DRIVER( "org{}mariadb{}jdbc", "mariadb-java-client", - "2.6.0", - "fgiCp29Z7X38ULAJNsxZ1wFIVT2u3trSx/VCMxTlA6g=", + "2.7.0", + "ABURDun85Q01kf119r4yjDtl5ju9Fg9uV2nXyU3SEdw=", Relocation.of("mariadb", "org{}mariadb{}jdbc") ), MYSQL_DRIVER( "mysql", "mysql-connector-java", - "5.1.48", - "VuJsqqOCH1rkr0T5x09mz4uE6gFRatOAPLsOkEm27Kg=", + "8.0.22", + "UBne+9EjFilel6bojyqbB/EYNFpOmCcQu6Iy5JmyL08=", Relocation.of("mysql", "com{}mysql") ), POSTGRESQL_DRIVER( diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/HikariConnectionFactory.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/HikariConnectionFactory.java index d561b7d80..df9f64c62 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/HikariConnectionFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/HikariConnectionFactory.java @@ -47,37 +47,46 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +/** + * Abstract {@link ConnectionFactory} using a {@link HikariDataSource}. + */ public abstract class HikariConnectionFactory implements ConnectionFactory { - - protected final StorageCredentials configuration; + private final StorageCredentials configuration; private HikariDataSource hikari; public HikariConnectionFactory(StorageCredentials configuration) { this.configuration = configuration; } - protected String getDriverClass() { - return null; - } + /** + * Gets the default port used by the database + * + * @return the default port + */ + protected abstract String defaultPort(); - protected void appendProperties(HikariConfig config, Map properties) { - for (Map.Entry property : properties.entrySet()) { - config.addDataSourceProperty(property.getKey(), property.getValue()); - } - } + /** + * Configures the {@link HikariConfig} with the relevant database properties. + * + *

Each driver does this slightly differently...

+ * + * @param config the hikari config + * @param address the database address + * @param port the database port + * @param databaseName the database name + * @param username the database username + * @param password the database password + */ + protected abstract void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password); - protected void appendConfigurationInfo(HikariConfig config) { - String address = this.configuration.getAddress(); - String[] addressSplit = address.split(":"); - address = addressSplit[0]; - String port = addressSplit.length > 1 ? addressSplit[1] : "3306"; - - config.setDataSourceClassName(getDriverClass()); - config.addDataSourceProperty("serverName", address); - config.addDataSourceProperty("port", port); - config.addDataSourceProperty("databaseName", this.configuration.getDatabase()); - config.setUsername(this.configuration.getUsername()); - config.setPassword(this.configuration.getPassword()); + /** + * Allows the connection factory instance to override certain properties before they are set. + * + * @param properties the current properties + */ + protected void overrideProperties(Map properties) { + // https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery + properties.putIfAbsent("socketTimeout", String.valueOf(TimeUnit.SECONDS.toMillis(30))); } @Override @@ -92,17 +101,29 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { throw e; } + // set pool name so the logging output can be linked back to us config.setPoolName("luckperms-hikari"); - appendConfigurationInfo(config); + // get the database info/credentials from the config file + String[] addressSplit = this.configuration.getAddress().split(":"); + String address = addressSplit[0]; + String port = addressSplit.length > 1 ? addressSplit[1] : defaultPort(); + // allow the implementation to configure the HikariConfig appropriately with these values + configureDatabase(config, address, port, this.configuration.getDatabase(), this.configuration.getUsername(), this.configuration.getPassword()); + + // get the extra connection properties from the config Map properties = new HashMap<>(this.configuration.getProperties()); - // https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery - properties.putIfAbsent("socketTimeout", String.valueOf(TimeUnit.SECONDS.toMillis(30))); + // allow the implementation to override/make changes to these properties + overrideProperties(properties); - appendProperties(config, properties); + // set the properties + for (Map.Entry property : properties.entrySet()) { + config.addDataSourceProperty(property.getKey(), property.getValue()); + } + // configure the connection pool config.setMaximumPoolSize(this.configuration.getMaxPoolSize()); config.setMinimumIdle(this.configuration.getMinIdleConnections()); config.setMaxLifetime(this.configuration.getMaxLifetime()); @@ -122,6 +143,20 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { } } + @Override + public Connection getConnection() throws SQLException { + if (this.hikari == null) { + throw new SQLException("Unable to get a connection from the pool. (hikari is null)"); + } + + Connection connection = this.hikari.getConnection(); + if (connection == null) { + throw new SQLException("Unable to get a connection from the pool. (getConnection returned null)"); + } + + return connection; + } + @Override public Map getMeta() { Map meta = new LinkedHashMap<>(); @@ -135,9 +170,9 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { } catch (SQLException e) { success = false; } - long duration = System.currentTimeMillis() - start; if (success) { + long duration = System.currentTimeMillis() - start; meta.put( Component.translatable("luckperms.command.info.storage.meta.ping-key"), Component.text(duration + "ms", NamedTextColor.GREEN) @@ -151,18 +186,6 @@ public abstract class HikariConnectionFactory implements ConnectionFactory { return meta; } - @Override - public Connection getConnection() throws SQLException { - if (this.hikari == null) { - throw new SQLException("Unable to get a connection from the pool. (hikari is null)"); - } - Connection connection = this.hikari.getConnection(); - if (connection == null) { - throw new SQLException("Unable to get a connection from the pool. (getConnection returned null)"); - } - return connection; - } - private static void handleLinkageError(LinkageError linkageError, LuckPermsPlugin plugin) { List noteworthyClasses = ImmutableList.of( "org.slf4j.LoggerFactory", diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MariaDbConnectionFactory.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MariaDbConnectionFactory.java index 2807d364a..be973352f 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MariaDbConnectionFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MariaDbConnectionFactory.java @@ -29,9 +29,7 @@ import com.zaxxer.hikari.HikariConfig; import me.lucko.luckperms.common.storage.misc.StorageCredentials; -import java.util.Map; import java.util.function.Function; -import java.util.stream.Collectors; public class MariaDbConnectionFactory extends HikariConnectionFactory { public MariaDbConnectionFactory(StorageCredentials configuration) { @@ -44,22 +42,20 @@ public class MariaDbConnectionFactory extends HikariConnectionFactory { } @Override - protected String getDriverClass() { - return "org.mariadb.jdbc.MariaDbDataSource"; + protected String defaultPort() { + return "3306"; } @Override - protected void appendProperties(HikariConfig config, Map properties) { - String propertiesString = properties.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(";")); - - // kinda hacky. this will call #setProperties on the datasource, which will append these options - // onto the connections. - config.addDataSourceProperty("properties", propertiesString); + protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) { + config.setDriverClassName("org.mariadb.jdbc.Driver"); + config.setJdbcUrl("jdbc:mariadb://" + address + ":" + port + "/" + databaseName); + config.setUsername(username); + config.setPassword(password); } @Override public Function getStatementProcessor() { return s -> s.replace("'", "`"); // use backticks for quotes } - } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MySqlConnectionFactory.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MySqlConnectionFactory.java index 5930ba39e..985070bf3 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MySqlConnectionFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/MySqlConnectionFactory.java @@ -43,12 +43,20 @@ public class MySqlConnectionFactory extends HikariConnectionFactory { } @Override - protected String getDriverClass() { - return "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"; + protected String defaultPort() { + return "3306"; } @Override - protected void appendProperties(HikariConfig config, Map properties) { + protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) { + config.setDriverClassName("com.mysql.cj.jdbc.Driver"); + config.setJdbcUrl("jdbc:mysql://" + address + ":" + port + "/" + databaseName); + config.setUsername(username); + config.setPassword(password); + } + + @Override + protected void overrideProperties(Map properties) { // https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration properties.putIfAbsent("cachePrepStmts", "true"); properties.putIfAbsent("prepStmtCacheSize", "250"); @@ -63,13 +71,11 @@ public class MySqlConnectionFactory extends HikariConnectionFactory { properties.putIfAbsent("alwaysSendSetIsolation", "false"); properties.putIfAbsent("cacheCallableStmts", "true"); - // append configurable properties - super.appendProperties(config, properties); + super.overrideProperties(properties); } @Override public Function getStatementProcessor() { return s -> s.replace("'", "`"); // use backticks for quotes } - } diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/PostgreConnectionFactory.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/PostgreConnectionFactory.java index 5249c350a..176df1823 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/PostgreConnectionFactory.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/sql/connection/hikari/PostgreConnectionFactory.java @@ -43,33 +43,29 @@ public class PostgreConnectionFactory extends HikariConnectionFactory { } @Override - protected void appendProperties(HikariConfig config, Map properties) { - // remove the default config properties which don't exist for PostgreSQL - properties.remove("useUnicode"); - properties.remove("characterEncoding"); - - super.appendProperties(config, properties); + protected String defaultPort() { + return "5432"; } @Override - protected void appendConfigurationInfo(HikariConfig config) { - String address = this.configuration.getAddress(); - String[] addressSplit = address.split(":"); - address = addressSplit[0]; - String port = addressSplit.length > 1 ? addressSplit[1] : "5432"; - - String database = this.configuration.getDatabase(); - String username = this.configuration.getUsername(); - String password = this.configuration.getPassword(); - + protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) { config.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource"); config.addDataSourceProperty("serverName", address); config.addDataSourceProperty("portNumber", port); - config.addDataSourceProperty("databaseName", database); + config.addDataSourceProperty("databaseName", databaseName); config.addDataSourceProperty("user", username); config.addDataSourceProperty("password", password); } + @Override + protected void overrideProperties(Map properties) { + super.overrideProperties(properties); + + // remove the default config properties which don't exist for PostgreSQL + properties.remove("useUnicode"); + properties.remove("characterEncoding"); + } + @Override public Function getStatementProcessor() { return s -> s.replace("'", "\"");