v2.0.5 - Fix for reloading ourselves
This commit is contained in:
parent
4b6008299b
commit
71b6a5fa02
8 changed files with 147 additions and 21 deletions
|
|
@ -32,6 +32,7 @@ import net.frankheijden.serverutils.common.utils.ForwardFilter;
|
||||||
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListFormat;
|
import net.frankheijden.serverutils.common.utils.ListFormat;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.PluginIdentifiableCommand;
|
import org.bukkit.command.PluginIdentifiableCommand;
|
||||||
|
|
@ -195,6 +196,16 @@ public class CommandServerUtils extends BaseCommand {
|
||||||
@CommandPermission("serverutils.reloadplugin")
|
@CommandPermission("serverutils.reloadplugin")
|
||||||
@Description("Reloads a specified plugin.")
|
@Description("Reloads a specified plugin.")
|
||||||
public void onReloadPlugin(CommandSender sender, String pluginName) {
|
public void onReloadPlugin(CommandSender sender, String pluginName) {
|
||||||
|
if (pluginName.equalsIgnoreCase("ServerUtils")) {
|
||||||
|
String result = BukkitPluginManager.get().reloadPlugin(pluginName).toString();
|
||||||
|
if (result.equals("SUCCESS")) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Successfully reloaded ServerUtils.");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Something went wrong reloading ServerUtils.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Result result = BukkitPluginManager.get().reloadPlugin(pluginName);
|
Result result = BukkitPluginManager.get().reloadPlugin(pluginName);
|
||||||
result.sendTo(BukkitUtils.wrap(sender), "reload", pluginName);
|
result.sendTo(BukkitUtils.wrap(sender), "reload", pluginName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package net.frankheijden.serverutils.bukkit.managers;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -16,6 +18,7 @@ import net.frankheijden.serverutils.bukkit.reflection.RCommandMap;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RCraftServer;
|
import net.frankheijden.serverutils.bukkit.reflection.RCraftServer;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RCraftingManager;
|
import net.frankheijden.serverutils.bukkit.reflection.RCraftingManager;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RJavaPlugin;
|
import net.frankheijden.serverutils.bukkit.reflection.RJavaPlugin;
|
||||||
|
import net.frankheijden.serverutils.bukkit.reflection.RJavaPluginLoader;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RPluginClassLoader;
|
import net.frankheijden.serverutils.bukkit.reflection.RPluginClassLoader;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RSimplePluginManager;
|
import net.frankheijden.serverutils.bukkit.reflection.RSimplePluginManager;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
||||||
|
|
@ -136,16 +139,34 @@ public class BukkitPluginManager extends AbstractPluginManager<Plugin> {
|
||||||
@Override
|
@Override
|
||||||
public CloseableResult unloadPlugin(Plugin plugin) {
|
public CloseableResult unloadPlugin(Plugin plugin) {
|
||||||
if (plugin == null) return new CloseableResult(Result.NOT_EXISTS);
|
if (plugin == null) return new CloseableResult(Result.NOT_EXISTS);
|
||||||
Closeable closeable;
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
RSimplePluginManager.getPlugins(Bukkit.getPluginManager()).remove(plugin);
|
RSimplePluginManager.getPlugins(Bukkit.getPluginManager()).remove(plugin);
|
||||||
RSimplePluginManager.removeLookupName(Bukkit.getPluginManager(), plugin.getName());
|
RSimplePluginManager.removeLookupName(Bukkit.getPluginManager(), plugin.getName());
|
||||||
closeable = RPluginClassLoader.clearClassLoader(RJavaPlugin.getClassLoader(plugin));
|
|
||||||
|
ClassLoader loader = RJavaPlugin.getClassLoader(plugin);
|
||||||
|
RPluginClassLoader.clearClassLoader(loader);
|
||||||
|
addIfInstance(closeables, (Closeable) () -> {
|
||||||
|
try {
|
||||||
|
Map<String, Class<?>> classes = RPluginClassLoader.getClasses(loader);
|
||||||
|
RJavaPluginLoader.removeClasses(getPluginLoader(getPluginFile(plugin)), classes.keySet());
|
||||||
|
} catch (IllegalAccessException ex) {
|
||||||
|
throw new IOException(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addIfInstance(closeables, loader);
|
||||||
|
addIfInstance(closeables, RJavaPlugin.clearJavaPlugin(plugin));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return new CloseableResult(Result.ERROR);
|
return new CloseableResult(Result.ERROR);
|
||||||
}
|
}
|
||||||
return new CloseableResult(closeable);
|
return new CloseableResult(closeables);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addIfInstance(List<Closeable> list, Object obj) {
|
||||||
|
if (obj instanceof Closeable) {
|
||||||
|
list.add((Closeable) obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
package net.frankheijden.serverutils.bukkit.reflection;
|
package net.frankheijden.serverutils.bukkit.reflection;
|
||||||
|
|
||||||
|
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
|
||||||
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
|
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
|
||||||
|
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
|
||||||
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
|
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
|
||||||
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
|
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
|
||||||
|
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -14,13 +19,18 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||||
public class RJavaPlugin {
|
public class RJavaPlugin {
|
||||||
|
|
||||||
private static Class<?> javaPluginClass;
|
private static Class<?> javaPluginClass;
|
||||||
|
private static Map<String, Field> fields;
|
||||||
private static Map<String, Method> methods;
|
private static Map<String, Method> methods;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
javaPluginClass = JavaPlugin.class;
|
javaPluginClass = JavaPlugin.class;
|
||||||
|
fields = getAllFields(javaPluginClass,
|
||||||
|
fieldOf("loader"),
|
||||||
|
fieldOf("classLoader"));
|
||||||
methods = getAllMethods(javaPluginClass,
|
methods = getAllMethods(javaPluginClass,
|
||||||
methodOf("getClassLoader"),
|
methodOf("getClassLoader"),
|
||||||
|
methodOf("getClass"),
|
||||||
methodOf("getFile"));
|
methodOf("getFile"));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
|
@ -34,4 +44,20 @@ public class RJavaPlugin {
|
||||||
public static File getFile(Object instance) throws ReflectiveOperationException {
|
public static File getFile(Object instance) throws ReflectiveOperationException {
|
||||||
return (File) invoke(methods, instance, "getFile");
|
return (File) invoke(methods, instance, "getFile");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the JavaPlugin from instances and returns the classloader associated with it.
|
||||||
|
* @param instance The instance of the JavaPlugin.
|
||||||
|
* @return The classloader associated with it.
|
||||||
|
* @throws ReflectiveOperationException When a reflection error occurred.
|
||||||
|
*/
|
||||||
|
public static Closeable clearJavaPlugin(Object instance) throws ReflectiveOperationException {
|
||||||
|
set(fields, instance, "loader", null);
|
||||||
|
set(fields, instance, "classLoader", null);
|
||||||
|
Class<?> clazz = (Class<?>) invoke(methods, instance, "getClass");
|
||||||
|
if (clazz != null && clazz.getClassLoader() instanceof Closeable) {
|
||||||
|
return (Closeable) clazz.getClassLoader();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package net.frankheijden.serverutils.bukkit.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 java.lang.reflect.Field;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||||
|
|
||||||
|
public class RJavaPluginLoader {
|
||||||
|
|
||||||
|
private static Class<?> javaPluginLoaderClass;
|
||||||
|
private static Map<String, Field> fields;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
javaPluginLoaderClass = JavaPluginLoader.class;
|
||||||
|
fields = getAllFields(javaPluginLoaderClass,
|
||||||
|
fieldOf("classes"));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given classes from the JavaPluginLoader instance.
|
||||||
|
* @param instance The instance.
|
||||||
|
* @param list The list of classpaths.
|
||||||
|
* @throws IllegalAccessException When prohibited access to the method.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static void removeClasses(Object instance, Collection<? extends String> list) throws IllegalAccessException {
|
||||||
|
Map<String, Class<?>> classes = (Map<String, Class<?>>) get(fields, instance, "classes");
|
||||||
|
if (classes == null) return;
|
||||||
|
|
||||||
|
for (String key : list) {
|
||||||
|
classes.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package net.frankheijden.serverutils.bukkit.reflection;
|
package net.frankheijden.serverutils.bukkit.reflection;
|
||||||
|
|
||||||
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
|
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.ReflectionUtils.getAllFields;
|
||||||
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
|
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -18,7 +18,8 @@ public class RPluginClassLoader {
|
||||||
pluginClassLoaderClass = Class.forName("org.bukkit.plugin.java.PluginClassLoader");
|
pluginClassLoaderClass = Class.forName("org.bukkit.plugin.java.PluginClassLoader");
|
||||||
fields = getAllFields(pluginClassLoaderClass,
|
fields = getAllFields(pluginClassLoaderClass,
|
||||||
fieldOf("plugin"),
|
fieldOf("plugin"),
|
||||||
fieldOf("pluginInit"));
|
fieldOf("pluginInit"),
|
||||||
|
fieldOf("classes"));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
@ -31,17 +32,13 @@ public class RPluginClassLoader {
|
||||||
/**
|
/**
|
||||||
* Clears and closes the provided classloader.
|
* Clears and closes the provided classloader.
|
||||||
* @param loader The classloader instance.
|
* @param loader The classloader instance.
|
||||||
* @return The Closeable object.
|
|
||||||
* @throws IllegalAccessException When prohibited access to the field.
|
* @throws IllegalAccessException When prohibited access to the field.
|
||||||
*/
|
*/
|
||||||
public static Closeable clearClassLoader(ClassLoader loader) throws IllegalAccessException {
|
public static void clearClassLoader(ClassLoader loader) throws IllegalAccessException {
|
||||||
if (loader == null) return null;
|
if (loader == null) return;
|
||||||
if (isInstance(loader)) {
|
if (isInstance(loader)) {
|
||||||
clearUrlClassLoader(loader);
|
clearPluginClassLoader(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loader instanceof Closeable) return (Closeable) loader;
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -49,9 +46,14 @@ public class RPluginClassLoader {
|
||||||
* @param pluginLoader The plugin loader instance.
|
* @param pluginLoader The plugin loader instance.
|
||||||
* @throws IllegalAccessException When prohibited access to the field.
|
* @throws IllegalAccessException When prohibited access to the field.
|
||||||
*/
|
*/
|
||||||
public static void clearUrlClassLoader(Object pluginLoader) throws IllegalAccessException {
|
public static void clearPluginClassLoader(Object pluginLoader) throws IllegalAccessException {
|
||||||
if (pluginLoader == null) return;
|
if (pluginLoader == null) return;
|
||||||
set(fields, pluginLoader, "plugin", null);
|
set(fields, pluginLoader, "plugin", null);
|
||||||
set(fields, pluginLoader, "pluginInit", null);
|
set(fields, pluginLoader, "pluginInit", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Map<String, Class<?>> getClasses(Object pluginLoader) throws IllegalAccessException {
|
||||||
|
return (Map<String,Class<?>>) get(fields, pluginLoader, "classes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListFormat;
|
import net.frankheijden.serverutils.common.utils.ListFormat;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.plugin.Command;
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
|
|
@ -136,6 +137,16 @@ public class CommandServerUtils extends BaseCommand {
|
||||||
@CommandPermission("serverutils.reloadplugin")
|
@CommandPermission("serverutils.reloadplugin")
|
||||||
@Description("Reloads a specified plugin.")
|
@Description("Reloads a specified plugin.")
|
||||||
public void onReloadPlugin(CommandSender sender, String pluginName) {
|
public void onReloadPlugin(CommandSender sender, String pluginName) {
|
||||||
|
if (pluginName.equalsIgnoreCase("ServerUtils")) {
|
||||||
|
String result = BungeePluginManager.get().reloadPlugin(pluginName).toString();
|
||||||
|
if (result.equals("SUCCESS")) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Successfully reloaded ServerUtils.");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Something went wrong reloading ServerUtils.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Result result = BungeePluginManager.get().reloadPlugin(pluginName);
|
Result result = BungeePluginManager.get().reloadPlugin(pluginName);
|
||||||
result.sendTo(BungeeUtils.wrap(sender), "reload", pluginName);
|
result.sendTo(BungeeUtils.wrap(sender), "reload", pluginName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package net.frankheijden.serverutils.common.entities;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A result which should be closed when done.
|
* A result which should be closed when done.
|
||||||
|
|
@ -9,18 +11,18 @@ import java.io.IOException;
|
||||||
public class CloseableResult implements Closeable {
|
public class CloseableResult implements Closeable {
|
||||||
|
|
||||||
private Result result;
|
private Result result;
|
||||||
private final Closeable closeable;
|
private final List<Closeable> closeables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new closable result.
|
* Constructs a new closable result.
|
||||||
* Used for unloading / reloading a plugin.
|
* Used for unloading / reloading a plugin.
|
||||||
* NB: The closable needs to be closed to fully ensure that the old plugin doesn't work anymore!
|
* 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 result The result of the procedure
|
||||||
* @param closeable The closable of the procedure.
|
* @param closeables The list of closable's of the procedure.
|
||||||
*/
|
*/
|
||||||
public CloseableResult(Result result, Closeable closeable) {
|
public CloseableResult(Result result, List<Closeable> closeables) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.closeable = closeable;
|
this.closeables = closeables;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -36,7 +38,15 @@ public class CloseableResult implements Closeable {
|
||||||
* @param closeable The closable of the procedure.
|
* @param closeable The closable of the procedure.
|
||||||
*/
|
*/
|
||||||
public CloseableResult(Closeable closeable) {
|
public CloseableResult(Closeable closeable) {
|
||||||
this(Result.SUCCESS, closeable);
|
this(Result.SUCCESS, Collections.singletonList(closeable));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new closable result with a closable instance and success result.
|
||||||
|
* @param closeables The list of closable's of the procedure.
|
||||||
|
*/
|
||||||
|
public CloseableResult(List<Closeable> closeables) {
|
||||||
|
this(Result.SUCCESS, closeables);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,7 +71,7 @@ public class CloseableResult implements Closeable {
|
||||||
* Attempts to close the closable, essentially wrapping it with try-catch.
|
* Attempts to close the closable, essentially wrapping it with try-catch.
|
||||||
*/
|
*/
|
||||||
public void tryClose() {
|
public void tryClose() {
|
||||||
if (closeable == null) return;
|
if (closeables == null) return;
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
|
|
@ -75,6 +85,8 @@ public class CloseableResult implements Closeable {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
closeable.close();
|
for (Closeable closeable : closeables) {
|
||||||
|
closeable.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'net.frankheijden.serverutils'
|
group = 'net.frankheijden.serverutils'
|
||||||
version = '2.0.4'
|
version = '2.0.5'
|
||||||
|
|
||||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue