Skip to content

Commit fc33641

Browse files
committed
refactor: (ported from 0.2.32) allow custom jdbc drivers and custom properties for mysql connection
1 parent 995639f commit fc33641

File tree

2 files changed

+101
-15
lines changed

2 files changed

+101
-15
lines changed

plugin/common/src/main/java/org/screamingsandals/bedwars/config/MainConfig.java

+27-3
Original file line numberDiff line numberDiff line change
@@ -561,9 +561,33 @@ public void load() {
561561
.key("user").defValue("root")
562562
.key("password").defValue("secret")
563563
.key("table-prefix").defValue("bw_")
564-
.key("useSSL").defValue(false)
565-
.key("add-timezone-to-connection-string").defValue(true)
566-
.key("timezone-id").defValue(TimeZone.getDefault().getID())
564+
.key("type").defValue("mysql")
565+
.key("driver").defValue("default")
566+
.key("params").defValue(() -> {
567+
var map = new HashMap<String, Object>();
568+
map.put("useSSL", configurationNode.node("database", "useSSL").getBoolean(true));
569+
if (configurationNode.node("database", "add-timezone-to-connection-string").getBoolean(true)) {
570+
map.put("serverTimezone", configurationNode.node("database", "timezone-id").getString(TimeZone.getDefault().getID()));
571+
}
572+
map.put("autoReconnect", true);
573+
map.put("cachePrepStmts", true);
574+
map.put("prepStmtCacheSize", 250);
575+
map.put("prepStmtCacheSqlLimit", 2048);
576+
577+
if (!configurationNode.node("database", "useSSL").virtual()) {
578+
configurationNode.node("database").removeChild("useSSL");
579+
}
580+
581+
if (!configurationNode.node("database", "add-timezone-to-connection-string").virtual()) {
582+
configurationNode.node("database").removeChild("add-timezone-to-connection-string");
583+
}
584+
585+
if (!configurationNode.node("database", "timezone-id").virtual()) {
586+
configurationNode.node("database").removeChild("timezone-id");
587+
}
588+
589+
return map;
590+
})
567591
.back()
568592
.section("bossbar")
569593
.key("use-xp-bar").defValue(false)

plugin/common/src/main/java/org/screamingsandals/bedwars/database/DatabaseManager.java

+74-12
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,25 @@
2626
import org.screamingsandals.lib.plugin.ServiceManager;
2727
import org.screamingsandals.lib.utils.annotations.Service;
2828
import org.screamingsandals.lib.utils.annotations.methods.OnEnable;
29+
import org.screamingsandals.lib.utils.annotations.parameters.DataFolder;
30+
import org.spongepowered.configurate.ConfigurationNode;
2931

32+
import java.io.BufferedReader;
33+
import java.io.IOException;
34+
import java.io.InputStreamReader;
35+
import java.net.URL;
36+
import java.net.URLClassLoader;
37+
import java.nio.file.Path;
3038
import java.sql.Connection;
39+
import java.sql.DriverManager;
3140
import java.sql.SQLException;
32-
import java.util.TimeZone;
3341

3442
@Service
3543
@RequiredArgsConstructor
3644
public class DatabaseManager {
3745
private final MainConfig mainConfig;
46+
@DataFolder
47+
private final Path dataFolder;
3848

3949
private String tablePrefix;
4050
private String database;
@@ -43,9 +53,9 @@ public class DatabaseManager {
4353
private String password;
4454
private int port;
4555
private String user;
46-
private boolean useSSL;
47-
private boolean addTimezone;
48-
private String timezoneID;
56+
private ConfigurationNode params;
57+
private String type;
58+
private String driver;
4959

5060
public static DatabaseManager getInstance() {
5161
return ServiceManager.get(DatabaseManager.class);
@@ -59,22 +69,74 @@ public void onEnable() {
5969
this.password = mainConfig.node("database", "password").getString();
6070
this.database = mainConfig.node("database", "db").getString();
6171
this.tablePrefix = mainConfig.node("database", "table-prefix").getString();
62-
this.useSSL = mainConfig.node("database", "useSSL").getBoolean();
63-
this.addTimezone = mainConfig.node("database", "add-timezone-to-connection-string").getBoolean();
64-
this.timezoneID = mainConfig.node("database", "timezone-id").getString();
72+
this.params = mainConfig.node("database", "params");
73+
this.type = mainConfig.node("database", "type").getString();
74+
this.driver = mainConfig.node("database", "driver").getString();
6575
}
6676

6777
public void initialize() {
6878
var config = new HikariConfig();
69-
config.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database
70-
+ "?autoReconnect=true" + (addTimezone && timezoneID != null ? "&serverTimezone=" + timezoneID : "") + "&useSSL=" + useSSL);
79+
config.setJdbcUrl("jdbc:" + this.type + "://" + this.host + ":" + this.port + "/" + this.database);
7180
config.setUsername(this.user);
7281
config.setPassword(this.password);
73-
config.addDataSourceProperty("cachePrepStmts", "true");
74-
config.addDataSourceProperty("prepStmtCacheSize", "250");
75-
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
82+
83+
params.childrenMap().forEach((key, node) -> {
84+
config.addDataSourceProperty(key.toString(), node.getString());
85+
});
86+
87+
ClassLoader contextCl = null;
88+
Class<?> driverClazz = null;
89+
90+
if (driver != null && !"default".equalsIgnoreCase(driver)) {
91+
try {
92+
var cl = new URLClassLoader(new URL[] {dataFolder.resolve(driver).toAbsolutePath().toUri().toURL()}, ClassLoader.getSystemClassLoader().getParent());
93+
try (var is = cl.getResourceAsStream("META-INF/services/java.sql.Driver")) {
94+
if (is == null) {
95+
throw new RuntimeException("Database driver JAR does not contain JDBC 4 compatible driver");
96+
}
97+
String driverClassName = null;
98+
try (var isr = new InputStreamReader(is);
99+
var reader = new BufferedReader(isr)) {
100+
do {
101+
driverClassName = reader.readLine();
102+
if (driverClassName != null) {
103+
// All characters after '#' should be ignored, whitespaces around the qualified name are also ignored
104+
driverClassName = driver.split("#", 2)[0].trim();
105+
}
106+
} while (driverClassName != null && driverClassName.isEmpty());
107+
}
108+
if (driverClassName == null) {
109+
throw new RuntimeException("Database driver JAR does not contain JDBC 4 compatible driver");
110+
}
111+
driverClazz = cl.loadClass(driverClassName);
112+
contextCl = Thread.currentThread().getContextClassLoader();
113+
Thread.currentThread().setContextClassLoader(cl);
114+
config.setDriverClassName(driverClassName);
115+
}
116+
} catch (IOException | ClassNotFoundException e) {
117+
throw new RuntimeException(e);
118+
}
119+
}
76120

77121
this.dataSource = new HikariDataSource(config);
122+
123+
if (contextCl != null) {
124+
Thread.currentThread().setContextClassLoader(contextCl);
125+
}
126+
127+
if (driverClazz != null) {
128+
var drivers = DriverManager.getDrivers();
129+
while (drivers.hasMoreElements()) {
130+
var driver = drivers.nextElement();
131+
if (driver.getClass().equals(driverClazz)) {
132+
try {
133+
DriverManager.deregisterDriver(driver);
134+
} catch (SQLException e) {
135+
// ignore
136+
}
137+
}
138+
}
139+
}
78140
}
79141

80142
public Connection getConnection() {

0 commit comments

Comments
 (0)