diff --git a/build.gradle.kts b/build.gradle.kts index a43ff662b..f3adb5846 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -66,19 +66,27 @@ dependencies { implementation(libs.xseries) implementation(libs.adventure.platform.bukkit) implementation(libs.triumph.gui) - implementation(libs.hikaricp) - implementation(libs.jdbi.core) - implementation(libs.jdbi.sqlobject) - implementation(libs.mariadb.client) implementation(libs.quark.bukkit) /* - * Kotlin is compiled against locally, but downloaded and loaded at runtime - * by Quark to reduce the SpigotMC upload jar size. + * Large runtime libraries are compiled against locally, but downloaded and loaded + * by Quark to keep the file size slim. */ compileOnly(libs.kotlin.stdlib) quark(libs.kotlin.stdlib) + compileOnly(libs.hikaricp) + quark(libs.hikaricp) + + compileOnly(libs.jdbi.core) + quark(libs.jdbi.core) + + compileOnly(libs.jdbi.sqlobject) + quark(libs.jdbi.sqlobject) + + compileOnly(libs.mariadb.client) + quark(libs.mariadb.client) + /* * Provided by the server or by other plugins at runtime. * These must not be bundled or relocated. @@ -284,20 +292,7 @@ tasks.named("shadowJar") { } /* - * Database stack - */ - relocate("com.zaxxer.hikari", "$relocationRoot.hikari") { - skipStringConstants = true - } - relocate("org.jdbi", "$relocationRoot.jdbi") { - skipStringConstants = true - } - relocate("org.mariadb.jdbc", "$relocationRoot.mariadb") { - skipStringConstants = true - } - - /* - * Common transitive libraries pulled by the database/config stack. + * Common transitive libraries pulled by shaded dependencies. * These are intentionally narrow to avoid relocating server/plugin APIs. */ relocate("org.antlr", "$relocationRoot.antlr") { @@ -376,10 +371,8 @@ fun RunServer.configureGuildsRunServer(target: MinecraftRunTarget) { downloadPlugins { /* * EssentialsX: - * Hangar marks this release as an external download, so run-task's - * Hangar downloader returns 404. Use GitHub Releases instead. */ - url("https://ci.ender.zone/job/EssentialsX/lastSuccessfulBuild/artifact/jars/EssentialsX-2.22.0-dev+112-5baf239.jar") + github("EssentialsX", "Essentials", "2.22.0", "EssentialsX-2.22.0.jar") /* * LuckPerms: diff --git a/src/main/java/me/glaremasters/guilds/database/DatabaseManager.java b/src/main/java/me/glaremasters/guilds/database/DatabaseManager.java index 09324915b..bc6815f7f 100644 --- a/src/main/java/me/glaremasters/guilds/database/DatabaseManager.java +++ b/src/main/java/me/glaremasters/guilds/database/DatabaseManager.java @@ -59,7 +59,7 @@ public DatabaseManager(SettingsManager settingsManager, DatabaseBackend backend) switch (backend) { case MYSQL: config.setPoolName("Guilds MySQL Connection Pool"); - config.setDataSourceClassName(requireDataSourceName( + config.setDataSourceClassName(requireDataSourceClassName( backend, "com.mysql.cj.jdbc.MysqlDataSource", "com.mysql.jdbc.jdbc2.optional.MysqlDataSource" @@ -77,11 +77,12 @@ public DatabaseManager(SettingsManager settingsManager, DatabaseBackend backend) break; case SQLITE: config.setPoolName("Guilds SQLite Connection Pool"); + config.setDriverClassName(requireDriverClassName(backend, "org.sqlite.JDBC")); config.setJdbcUrl("jdbc:sqlite:plugins/Guilds/guilds.db"); break; case MARIADB: config.setPoolName("Guilds MariaDB Connection Pool"); - config.setDataSourceClassName(requireDataSourceName( + config.setDataSourceClassName(requireDataSourceClassName( backend, "org.mariadb.jdbc.MariaDbDataSource" )); @@ -130,7 +131,15 @@ public HikariDataSource getHikari() { return hikari; } - private static String requireDataSourceName(DatabaseBackend backend, String... classNames) throws IOException { + private static String requireDataSourceClassName(DatabaseBackend backend, String... classNames) throws IOException { + return requireClassName("datasource", backend, classNames); + } + + private static String requireDriverClassName(DatabaseBackend backend, String... classNames) throws IOException { + return requireClassName("driver", backend, classNames); + } + + private static String requireClassName(String classType, DatabaseBackend backend, String... classNames) throws IOException { for (String className : classNames) { if (isClassAvailable(className)) { return className; @@ -138,14 +147,25 @@ private static String requireDataSourceName(DatabaseBackend backend, String... c } throw new IOException( - "No datasource class is available for the " + backend.getBackendName() + - " backend. Tried: " + Arrays.toString(classNames) + "No " + classType + " class is available for the " + backend.getBackendName() + + " backend. Tried: " + Arrays.toString(classNames) + + ". Ensure the selected backend's JDBC driver is available to the server/plugin runtime." ); } private static boolean isClassAvailable(String className) { + return isClassAvailable(className, DatabaseManager.class.getClassLoader()) || + isClassAvailable(className, Thread.currentThread().getContextClassLoader()) || + isClassAvailable(className, ClassLoader.getSystemClassLoader()); + } + + private static boolean isClassAvailable(String className, ClassLoader classLoader) { + if (classLoader == null) { + return false; + } + try { - Class.forName(className); + Class.forName(className, false, classLoader); return true; } catch (ClassNotFoundException ignored) { return false; @@ -158,7 +178,8 @@ private static String getConnectionDetails( HikariConfig config ) { if (backend == DatabaseBackend.SQLITE) { - return "jdbcUrl=" + config.getJdbcUrl(); + return "jdbcUrl=" + config.getJdbcUrl() + + ", driver=" + config.getDriverClassName(); } return "host=" + settingsManager.getProperty(StorageSettings.SQL_HOST) +