bukman/src/main/java/net/frankheijden/serverutils/managers/PluginManager.java
Frank van der Heijden c2049503a7
Pass closable around instead of closing it straight away.
- Ensures ServerUtils can reload itself :)
2020-06-27 11:38:34 +02:00

297 lines
11 KiB
Java

package net.frankheijden.serverutils.managers;
import java.io.Closeable;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.frankheijden.serverutils.ServerUtils;
import net.frankheijden.serverutils.reflection.RCommandMap;
import net.frankheijden.serverutils.reflection.RCraftServer;
import net.frankheijden.serverutils.reflection.RCraftingManager;
import net.frankheijden.serverutils.reflection.RJavaPlugin;
import net.frankheijden.serverutils.reflection.RPlugin;
import net.frankheijden.serverutils.reflection.RPluginClassLoader;
import net.frankheijden.serverutils.reflection.RSimplePluginManager;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.InvalidPluginException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.UnknownDependencyException;
public class PluginManager {
/**
* Loads the specified file as a plugin.
* @param jarFile The name of the file in the plugins/ folder.
* @return The result of the loading procedure.
*/
public static LoadResult loadPlugin(String jarFile) {
return loadPlugin(new File(ServerUtils.getInstance().getDataFolder().getParent(), jarFile));
}
/**
* Loads the specified file as a plugin.
* @param file The file to be loaded.
* @return The result of the loading procedure.
*/
public static LoadResult loadPlugin(File file) {
if (!file.exists()) return new LoadResult(Result.NOT_EXISTS);
Plugin loadedPlugin = getLoadedPlugin(file);
if (loadedPlugin != null) return new LoadResult(Result.ALREADY_LOADED);
Plugin plugin;
try {
plugin = Bukkit.getPluginManager().loadPlugin(file);
} catch (InvalidDescriptionException ex) {
return new LoadResult(Result.INVALID_DESCRIPTION);
} catch (UnknownDependencyException ex) {
return new LoadResult(Result.UNKNOWN_DEPENDENCY.arg(ex.getMessage()));
} catch (InvalidPluginException ex) {
if (ex.getCause() instanceof IllegalArgumentException) {
IllegalArgumentException e = (IllegalArgumentException) ex.getCause();
if (e.getMessage().equalsIgnoreCase("Plugin already initialized!")) {
return new LoadResult(Result.ALREADY_ENABLED);
}
}
ex.printStackTrace();
return new LoadResult(Result.ERROR);
}
if (plugin == null) return new LoadResult(Result.INVALID_PLUGIN);
plugin.onLoad();
return new LoadResult(plugin);
}
/**
* Disables the specified plugin by name and cleans all commands and recipes of the plugin.
* @param pluginName The plugin to disable.
* @return The result of the disable call.
*/
public static Result disablePlugin(String pluginName) {
return disablePlugin(Bukkit.getPluginManager().getPlugin(pluginName));
}
/**
* Disables the specified plugin and cleans all commands and recipes of the plugin.
* @param plugin The plugin to disable.
* @return The result of the disable call.
*/
public static Result disablePlugin(Plugin plugin) {
if (plugin == null) return Result.NOT_ENABLED;
if (!plugin.isEnabled()) return Result.ALREADY_DISABLED;
try {
Bukkit.getPluginManager().disablePlugin(plugin);
RCraftingManager.removeRecipesFor(plugin);
} catch (Exception ex) {
ex.printStackTrace();
return Result.ERROR;
}
unregisterCommands(plugin);
return Result.SUCCESS;
}
/**
* Unloads the specified plugin by name and cleans all traces within bukkit.
* @param pluginName The plugin to unload.
* @return The result of the unload.
*/
public static CloseableResult unloadPlugin(String pluginName) {
return unloadPlugin(Bukkit.getPluginManager().getPlugin(pluginName));
}
/**
* Unloads the specified plugin and cleans all traces within bukkit.
* @param plugin The plugin to unload.
* @return The result of the unload.
*/
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());
closeable = RPluginClassLoader.clearClassLoader(RJavaPlugin.getClassLoader(plugin));
} catch (Exception ex) {
ex.printStackTrace();
return new CloseableResult(Result.ERROR);
}
return new CloseableResult(closeable);
}
/**
* Enables the specified plugin by name.
* @param pluginName The plugin to enable.
* @return The result of the enabling.
*/
public static Result enablePlugin(String pluginName) {
return enablePlugin(Bukkit.getPluginManager().getPlugin(pluginName));
}
/**
* Enables the specified plugin.
* @param plugin The plugin to enable.
* @return The result of the enabling.
*/
public static Result enablePlugin(Plugin plugin) {
if (plugin == null) return Result.NOT_EXISTS;
if (Bukkit.getPluginManager().isPluginEnabled(plugin.getName())) return Result.ALREADY_ENABLED;
Bukkit.getPluginManager().enablePlugin(plugin);
if (Bukkit.getPluginManager().isPluginEnabled(plugin.getName())) {
return Result.SUCCESS;
}
return Result.ERROR;
}
/**
* Reloads the specified plugin by name.
* @param pluginName The plugin to reload.
* @return The result of the reload.
*/
public static CloseableResult reloadPlugin(String pluginName) {
Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
if (plugin == null) return new CloseableResult(Result.NOT_EXISTS);
return reloadPlugin(plugin);
}
/**
* Reloads the specified plugin.
* @param plugin The plugin to reload.
* @return The result of the reload.
*/
public static CloseableResult reloadPlugin(Plugin plugin) {
Result disableResult = disablePlugin(plugin);
if (disableResult != Result.SUCCESS && disableResult != Result.ALREADY_DISABLED) {
return new CloseableResult(disableResult);
}
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.set(Result.ERROR);
}
LoadResult loadResult = loadPlugin(pluginFile);
if (!loadResult.isSuccess()) {
Result r = loadResult.getResult();
return result.set((r == Result.NOT_EXISTS) ? Result.FILE_CHANGED : r);
}
return result.set(enablePlugin(loadResult.getPlugin()));
}
/**
* Retrieves all known commands registered to bukkit.
* @return A map with all known commands.
*/
public static Map<String, Command> getKnownCommands() {
try {
return RCommandMap.getKnownCommands(RCraftServer.getCommandMap());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* Unregisters all commands from the specified plugin.
* @param plugin The plugin.
*/
public static void unregisterCommands(Plugin plugin) {
Map<String, Command> knownCommands = getKnownCommands();
if (knownCommands == null) return;
knownCommands.values().removeIf(c -> {
if (c instanceof PluginCommand) {
PluginCommand pc = (PluginCommand) c;
if (pc.getPlugin() == plugin) {
pc.unregister(RCraftServer.getCommandMap());
return true;
}
return false;
}
return false;
});
}
/**
* Retrieves a command from the command map.
* @param command The command string.
* @return The command.
*/
public static Command getCommand(String command) {
Map<String, Command> knownCommands = getKnownCommands();
if (knownCommands == null) return null;
return knownCommands.get(command);
}
/**
* Retrieves all file associations, i.e. all plugin loaders.
* @return A map with all pluginloaders.
*/
public static Map<Pattern, PluginLoader> getFileAssociations() {
try {
return RSimplePluginManager.getFileAssociations(Bukkit.getPluginManager());
} catch (IllegalAccessException ex) {
ex.printStackTrace();
return null;
}
}
/**
* Retrieves the PluginLoader for the input file.
* @param file The file.
* @return The appropiate PluginLoader.
*/
public static PluginLoader getPluginLoader(File file) {
Map<Pattern, PluginLoader> fileAssociations = getFileAssociations();
if (fileAssociations == null) return null;
for (Pattern filter : fileAssociations.keySet()) {
Matcher match = filter.matcher(file.getName());
if (match.find()) {
return fileAssociations.get(filter);
}
}
return null;
}
/**
* Retrieves a loaded plugin associated to a jar file.
* @param file The jar file.
* @return The already loaded plugin, or null if none.
*/
public static Plugin getLoadedPlugin(File file) {
PluginDescriptionFile descriptionFile;
try {
descriptionFile = getPluginDescription(file);
} catch (InvalidDescriptionException ex) {
return null;
}
if (descriptionFile == null) return null;
return Bukkit.getPluginManager().getPlugin(descriptionFile.getName());
}
/**
* Retrieves the PluginDescriptionFile of a jar file.
* @param file The jar file.
* @return The PluginDescriptionFile.
* @throws InvalidDescriptionException Iff the PluginDescriptionFile is invalid.
*/
public static PluginDescriptionFile getPluginDescription(File file) throws InvalidDescriptionException {
PluginLoader loader = getPluginLoader(file);
if (loader == null) return null;
return loader.getPluginDescription(file);
}
}