diff --git a/src/main/java/cn/citycraft/Yum/Yum.java b/src/main/java/cn/citycraft/Yum/Yum.java index bff6d73..96a97a6 100644 --- a/src/main/java/cn/citycraft/Yum/Yum.java +++ b/src/main/java/cn/citycraft/Yum/Yum.java @@ -3,11 +3,14 @@ */ package cn.citycraft.Yum; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import cn.citycraft.Yum.utils.DownloadUtils; +import cn.citycraft.Yum.utils.PluginUtil; /** * MC插件仓库 @@ -16,29 +19,45 @@ import cn.citycraft.Yum.utils.DownloadUtils; * 2015年8月21日下午5:14:39 */ public class Yum extends JavaPlugin { - String url = "http://ci.citycraft.cn:8800/jenkins/job/%1$s/lastSuccessfulBuild/artifact/target/%1$s.jar"; - @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { switch (args.length) { case 0: break; - case 2: + case 1: switch (args[0]) { - case "install": - if (DownloadUtils.download(String.format(url, args[1]), getDataFolder().getParent(), args[1])) { - sender.sendMessage("OK"); - } else { - sender.sendMessage("Error"); + case "list": + sender.sendMessage("§3服务器已安装插件: "); + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + sender.sendMessage("§6 - " + PluginUtil.getFormattedName(plugin, true)); } break; - case "remove": - break; } break; - + case 2: + Plugin plugin = this.getServer().getPluginManager().getPlugin(args[1]); + switch (args[0]) { + case "install": + if (DownloadUtils.download(sender, args[1])) + sender.sendMessage(PluginUtil.load(args[1])); + break; + case "remove": + if (plugin != null) { + sender.sendMessage(PluginUtil.unload(plugin)); + } else { + sender.sendMessage("插件不存在或已卸载!"); + } + break; + case "update": + if (plugin != null) { + if (DownloadUtils.download(sender, args[1])) + sender.sendMessage(PluginUtil.load(args[1])); + } else { + sender.sendMessage("插件不存在或已卸载!"); + } + break; + } } return true; } - } diff --git a/src/main/java/cn/citycraft/Yum/utils/DownloadUtils.java b/src/main/java/cn/citycraft/Yum/utils/DownloadUtils.java index d8d2a42..02275c4 100644 --- a/src/main/java/cn/citycraft/Yum/utils/DownloadUtils.java +++ b/src/main/java/cn/citycraft/Yum/utils/DownloadUtils.java @@ -8,9 +8,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; -import java.util.logging.Level; import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; /** * @author 蒋天蓓 @@ -18,49 +18,50 @@ import org.bukkit.Bukkit; * TODO */ public class DownloadUtils { - public static boolean download(String url, String dir, String filename) { - + public static boolean download(CommandSender sender, String pluginname) { + String url = "http://ci.citycraft.cn:8800/jenkins/job/%1$s/lastSuccessfulBuild/artifact/target/%1$s.jar"; BufferedInputStream in = null; FileOutputStream fout = null; + if (sender == null) + sender = Bukkit.getConsoleSender(); try { - URL fileUrl = new URL(url); - System.out.println("下载地址: " + url); + sender.sendMessage("开始下载: " + pluginname); + URL fileUrl = new URL(String.format(url, pluginname)); + sender.sendMessage("下载地址: http://********/" + fileUrl.getFile()); int fileLength = fileUrl.openConnection().getContentLength(); - System.out.println("文件长度: " + fileLength); + sender.sendMessage("文件长度: " + fileLength); in = new BufferedInputStream(fileUrl.openStream()); - File file = new File(dir, filename + ".jar"); + File file = new File("/plugins/", fileUrl.getFile()); if (!file.exists()) { file.createNewFile(); + sender.sendMessage("创建新文件: " + fileUrl.getFile()); } fout = new FileOutputStream(file); - byte[] data = new byte[1024]; - - // long downloaded = 0L; + long downloaded = 0L; int count; + long time = System.currentTimeMillis(); while ((count = in.read(data)) != -1) { - // downloaded += count; + downloaded += count; fout.write(data, 0, count); - // int percent = (int) (downloaded / fileLength); + double percent = downloaded / fileLength * 10000; + if (System.currentTimeMillis() - time > 1000) { + sender.sendMessage(String.format("已下载: ====================> %.2f%%", percent)); + time = System.currentTimeMillis(); + } } return true; } catch (Exception ex) { - Bukkit.getLogger().log(Level.WARNING, "The auto-updater tried to download a new update, but was unsuccessful.", ex); + sender.sendMessage("插件下载失败!"); return false; } finally { try { if (in != null) { in.close(); - } - } catch (IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, null, ex); - } - try { - if (fout != null) { fout.close(); } } catch (IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, null, ex); + sender.sendMessage("关闭数据流时发生错误!"); } } } diff --git a/src/main/java/cn/citycraft/Yum/utils/PluginUtil.java b/src/main/java/cn/citycraft/Yum/utils/PluginUtil.java new file mode 100644 index 0000000..ca92fa7 --- /dev/null +++ b/src/main/java/cn/citycraft/Yum/utils/PluginUtil.java @@ -0,0 +1,282 @@ +/** + * + */ +package cn.citycraft.Yum.utils; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.SortedSet; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.event.Event; +import org.bukkit.plugin.InvalidDescriptionException; +import org.bukkit.plugin.InvalidPluginException; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.RegisteredListener; + +import com.google.common.base.Joiner; + +/** + * 插件管理类 + * + * @author 蒋天蓓 + * 2015年8月21日下午7:03:26 + */ +public class PluginUtil { + + public static void enable(Plugin plugin) { + if ((!plugin.isEnabled()) && (plugin != null)) { + Bukkit.getPluginManager().enablePlugin(plugin); + } + } + + public static void enableAll() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (!isIgnored(plugin)) { + enable(plugin); + } + } + } + + public static void disable(Plugin plugin) { + if ((plugin.isEnabled()) && (plugin != null)) { + Bukkit.getPluginManager().disablePlugin(plugin); + } + } + + public static void disableAll() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (!isIgnored(plugin)) { + disable(plugin); + } + } + } + + public static String getFormattedName(Plugin plugin) { + return getFormattedName(plugin, false); + } + + public static String getFormattedName(Plugin plugin, boolean includeVersions) { + ChatColor color = plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED; + String pluginName = color + plugin.getName(); + if (includeVersions) + pluginName = pluginName + " (" + plugin.getDescription().getVersion() + ")"; + return pluginName; + } + + public static Plugin getPluginByName(String[] args, int start) { + return getPluginByName(StringUtil.consolidateStrings(args, start)); + } + + public static Plugin getPluginByName(String name) { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (name.equalsIgnoreCase(plugin.getName())) + return plugin; + } + return null; + } + + public static List getPluginNames(boolean fullName) { + List plugins = new ArrayList(); + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) + plugins.add(fullName ? plugin.getDescription().getFullName() : plugin.getName()); + return plugins; + } + + public static String getPluginVersion(String name) { + Plugin plugin = getPluginByName(name); + if ((plugin != null) && (plugin.getDescription() != null)) + return plugin.getDescription().getVersion(); + return null; + } + + public static String getUsages(Plugin plugin) { + List parsedCommands = new ArrayList(); + + Map> commands = plugin.getDescription().getCommands(); + + if (commands != null) { + Iterator>> commandsIt = commands.entrySet().iterator(); + while (commandsIt.hasNext()) { + Entry> thisEntry = commandsIt.next(); + if (thisEntry != null) { + parsedCommands.add(thisEntry.getKey()); + } + } + } + if (parsedCommands.isEmpty()) { + return "没有注册命令!"; + } + return Joiner.on(", ").join(parsedCommands); + } + + public static boolean isIgnored(Plugin plugin) { + return isIgnored(plugin.getName()); + } + + public static boolean isIgnored(String plugin) { + for (String name : new ArrayList()) { + if (name.equalsIgnoreCase(plugin)) + return true; + } + return false; + } + + private static String load(Plugin plugin) { + return load(plugin.getName()); + } + + public static String load(String name) { + Plugin target = null; + + File pluginDir = new File("plugins"); + + if (!pluginDir.isDirectory()) { + // TODO 提示 + } + File pluginFile = new File(pluginDir, name + ".jar"); + + if (!pluginFile.isFile()) { + return "插件不存在!"; + } + try { + target = Bukkit.getPluginManager().loadPlugin(pluginFile); + } catch (InvalidDescriptionException e) { + e.printStackTrace(); + return "错误的插件信息!"; + } catch (InvalidPluginException e) { + e.printStackTrace(); + return "错误的插件!"; + } + + target.onLoad(); + Bukkit.getPluginManager().enablePlugin(target); + + return "插件已载入!"; + } + + public static void reload(Plugin plugin) { + if (plugin != null) { + unload(plugin); + load(plugin); + } + } + + public static void reloadAll() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (!isIgnored(plugin)) { + reload(plugin); + } + } + } + + @SuppressWarnings("unchecked") + public static String unload(Plugin plugin) { + String name = plugin.getName(); + + PluginManager pluginManager = Bukkit.getPluginManager(); + + SimpleCommandMap commandMap = null; + + List plugins = null; + + Map names = null; + Map commands = null; + Map> listeners = null; + + boolean reloadlisteners = true; + + if (pluginManager != null) { + try { + Field pluginsField = Bukkit.getPluginManager().getClass().getDeclaredField("plugins"); + pluginsField.setAccessible(true); + plugins = (List) pluginsField.get(pluginManager); + + Field lookupNamesField = Bukkit.getPluginManager().getClass().getDeclaredField("lookupNames"); + lookupNamesField.setAccessible(true); + names = (Map) lookupNamesField.get(pluginManager); + try { + Field listenersField = Bukkit.getPluginManager().getClass().getDeclaredField("listeners"); + listenersField.setAccessible(true); + listeners = (Map>) listenersField.get(pluginManager); + } catch (Exception e) { + reloadlisteners = false; + } + + Field commandMapField = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap"); + commandMapField.setAccessible(true); + commandMap = (SimpleCommandMap) commandMapField.get(pluginManager); + + Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); + knownCommandsField.setAccessible(true); + commands = (Map) knownCommandsField.get(commandMap); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + return "插件卸载失败!"; + } catch (IllegalAccessException e) { + e.printStackTrace(); + return "插件已失败!"; + } + } + + pluginManager.disablePlugin(plugin); + + if ((plugins != null) && (plugins.contains(plugin))) { + plugins.remove(plugin); + } + if ((names != null) && (names.containsKey(name))) { + names.remove(name); + } + Iterator it; + if ((listeners != null) && (reloadlisteners)) { + for (SortedSet set : listeners.values()) { + for (it = set.iterator(); it.hasNext();) { + RegisteredListener value = it.next(); + if (value.getPlugin() == plugin) + it.remove(); + } + } + } + + Iterator> cmdit; + if (commandMap != null) { + for (cmdit = commands.entrySet().iterator(); cmdit.hasNext();) { + Map.Entry entry = cmdit.next(); + if ((entry.getValue() instanceof PluginCommand)) { + PluginCommand c = (PluginCommand) entry.getValue(); + if (c.getPlugin() == plugin) { + c.unregister(commandMap); + cmdit.remove(); + } + } + } + } + + ClassLoader cl = plugin.getClass().getClassLoader(); + + if ((cl instanceof URLClassLoader)) { + try { + ((URLClassLoader) cl).close(); + } catch (IOException ex) { + Logger.getLogger(PluginUtil.class.getName()).log(Level.SEVERE, null, ex); + } + } + + System.gc(); + return "插件已卸载!"; + } +} diff --git a/src/main/java/cn/citycraft/Yum/utils/StringUtil.java b/src/main/java/cn/citycraft/Yum/utils/StringUtil.java new file mode 100644 index 0000000..800ef6e --- /dev/null +++ b/src/main/java/cn/citycraft/Yum/utils/StringUtil.java @@ -0,0 +1,31 @@ +/** + * + */ +package cn.citycraft.Yum.utils; + +/** + * 字符串工具 + * + * @author 蒋天蓓 + * 2015年8月21日下午7:05:51 + */ +public class StringUtil { + + /** + * 转移数组 + * + * @param args + * - 原数组 + * @param start + * - 数组开始位置 + * @return 转移后的数组 + */ + public static String consolidateStrings(String[] args, int start) { + String ret = args[start]; + if (args.length > start + 1) { + for (int i = start + 1; i < args.length; i++) + ret = ret + " " + args[i]; + } + return ret; + } +} \ No newline at end of file