26
26
import org .screamingsandals .lib .plugin .ServiceManager ;
27
27
import org .screamingsandals .lib .utils .annotations .Service ;
28
28
import org .screamingsandals .lib .utils .annotations .methods .OnEnable ;
29
+ import org .screamingsandals .lib .utils .annotations .parameters .DataFolder ;
30
+ import org .spongepowered .configurate .ConfigurationNode ;
29
31
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 ;
30
38
import java .sql .Connection ;
39
+ import java .sql .DriverManager ;
31
40
import java .sql .SQLException ;
32
- import java .util .TimeZone ;
33
41
34
42
@ Service
35
43
@ RequiredArgsConstructor
36
44
public class DatabaseManager {
37
45
private final MainConfig mainConfig ;
46
+ @ DataFolder
47
+ private final Path dataFolder ;
38
48
39
49
private String tablePrefix ;
40
50
private String database ;
@@ -43,9 +53,9 @@ public class DatabaseManager {
43
53
private String password ;
44
54
private int port ;
45
55
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 ;
49
59
50
60
public static DatabaseManager getInstance () {
51
61
return ServiceManager .get (DatabaseManager .class );
@@ -59,22 +69,74 @@ public void onEnable() {
59
69
this .password = mainConfig .node ("database" , "password" ).getString ();
60
70
this .database = mainConfig .node ("database" , "db" ).getString ();
61
71
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 ();
65
75
}
66
76
67
77
public void initialize () {
68
78
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 );
71
80
config .setUsername (this .user );
72
81
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
+ }
76
120
77
121
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
+ }
78
140
}
79
141
80
142
public Connection getConnection () {
0 commit comments