From c2049503a724c9c50993432171d7ca95d0aea128 Mon Sep 17 00:00:00 2001 From: Frank van der Heijden Date: Sat, 27 Jun 2020 11:38:34 +0200 Subject: [PATCH] Pass closable around instead of closing it straight away. - Ensures ServerUtils can reload itself :) --- .../frankheijden/serverutils/ServerUtils.java | 6 +- .../commands/CommandServerUtils.java | 11 ++-- .../serverutils/managers/CloseableResult.java | 55 +++++++++++++++++++ .../serverutils/managers/PluginManager.java | 34 +++++++----- .../reflection/RPluginClassLoader.java | 15 ++--- 5 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 src/main/java/net/frankheijden/serverutils/managers/CloseableResult.java diff --git a/src/main/java/net/frankheijden/serverutils/ServerUtils.java b/src/main/java/net/frankheijden/serverutils/ServerUtils.java index 9397661..5728ddb 100644 --- a/src/main/java/net/frankheijden/serverutils/ServerUtils.java +++ b/src/main/java/net/frankheijden/serverutils/ServerUtils.java @@ -130,7 +130,11 @@ public class ServerUtils extends JavaPlugin implements CommandExecutor { return commandManager; } - private File[] getJars() { + /** + * Retrieves all files with a jar extension in the plugins/ folder. + * @return An array of jar files. + */ + public File[] getJars() { File parent = getDataFolder().getParentFile(); if (parent == null) return new File[0]; return parent.listFiles(f -> f.getName().endsWith(".jar")); diff --git a/src/main/java/net/frankheijden/serverutils/commands/CommandServerUtils.java b/src/main/java/net/frankheijden/serverutils/commands/CommandServerUtils.java index c460475..d4434a6 100644 --- a/src/main/java/net/frankheijden/serverutils/commands/CommandServerUtils.java +++ b/src/main/java/net/frankheijden/serverutils/commands/CommandServerUtils.java @@ -19,6 +19,7 @@ import java.util.Set; import net.frankheijden.serverutils.ServerUtils; import net.frankheijden.serverutils.config.Messenger; +import net.frankheijden.serverutils.managers.CloseableResult; import net.frankheijden.serverutils.managers.LoadResult; import net.frankheijden.serverutils.managers.PluginManager; import net.frankheijden.serverutils.managers.Result; @@ -171,8 +172,9 @@ public class CommandServerUtils extends BaseCommand { return; } - Result unloadResult = PluginManager.unloadPlugin(pluginName); - unloadResult.sendTo(sender, "unload", pluginName); + CloseableResult result = PluginManager.unloadPlugin(pluginName); + result.getResult().sendTo(sender, "unload", pluginName); + result.tryClose(); } /** @@ -185,8 +187,9 @@ public class CommandServerUtils extends BaseCommand { @CommandPermission("serverutils.reloadplugin") @Description("Reloads a specified plugin.") public void onReloadPlugin(CommandSender sender, String pluginName) { - Result result = PluginManager.reloadPlugin(pluginName); - result.sendTo(sender, "reload", pluginName); + CloseableResult result = PluginManager.reloadPlugin(pluginName); + result.getResult().sendTo(sender, "reload", pluginName); + result.tryClose(); } /** diff --git a/src/main/java/net/frankheijden/serverutils/managers/CloseableResult.java b/src/main/java/net/frankheijden/serverutils/managers/CloseableResult.java new file mode 100644 index 0000000..ebdd94f --- /dev/null +++ b/src/main/java/net/frankheijden/serverutils/managers/CloseableResult.java @@ -0,0 +1,55 @@ +package net.frankheijden.serverutils.managers; + +import java.io.Closeable; +import java.io.IOException; + +public class CloseableResult implements Closeable { + + private Result result; + private final Closeable closeable; + + /** + * Constructs a new closable result. + * Used for unloading / reloading a plugin. + * NB: The closable needs to be closed to fully ensure that the old plugin doesn't work anymore! + * @param result The result of the procedure + * @param closeable The closable of the procedure. + */ + public CloseableResult(Result result, Closeable closeable) { + this.result = result; + this.closeable = closeable; + } + + public CloseableResult(Result result) { + this(result, null); + } + + public CloseableResult(Closeable closeable) { + this(Result.SUCCESS, closeable); + } + + public Result getResult() { + return result; + } + + public CloseableResult set(Result result) { + this.result = result; + return this; + } + + /** + * Attempts to close the closable, essentially wrapping it with try-catch. + */ + public void tryClose() { + try { + close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + @Override + public void close() throws IOException { + closeable.close(); + } +} diff --git a/src/main/java/net/frankheijden/serverutils/managers/PluginManager.java b/src/main/java/net/frankheijden/serverutils/managers/PluginManager.java index c30f46b..59a7575 100644 --- a/src/main/java/net/frankheijden/serverutils/managers/PluginManager.java +++ b/src/main/java/net/frankheijden/serverutils/managers/PluginManager.java @@ -1,5 +1,6 @@ package net.frankheijden.serverutils.managers; +import java.io.Closeable; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.Map; @@ -102,7 +103,7 @@ public class PluginManager { * @param pluginName The plugin to unload. * @return The result of the unload. */ - public static Result unloadPlugin(String pluginName) { + public static CloseableResult unloadPlugin(String pluginName) { return unloadPlugin(Bukkit.getPluginManager().getPlugin(pluginName)); } @@ -111,17 +112,18 @@ public class PluginManager { * @param plugin The plugin to unload. * @return The result of the unload. */ - public static Result unloadPlugin(Plugin plugin) { - if (plugin == null) return Result.NOT_EXISTS; + public static CloseableResult unloadPlugin(Plugin plugin) { + if (plugin == null) return new CloseableResult(Result.NOT_EXISTS); + Closeable closeable; try { RSimplePluginManager.getPlugins(Bukkit.getPluginManager()).remove(plugin); RSimplePluginManager.removeLookupName(Bukkit.getPluginManager(), plugin.getName()); - RPluginClassLoader.clearClassLoader(RJavaPlugin.getClassLoader(plugin)); + closeable = RPluginClassLoader.clearClassLoader(RJavaPlugin.getClassLoader(plugin)); } catch (Exception ex) { ex.printStackTrace(); - return Result.ERROR; + return new CloseableResult(Result.ERROR); } - return Result.SUCCESS; + return new CloseableResult(closeable); } /** @@ -153,9 +155,9 @@ public class PluginManager { * @param pluginName The plugin to reload. * @return The result of the reload. */ - public static Result reloadPlugin(String pluginName) { + public static CloseableResult reloadPlugin(String pluginName) { Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName); - if (plugin == null) return Result.NOT_EXISTS; + if (plugin == null) return new CloseableResult(Result.NOT_EXISTS); return reloadPlugin(plugin); } @@ -164,27 +166,29 @@ public class PluginManager { * @param plugin The plugin to reload. * @return The result of the reload. */ - public static Result reloadPlugin(Plugin plugin) { + public static CloseableResult reloadPlugin(Plugin plugin) { Result disableResult = disablePlugin(plugin); - if (disableResult != Result.SUCCESS && disableResult != Result.ALREADY_DISABLED) return disableResult; + if (disableResult != Result.SUCCESS && disableResult != Result.ALREADY_DISABLED) { + return new CloseableResult(disableResult); + } - Result unloadResult = unloadPlugin(plugin); - if (unloadResult != Result.SUCCESS) return unloadResult; + CloseableResult result = unloadPlugin(plugin); + if (result.getResult() != Result.SUCCESS) return result; File pluginFile; try { pluginFile = RPlugin.getPluginFile(plugin); } catch (InvocationTargetException | IllegalAccessException ex) { ex.printStackTrace(); - return Result.ERROR; + return result.set(Result.ERROR); } LoadResult loadResult = loadPlugin(pluginFile); if (!loadResult.isSuccess()) { Result r = loadResult.getResult(); - return (r == Result.NOT_EXISTS) ? Result.FILE_CHANGED : r; + return result.set((r == Result.NOT_EXISTS) ? Result.FILE_CHANGED : r); } - return enablePlugin(loadResult.getPlugin()); + return result.set(enablePlugin(loadResult.getPlugin())); } /** diff --git a/src/main/java/net/frankheijden/serverutils/reflection/RPluginClassLoader.java b/src/main/java/net/frankheijden/serverutils/reflection/RPluginClassLoader.java index 593d553..3dbd380 100644 --- a/src/main/java/net/frankheijden/serverutils/reflection/RPluginClassLoader.java +++ b/src/main/java/net/frankheijden/serverutils/reflection/RPluginClassLoader.java @@ -5,9 +5,8 @@ import static net.frankheijden.serverutils.reflection.ReflectionUtils.VersionPar import static net.frankheijden.serverutils.reflection.ReflectionUtils.getAllFields; import static net.frankheijden.serverutils.reflection.ReflectionUtils.set; -import java.io.IOException; +import java.io.Closeable; import java.lang.reflect.Field; -import java.net.URLClassLoader; import java.util.Map; public class RPluginClassLoader { @@ -32,20 +31,18 @@ public class RPluginClassLoader { /** * Clears and closes the provided classloader. - * Remov * @param loader The classloader instance. - * @throws IOException When closing the loader failed. + * @return The Closeable object. * @throws IllegalAccessException When prohibited access to the field. */ - public static void clearClassLoader(ClassLoader loader) throws IOException, IllegalAccessException { - if (loader == null) return; + public static Closeable clearClassLoader(ClassLoader loader) throws IllegalAccessException { + if (loader == null) return null; if (isInstance(loader)) { clearUrlClassLoader(loader); } - if (loader instanceof URLClassLoader) { - ((URLClassLoader) loader).close(); - } + if (loader instanceof Closeable) return (Closeable) loader; + return null; } /**