From 723c79b3a9f5a48727b8192f7ff28a66a303fc10 Mon Sep 17 00:00:00 2001 From: William Date: Mon, 11 Jul 2022 13:18:36 +0100 Subject: [PATCH] Improve initialization logic --- .../william278/husksync/BukkitHuskSync.java | 196 ++++++++---------- .../HuskSyncInitializationException.java | 12 ++ .../husksync/database/MySqlDatabase.java | 2 +- 3 files changed, 96 insertions(+), 114 deletions(-) create mode 100644 common/src/main/java/net/william278/husksync/HuskSyncInitializationException.java diff --git a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java index ce4a578e..c2436cd3 100644 --- a/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java +++ b/bukkit/src/main/java/net/william278/husksync/BukkitHuskSync.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.stream.Collectors; @@ -75,147 +76,116 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync { @Override public void onEnable() { - // Process initialization stages - CompletableFuture.supplyAsync(() -> { - + // Initialize HuskSync + final AtomicBoolean initialized = new AtomicBoolean(true); + try { // Set the logging adapter and resource reader this.logger = new BukkitLogger(this.getLogger()); this.resourceReader = new BukkitResourceReader(this); // Load settings and locales getLoggingAdapter().log(Level.INFO, "Loading plugin configuration settings & locales..."); - return reload().thenApply(loadedSettings -> { - if (loadedSettings) { - logger.showDebugLogs(settings.getBooleanValue(Settings.ConfigOption.DEBUG_LOGGING)); - getLoggingAdapter().log(Level.INFO, "Successfully loaded plugin configuration settings & locales"); - } else { - getLoggingAdapter().log(Level.SEVERE, "Failed to load plugin configuration settings and/or locales"); - } - return loadedSettings; - }).join(); - }).thenApply(succeeded -> { + initialized.set(reload().join()); + if (initialized.get()) { + logger.showDebugLogs(settings.getBooleanValue(Settings.ConfigOption.DEBUG_LOGGING)); + getLoggingAdapter().log(Level.INFO, "Successfully loaded plugin configuration settings & locales"); + } else { + throw new HuskSyncInitializationException("Failed to load plugin configuration settings and/or locales"); + } + // Prepare data adapter - if (succeeded) { - if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_COMPRESS_DATA)) { - dataAdapter = new CompressedDataAdapter(); - } else { - dataAdapter = new JsonDataAdapter(); - } + if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_COMPRESS_DATA)) { + dataAdapter = new CompressedDataAdapter(); + } else { + dataAdapter = new JsonDataAdapter(); } - return succeeded; - }).thenApply(succeeded -> { + // Prepare event cannon - if (succeeded) { - eventCannon = new BukkitEventCannon(); - } - return succeeded; - }).thenApply(succeeded -> { + eventCannon = new BukkitEventCannon(); + // Prepare data editor - if (succeeded) { - dataEditor = new DataEditor(locales); - } - return succeeded; - }).thenApply(succeeded -> { + dataEditor = new DataEditor(locales); + // Prepare migrators - if (succeeded) { - availableMigrators = new ArrayList<>(); - availableMigrators.add(new LegacyMigrator(this)); - final Plugin mySqlPlayerDataBridge = Bukkit.getPluginManager().getPlugin("MySqlPlayerDataBridge"); - if (mySqlPlayerDataBridge != null) { - availableMigrators.add(new MpdbMigrator(this, mySqlPlayerDataBridge)); - } + availableMigrators = new ArrayList<>(); + availableMigrators.add(new LegacyMigrator(this)); + final Plugin mySqlPlayerDataBridge = Bukkit.getPluginManager().getPlugin("MySqlPlayerDataBridge"); + if (mySqlPlayerDataBridge != null) { + availableMigrators.add(new MpdbMigrator(this, mySqlPlayerDataBridge)); } - return succeeded; - }).thenApply(succeeded -> { - // Establish connection to the database - if (succeeded) { - this.database = new MySqlDatabase(settings, resourceReader, logger, dataAdapter, eventCannon); - getLoggingAdapter().log(Level.INFO, "Attempting to establish connection to the database..."); - final CompletableFuture databaseConnectFuture = new CompletableFuture<>(); - Bukkit.getScheduler().runTask(this, () -> { - final boolean initialized = this.database.initialize(); - if (!initialized) { - getLoggingAdapter().log(Level.SEVERE, "Failed to establish a connection to the database. " + "Please check the supplied database credentials in the config file"); - databaseConnectFuture.completeAsync(() -> false); - return; - } - getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the database"); - databaseConnectFuture.completeAsync(() -> true); - }); - return databaseConnectFuture.join(); + + // Prepare database connection + this.database = new MySqlDatabase(settings, resourceReader, logger, dataAdapter, eventCannon); + getLoggingAdapter().log(Level.INFO, "Attempting to establish connection to the database..."); + initialized.set(this.database.initialize()); + if (initialized.get()) { + getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the database"); + } else { + throw new HuskSyncInitializationException("Failed to establish a connection to the database. " + + "Please check the supplied database credentials in the config file"); } - return false; - }).thenApply(succeeded -> { - // Establish connection to the Redis server - if (succeeded) { - this.redisManager = new RedisManager(this); - getLoggingAdapter().log(Level.INFO, "Attempting to establish connection to the Redis server..."); - return this.redisManager.initialize().thenApply(initialized -> { - if (!initialized) { - getLoggingAdapter().log(Level.SEVERE, "Failed to establish a connection to the Redis server. " + "Please check the supplied Redis credentials in the config file"); - return false; - } - getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the Redis server"); - return true; - }).join(); + + // Prepare redis connection + this.redisManager = new RedisManager(this); + getLoggingAdapter().log(Level.INFO, "Attempting to establish connection to the Redis server..."); + initialized.set(this.redisManager.initialize().join()); + if (initialized.get()) { + getLoggingAdapter().log(Level.INFO, "Successfully established a connection to the Redis server"); + } else { + throw new HuskSyncInitializationException("Failed to establish a connection to the Redis server. " + + "Please check the supplied Redis credentials in the config file"); } - return false; - }).thenApply(succeeded -> { + // Register events - if (succeeded) { - getLoggingAdapter().log(Level.INFO, "Registering events..."); - this.eventListener = new BukkitEventListener(this); - getLoggingAdapter().log(Level.INFO, "Successfully registered events listener"); - } - return succeeded; - }).thenApply(succeeded -> { + getLoggingAdapter().log(Level.INFO, "Registering events..."); + this.eventListener = new BukkitEventListener(this); + getLoggingAdapter().log(Level.INFO, "Successfully registered events listener"); + // Register permissions - if (succeeded) { - getLoggingAdapter().log(Level.INFO, "Registering permissions & commands..."); - Arrays.stream(Permission.values()).forEach(permission -> getServer().getPluginManager().addPermission(new org.bukkit.permissions.Permission(permission.node, switch (permission.defaultAccess) { - case EVERYONE -> PermissionDefault.TRUE; - case NOBODY -> PermissionDefault.FALSE; - case OPERATORS -> PermissionDefault.OP; - }))); - - // Register commands - for (final BukkitCommandType bukkitCommandType : BukkitCommandType.values()) { - final PluginCommand pluginCommand = getCommand(bukkitCommandType.commandBase.command); - if (pluginCommand != null) { - new BukkitCommand(bukkitCommandType.commandBase, this).register(pluginCommand); - } + getLoggingAdapter().log(Level.INFO, "Registering permissions & commands..."); + Arrays.stream(Permission.values()).forEach(permission -> getServer().getPluginManager() + .addPermission(new org.bukkit.permissions.Permission(permission.node, switch (permission.defaultAccess) { + case EVERYONE -> PermissionDefault.TRUE; + case NOBODY -> PermissionDefault.FALSE; + case OPERATORS -> PermissionDefault.OP; + }))); + + // Register commands + for (final BukkitCommandType bukkitCommandType : BukkitCommandType.values()) { + final PluginCommand pluginCommand = getCommand(bukkitCommandType.commandBase.command); + if (pluginCommand != null) { + new BukkitCommand(bukkitCommandType.commandBase, this).register(pluginCommand); } - getLoggingAdapter().log(Level.INFO, "Successfully registered permissions & commands"); } - return succeeded; - }).thenApply(succeeded -> { - if (succeeded && Bukkit.getPluginManager().getPlugin("Plan") != null) { + getLoggingAdapter().log(Level.INFO, "Successfully registered permissions & commands"); + + // Hook into plan + if (Bukkit.getPluginManager().getPlugin("Plan") != null) { getLoggingAdapter().log(Level.INFO, "Enabling Plan integration..."); new PlanHook(database, logger).hookIntoPlan(); getLoggingAdapter().log(Level.INFO, "Plan integration enabled!"); } - return succeeded; - }).thenApply(succeeded -> { + // Check for updates - if (succeeded && settings.getBooleanValue(Settings.ConfigOption.CHECK_FOR_UPDATES)) { + if (settings.getBooleanValue(Settings.ConfigOption.CHECK_FOR_UPDATES)) { getLoggingAdapter().log(Level.INFO, "Checking for updates..."); - new UpdateChecker(getPluginVersion(), getLoggingAdapter()).logToConsole(); + CompletableFuture.runAsync(() -> new UpdateChecker(getPluginVersion(), getLoggingAdapter()).logToConsole()); } - return succeeded; - }).thenAccept(succeeded -> { - // Handle failed initialization - if (!succeeded) { + } catch (HuskSyncInitializationException exception) { + getLoggingAdapter().log(Level.SEVERE, exception.getMessage()); + initialized.set(false); + } catch (Exception exception) { + getLoggingAdapter().log(Level.SEVERE, "An unhandled exception occurred initializing HuskSync!", exception); + initialized.set(false); + } finally { + // Validate initialization + if (initialized.get()) { + getLoggingAdapter().log(Level.INFO, "Successfully enabled HuskSync v" + getPluginVersion()); + } else { getLoggingAdapter().log(Level.SEVERE, "Failed to initialize HuskSync. The plugin will now be disabled"); getServer().getPluginManager().disablePlugin(this); - } else { - getLoggingAdapter().log(Level.INFO, "Successfully enabled HuskSync v" + getPluginVersion()); } - }).exceptionally(exception -> { - getLoggingAdapter().log(Level.SEVERE, "An exception occurred initializing HuskSync. (" + exception.getMessage() + ") The plugin will now be disabled."); - exception.printStackTrace(); - getServer().getPluginManager().disablePlugin(this); - return null; - }); + } } @Override diff --git a/common/src/main/java/net/william278/husksync/HuskSyncInitializationException.java b/common/src/main/java/net/william278/husksync/HuskSyncInitializationException.java new file mode 100644 index 00000000..63d41208 --- /dev/null +++ b/common/src/main/java/net/william278/husksync/HuskSyncInitializationException.java @@ -0,0 +1,12 @@ +package net.william278.husksync; + +import org.jetbrains.annotations.NotNull; + +/** + * Indicates an exception occurred while initialising the HuskSync plugin + */ +public class HuskSyncInitializationException extends RuntimeException { + public HuskSyncInitializationException(@NotNull String message) { + super(message); + } +} diff --git a/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java b/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java index d2eeffc4..9bd8aa66 100644 --- a/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java +++ b/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java @@ -114,7 +114,7 @@ public class MySqlDatabase extends Database { getLogger().log(Level.SEVERE, "Failed to perform database setup: " + e.getMessage()); } } catch (Exception e) { - e.printStackTrace(); + getLogger().log(Level.SEVERE, "An unhandled exception occurred during database setup!", e); } return false; }