diff --git a/Bungee/src/main/java/net/frankheijden/serverutils/bungee/ServerUtils.java b/Bungee/src/main/java/net/frankheijden/serverutils/bungee/ServerUtils.java index 804afa4..95e875d 100644 --- a/Bungee/src/main/java/net/frankheijden/serverutils/bungee/ServerUtils.java +++ b/Bungee/src/main/java/net/frankheijden/serverutils/bungee/ServerUtils.java @@ -9,9 +9,14 @@ import net.frankheijden.serverutils.bungee.entities.BungeePlugin; import net.frankheijden.serverutils.bungee.entities.BungeeReflection; import net.frankheijden.serverutils.bungee.listeners.BungeeListener; import net.frankheijden.serverutils.bungee.managers.BungeePluginManager; +import net.frankheijden.serverutils.bungee.reflection.RPluginClassLoader; +import net.frankheijden.serverutils.bungee.reflection.RPluginManager; import net.frankheijden.serverutils.common.ServerUtilsApp; import net.frankheijden.serverutils.common.config.Config; import net.frankheijden.serverutils.common.config.Messenger; +import net.frankheijden.serverutils.common.entities.CloseableResult; +import net.frankheijden.serverutils.common.entities.Result; +import net.frankheijden.serverutils.common.utils.MapUtils; import net.md_5.bungee.api.plugin.Plugin; import org.bstats.bungeecord.Metrics; @@ -47,9 +52,20 @@ public class ServerUtils extends Plugin { reload(); getProxy().getPluginManager().registerListener(this, new BungeeListener()); + loadClasses(); ServerUtilsApp.tryCheckForUpdates(); } + /** + * Loads some classes in memory so they're available during updating. + */ + private void loadClasses() { + new RPluginManager(); + new MapUtils(); + new CloseableResult(Result.SUCCESS); + new RPluginClassLoader(); + } + public static ServerUtils getInstance() { return instance; } diff --git a/Bungee/src/main/java/net/frankheijden/serverutils/bungee/managers/BungeePluginManager.java b/Bungee/src/main/java/net/frankheijden/serverutils/bungee/managers/BungeePluginManager.java index 09f8cac..7ab3118 100644 --- a/Bungee/src/main/java/net/frankheijden/serverutils/bungee/managers/BungeePluginManager.java +++ b/Bungee/src/main/java/net/frankheijden/serverutils/bungee/managers/BungeePluginManager.java @@ -123,6 +123,7 @@ public class BungeePluginManager extends AbstractPluginManager { public CloseableResult reloadPlugin(Plugin plugin) { CloseableResult result = unloadPlugin(plugin); if (result.getResult() != Result.SUCCESS) return result; + result.tryClose(); File file = getPluginFile(plugin.getDescription().getName()); if (file == null) return result.set(Result.FILE_DELETED); @@ -145,13 +146,16 @@ public class BungeePluginManager extends AbstractPluginManager { plugin.onDisable(); proxy.getPluginManager().unregisterCommands(plugin); proxy.getPluginManager().unregisterListeners(plugin); + proxy.getScheduler().cancel(plugin); + Closeable closeable; try { RPluginManager.clearPlugin(proxy.getPluginManager(), plugin); + closeable = (Closeable) RPluginClassLoader.getPluginClassLoader(plugin); } catch (Exception ex) { ex.printStackTrace(); return new CloseableResult(Result.ERROR); } - return new CloseableResult(getCloseable(plugin)); + return new CloseableResult(closeable); } public static File getPluginFileExact(String fileName) { @@ -216,17 +220,6 @@ public class BungeePluginManager extends AbstractPluginManager { return entry; } - /** - * Retrieves the closable classloader of the plugin, if possible. - * @param plugin The plugin. - * @return The closable instance. - */ - public static Closeable getCloseable(Plugin plugin) { - ClassLoader loader = plugin.getClass().getClassLoader(); - if (loader instanceof Closeable) return (Closeable) loader; - return null; - } - @Override public File getPluginsFolder() { return plugin.getProxy().getPluginsFolder(); diff --git a/Bungee/src/main/java/net/frankheijden/serverutils/bungee/reflection/RPluginClassLoader.java b/Bungee/src/main/java/net/frankheijden/serverutils/bungee/reflection/RPluginClassLoader.java index d57019f..756a92b 100644 --- a/Bungee/src/main/java/net/frankheijden/serverutils/bungee/reflection/RPluginClassLoader.java +++ b/Bungee/src/main/java/net/frankheijden/serverutils/bungee/reflection/RPluginClassLoader.java @@ -1,13 +1,18 @@ package net.frankheijden.serverutils.bungee.reflection; +import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf; +import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields; +import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.net.URL; import java.util.Map; +import java.util.Set; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.PluginDescription; public class RPluginClassLoader { @@ -21,7 +26,9 @@ public class RPluginClassLoader { loaderClass = Class.forName("net.md_5.bungee.api.plugin.PluginClassloader"); constructor = loaderClass.getDeclaredConstructor(ProxyServer.class, PluginDescription.class, URL[].class); constructor.setAccessible(true); - fields = getAllFields(loaderClass); + fields = getAllFields(loaderClass, + fieldOf("allLoaders", ALL_VERSIONS), + fieldOf("plugin", ALL_VERSIONS)); } catch (Exception ex) { ex.printStackTrace(); } @@ -30,4 +37,26 @@ public class RPluginClassLoader { public static Object newInstance(ProxyServer proxy, PluginDescription desc, URL... urls) throws Exception { return constructor.newInstance(proxy, desc, urls); } + + /** + * Retrieves the PluginClassLoader of a specific plugin. + * @param plugin The plugin to lookup the PluginClassLoader for. + * @return The PluginClassLoader. + * @throws ReflectiveOperationException Iff a reflection error occurred. + */ + @SuppressWarnings("unchecked") + public static Object getPluginClassLoader(Plugin plugin) throws ReflectiveOperationException { + Set allLoaders = (Set) get(fields, null, "allLoaders"); + if (allLoaders == null) return null; + + Object matchingLoader = null; + for (Object loader : allLoaders) { + if (plugin.equals(get(fields, loader, "plugin"))) { + matchingLoader = loader; + break; + } + } + if (matchingLoader != null) allLoaders.remove(matchingLoader); + return matchingLoader; + } } diff --git a/Common/src/main/java/net/frankheijden/serverutils/common/tasks/UpdateCheckerTask.java b/Common/src/main/java/net/frankheijden/serverutils/common/tasks/UpdateCheckerTask.java index 4376a14..b9128b7 100644 --- a/Common/src/main/java/net/frankheijden/serverutils/common/tasks/UpdateCheckerTask.java +++ b/Common/src/main/java/net/frankheijden/serverutils/common/tasks/UpdateCheckerTask.java @@ -175,7 +175,7 @@ public class UpdateCheckerTask implements Runnable { if (isStartupCheck()) { plugin.getLogger().info(String.format(DOWNLOADED_RESTART, downloadedVersion)); - CloseableResult result = plugin.getPluginManager().reloadPlugin(ServerUtilsApp.getPlatformPlugin()); + CloseableResult result = plugin.getPluginManager().reloadPlugin((Object)ServerUtilsApp.getPlatformPlugin()); plugin.getLogger().info(String.format(UPGRADE_SUCCESS, downloadedVersion)); result.tryClose(); } else { diff --git a/build.gradle b/build.gradle index af0abcb..4cb839d 100644 --- a/build.gradle +++ b/build.gradle @@ -4,8 +4,7 @@ plugins { } group = 'net.frankheijden.serverutils' -String dependencyDir = group + '.dependencies' -version = '2.0.1' +version = '2.0.2' sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8