clean up and close classloader while unload plugin...

Signed-off-by: 502647092 <jtb1@163.com>
This commit is contained in:
502647092 2015-09-24 19:02:44 +08:00
parent acf587b022
commit 464093aade
20 changed files with 406 additions and 320 deletions

View File

@ -19,8 +19,8 @@ import cn.citycraft.Yum.manager.YumManager;
* @author 蒋天蓓 2015年8月21日下午5:14:39 * @author 蒋天蓓 2015年8月21日下午5:14:39
*/ */
public class Yum extends JavaPlugin { public class Yum extends JavaPlugin {
public YumManager yumgr;
public FileConfig config; public FileConfig config;
public YumManager yumgr;
@Override @Override
public void onDisable() { public void onDisable() {
@ -30,16 +30,16 @@ public class Yum extends JavaPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
HandlerCommand cmdhandler = new HandlerCommand(this); final HandlerCommand cmdhandler = new HandlerCommand(this);
this.getCommand("yum").setExecutor(cmdhandler); this.getCommand("yum").setExecutor(cmdhandler);
this.getCommand("yum").setTabCompleter(cmdhandler); this.getCommand("yum").setTabCompleter(cmdhandler);
yumgr = new YumManager(this); yumgr = new YumManager(this);
YumManager.repo.jsonToCache(config); YumManager.repo.jsonToCache(config);
new VersionChecker(this); new VersionChecker(this);
try { try {
Metrics metrics = new Metrics(this); final Metrics metrics = new Metrics(this);
metrics.start(); metrics.start();
} catch (IOException e) { } catch (final IOException e) {
} }
} }

View File

@ -3,7 +3,6 @@
*/ */
package cn.citycraft.Yum.api; package cn.citycraft.Yum.api;
/** /**
* Yum仓库插件API * Yum仓库插件API
* *

View File

@ -17,19 +17,19 @@ import org.bukkit.command.CommandSender;
* 2015年8月12日下午12:49:34 * 2015年8月12日下午12:49:34
*/ */
public abstract class BaseCommand { public abstract class BaseCommand {
private String name; private final String[] aliases;
private String permission; private final String description;
private String[] aliases;
private String description;
private int minimumArguments = 0; private int minimumArguments = 0;
private String possibleArguments = ""; private final String name;
private boolean onlyPlayerExecutable = false; private boolean onlyPlayerExecutable = false;
private String permission;
private String possibleArguments = "";
public BaseCommand(String name, String description) { public BaseCommand(final String name, final String description) {
this(name, description, new String[0]); this(name, description, new String[0]);
} }
public BaseCommand(String name, String description, String... aliases) { public BaseCommand(final String name, final String description, final String... aliases) {
this.name = name; this.name = name;
this.description = description; this.description = description;
this.aliases = aliases; this.aliases = aliases;
@ -51,11 +51,11 @@ public abstract class BaseCommand {
/** /**
* 获得当前命令的别名 * 获得当前命令的别名
* *
* @return 当前命令的别名 * @return 当前命令的别名
*/ */
public List<String> getCommandList() { public List<String> getCommandList() {
List<String> cmds = new ArrayList<String>(); final List<String> cmds = new ArrayList<String>();
cmds.add(name); cmds.add(name);
cmds.addAll(Arrays.asList(aliases)); cmds.addAll(Arrays.asList(aliases));
return cmds; return cmds;
@ -113,9 +113,10 @@ public abstract class BaseCommand {
* - 命令发送者 * - 命令发送者
* @return 是否有权限执行命令 * @return 是否有权限执行命令
*/ */
public final boolean hasPermission(CommandSender sender) { public final boolean hasPermission(final CommandSender sender) {
if (permission == null) if (permission == null) {
return true; return true;
}
return sender.hasPermission(permission); return sender.hasPermission(permission);
} }
@ -135,13 +136,17 @@ public abstract class BaseCommand {
* - 命令 * - 命令
* @return 是否匹配 * @return 是否匹配
*/ */
public final boolean isValidTrigger(String name) { public final boolean isValidTrigger(final String name) {
if (this.name.equalsIgnoreCase(name)) if (this.name.equalsIgnoreCase(name)) {
return true; return true;
if (aliases != null) }
for (String alias : aliases) if (aliases != null) {
if (alias.equalsIgnoreCase(name)) for (final String alias : aliases) {
if (alias.equalsIgnoreCase(name)) {
return true; return true;
}
}
}
return false; return false;
} }
@ -151,7 +156,7 @@ public abstract class BaseCommand {
* @param minimumArguments * @param minimumArguments
* - 最小参数个数 * - 最小参数个数
*/ */
public void setMinimumArguments(int minimumArguments) { public void setMinimumArguments(final int minimumArguments) {
this.minimumArguments = minimumArguments; this.minimumArguments = minimumArguments;
} }
@ -161,7 +166,7 @@ public abstract class BaseCommand {
* @param onlyPlayerExecutable * @param onlyPlayerExecutable
* - 是否只允许玩家执行 * - 是否只允许玩家执行
*/ */
public void setOnlyPlayerExecutable(boolean onlyPlayerExecutable) { public void setOnlyPlayerExecutable(final boolean onlyPlayerExecutable) {
this.onlyPlayerExecutable = onlyPlayerExecutable; this.onlyPlayerExecutable = onlyPlayerExecutable;
} }
@ -171,7 +176,7 @@ public abstract class BaseCommand {
* @param permission * @param permission
* - 命令权限 * - 命令权限
*/ */
public void setPermission(String permission) { public void setPermission(final String permission) {
this.permission = permission; this.permission = permission;
} }
@ -181,7 +186,7 @@ public abstract class BaseCommand {
* @param possibleArguments * @param possibleArguments
* - 可能的命令参数 * - 可能的命令参数
*/ */
public void setPossibleArguments(String possibleArguments) { public void setPossibleArguments(final String possibleArguments) {
this.possibleArguments = possibleArguments; this.possibleArguments = possibleArguments;
} }

View File

@ -22,7 +22,7 @@ public class CommandDelete extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandDelete(Yum main) { public CommandDelete(final Yum main) {
super("delete", "删除插件"); super("delete", "删除插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -30,15 +30,17 @@ public class CommandDelete extends BaseCommand {
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
String pluginname = args[0]; final String pluginname = args[0];
Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) if (plugin != null) {
if (YumManager.plugman.deletePlugin(sender, plugin)) if (YumManager.plugman.deletePlugin(sender, plugin)) {
sender.sendMessage("§c删除: §a插件 " + pluginname + " 已从服务器卸载并删除!"); sender.sendMessage("§c删除: §a插件 " + pluginname + " 已从服务器卸载并删除!");
else } else {
sender.sendMessage("§c删除: §c插件 " + pluginname + " 卸载或删除时发生错误 删除失败!"); sender.sendMessage("§c删除: §c插件 " + pluginname + " 卸载或删除时发生错误 删除失败!");
else }
} else {
sender.sendMessage("§c插件 " + pluginname + " 不存在或已卸载!"); sender.sendMessage("§c插件 " + pluginname + " 不存在或已卸载!");
}
}; };
} }

View File

@ -24,20 +24,21 @@ public class CommandInfo extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandInfo(Yum main) { public CommandInfo(final Yum main) {
super("info", "查看插件详情"); super("info", "查看插件详情");
this.main = main; this.main = main;
setPossibleArguments("<插件名称>"); setPossibleArguments("<插件名称>");
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
if (args.length == 0) if (args.length == 0) {
return; return;
String pluginname = args[0]; }
Plugin plugin = main.getServer().getPluginManager().getPlugin(pluginname); final String pluginname = args[0];
final Plugin plugin = main.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) { if (plugin != null) {
PluginDescriptionFile desc = plugin.getDescription(); final PluginDescriptionFile desc = plugin.getDescription();
sender.sendMessage("§6插件名称: §3" + plugin.getName()); sender.sendMessage("§6插件名称: §3" + plugin.getName());
sender.sendMessage("§6插件版本: §3" + desc.getVersion()); sender.sendMessage("§6插件版本: §3" + desc.getVersion());
sender.sendMessage("§6插件作者: §3" + StringUtils.join(desc.getAuthors(), " ")); sender.sendMessage("§6插件作者: §3" + StringUtils.join(desc.getAuthors(), " "));
@ -47,7 +48,8 @@ public class CommandInfo extends BaseCommand {
sender.sendMessage("§6插件软依赖: §3" + (desc.getSoftDepend().size() == 0 ? "" : "")); sender.sendMessage("§6插件软依赖: §3" + (desc.getSoftDepend().size() == 0 ? "" : ""));
StringUtil.sendStringArray(sender, desc.getSoftDepend()); StringUtil.sendStringArray(sender, desc.getSoftDepend());
sender.sendMessage("§6插件物理路径: §3" + YumManager.plugman.getPluginFile(plugin).getAbsolutePath()); sender.sendMessage("§6插件物理路径: §3" + YumManager.plugman.getPluginFile(plugin).getAbsolutePath());
} else } else {
sender.sendMessage("§4错误: §c插件 " + pluginname + " 不存在或已卸载!"); sender.sendMessage("§4错误: §c插件 " + pluginname + " 不存在或已卸载!");
}
}; };
} }

View File

@ -22,7 +22,7 @@ public class CommandInstall extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandInstall(Yum main) { public CommandInstall(final Yum main) {
super("install", "安装插件"); super("install", "安装插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -30,18 +30,20 @@ public class CommandInstall extends BaseCommand {
} }
@Override @Override
public void execute(final CommandSender sender, String label, final String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
final String pluginname = args[0]; final String pluginname = args[0];
Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin == null) if (plugin == null) {
Bukkit.getScheduler().runTaskAsynchronously(main, () -> { Bukkit.getScheduler().runTaskAsynchronously(main, () -> {
if (args.length < 2) if (args.length < 2) {
YumManager.install(sender, pluginname); YumManager.install(sender, pluginname);
else } else {
YumManager.install(sender, pluginname, args[1]); YumManager.install(sender, pluginname, args[1]);
}
}); });
else } else {
sender.sendMessage("§c插件已安装在服务器 需要更新请使用yum update " + pluginname + "!"); sender.sendMessage("§c插件已安装在服务器 需要更新请使用yum update " + pluginname + "!");
}
}; };
} }

View File

@ -22,15 +22,16 @@ public class CommandList extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandList(Yum main) { public CommandList(final Yum main) {
super("list", "列出已安装插件列表"); super("list", "列出已安装插件列表");
this.main = main; this.main = main;
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
sender.sendMessage("§6[Yum仓库]§3服务器已安装插件: "); sender.sendMessage("§6[Yum仓库]§3服务器已安装插件: ");
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
sender.sendMessage("§6 - " + YumManager.plugman.getFormattedName(plugin, true)); sender.sendMessage("§6 - " + YumManager.plugman.getFormattedName(plugin, true));
}
}; };
} }

View File

@ -22,7 +22,7 @@ public class CommandLoad extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandLoad(Yum main) { public CommandLoad(final Yum main) {
super("load", "载入插件"); super("load", "载入插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -30,12 +30,13 @@ public class CommandLoad extends BaseCommand {
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
String pluginname = args[0]; final String pluginname = args[0];
Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin == null) if (plugin == null) {
YumManager.plugman.load(sender, pluginname); YumManager.plugman.load(sender, pluginname);
else } else {
sender.sendMessage("§c错误: 插件 " + pluginname + " 已加载到服务器!"); sender.sendMessage("§c错误: 插件 " + pluginname + " 已加载到服务器!");
}
}; };
} }

View File

@ -22,7 +22,7 @@ public class CommandReload extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandReload(Yum main) { public CommandReload(final Yum main) {
super("reload", "重载插件"); super("reload", "重载插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -30,16 +30,17 @@ public class CommandReload extends BaseCommand {
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
String pluginname = args[0]; final String pluginname = args[0];
if (pluginname.equalsIgnoreCase("all") || pluginname.equalsIgnoreCase("*")) { if (pluginname.equalsIgnoreCase("all") || pluginname.equalsIgnoreCase("*")) {
YumManager.plugman.reloadAll(sender); YumManager.plugman.reloadAll(sender);
return; return;
} }
Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) if (plugin != null) {
YumManager.plugman.reload(sender, plugin); YumManager.plugman.reload(sender, plugin);
else } else {
sender.sendMessage("§c插件 " + pluginname + " 不存在或已卸载!"); sender.sendMessage("§c插件 " + pluginname + " 不存在或已卸载!");
}
}; };
} }

View File

@ -21,7 +21,7 @@ public class CommandRepo extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandRepo(Yum main) { public CommandRepo(final Yum main) {
super("repo", "插件源命令"); super("repo", "插件源命令");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -29,17 +29,19 @@ public class CommandRepo extends BaseCommand {
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
String cmd = args[0]; final String cmd = args[0];
switch (cmd) { switch (cmd) {
case "add": case "add":
if (args.length == 2) { if (args.length == 2) {
if (YumManager.repo.addRepositories(sender, args[1])) if (YumManager.repo.addRepositories(sender, args[1])) {
sender.sendMessage("§6仓库: §a插件信息已缓存!"); sender.sendMessage("§6仓库: §a插件信息已缓存!");
else } else {
sender.sendMessage("§6仓库: §c源地址未找到仓库信息或无法访问!"); sender.sendMessage("§6仓库: §c源地址未找到仓库信息或无法访问!");
} else }
} else {
sender.sendMessage("§6仓库: §c请输入源地址!"); sender.sendMessage("§6仓库: §c请输入源地址!");
}
break; break;
case "list": case "list":
sender.sendMessage("§6仓库: §b缓存的插件信息如下 "); sender.sendMessage("§6仓库: §b缓存的插件信息如下 ");

View File

@ -22,7 +22,7 @@ public class CommandUnload extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandUnload(Yum main) { public CommandUnload(final Yum main) {
super("unload", "卸载插件"); super("unload", "卸载插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -30,12 +30,13 @@ public class CommandUnload extends BaseCommand {
} }
@Override @Override
public void execute(CommandSender sender, String label, String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
String pluginname = args[0]; final String pluginname = args[0];
Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
if (plugin != null) if (plugin != null) {
YumManager.plugman.unload(sender, plugin); YumManager.plugman.unload(sender, plugin);
else } else {
sender.sendMessage("§c插件 " + pluginname + " 不存在或已卸载!"); sender.sendMessage("§c插件 " + pluginname + " 不存在或已卸载!");
}
}; };
} }

View File

@ -20,7 +20,7 @@ public class CommandUpdate extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandUpdate(Yum main) { public CommandUpdate(final Yum main) {
super("update", "更新插件"); super("update", "更新插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -28,18 +28,20 @@ public class CommandUpdate extends BaseCommand {
} }
@Override @Override
public void execute(final CommandSender sender, String label, final String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
final String pluginname = args[0]; final String pluginname = args[0];
final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
sender.sendMessage("§a开始更新插件: " + pluginname); sender.sendMessage("§a开始更新插件: " + pluginname);
if (plugin != null) if (plugin != null) {
Bukkit.getScheduler().runTaskAsynchronously(main, () -> { Bukkit.getScheduler().runTaskAsynchronously(main, () -> {
if (args.length < 2) if (args.length < 2) {
YumManager.update(sender, plugin); YumManager.update(sender, plugin);
else } else {
YumManager.update(sender, plugin, args[1]); YumManager.update(sender, plugin, args[1]);
}
}); });
else } else {
sender.sendMessage("§c插件未安装或已卸载 需要安装请使用yum install " + pluginname + "!"); sender.sendMessage("§c插件未安装或已卸载 需要安装请使用yum install " + pluginname + "!");
}
}; };
} }

View File

@ -20,7 +20,7 @@ public class CommandUpgrade extends BaseCommand {
/** /**
* @param name * @param name
*/ */
public CommandUpgrade(Yum main) { public CommandUpgrade(final Yum main) {
super("upgrade", "升级插件"); super("upgrade", "升级插件");
this.main = main; this.main = main;
setMinimumArguments(1); setMinimumArguments(1);
@ -28,18 +28,19 @@ public class CommandUpgrade extends BaseCommand {
} }
@Override @Override
public void execute(final CommandSender sender, String label, final String[] args) throws CommandException { public void execute(final CommandSender sender, final String label, final String[] args) throws CommandException {
Bukkit.getScheduler().runTaskAsynchronously(main, () -> { Bukkit.getScheduler().runTaskAsynchronously(main, () -> {
if (args.length == 0) if (args.length == 0) {
YumManager.plugman.upgrade(sender); YumManager.plugman.upgrade(sender);
else { } else {
String pluginname = args[0]; final String pluginname = args[0];
Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname); final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin(pluginname);
sender.sendMessage("§a开始升级插件: " + pluginname); sender.sendMessage("§a开始升级插件: " + pluginname);
if (plugin != null) if (plugin != null) {
YumManager.plugman.upgrade(sender, plugin); YumManager.plugman.upgrade(sender, plugin);
else } else {
sender.sendMessage("§c插件未安装或已卸载 需要安装请使用yum install " + pluginname + "!"); sender.sendMessage("§c插件未安装或已卸载 需要安装请使用yum install " + pluginname + "!");
}
} }
}); });
}; };

View File

@ -25,19 +25,19 @@ import cn.citycraft.Yum.manager.YumManager;
* @author 蒋天蓓 2015年8月22日上午8:29:44 * @author 蒋天蓓 2015年8月22日上午8:29:44
*/ */
public class HandlerCommand implements CommandExecutor, TabCompleter { public class HandlerCommand implements CommandExecutor, TabCompleter {
/**
* 已注册命令列表(包括别名)
*/
List<String> RegisterCommandList = new ArrayList<String>();
/** /**
* 命令监听类列表 * 命令监听类列表
*/ */
private List<BaseCommand> commandlist = new ArrayList<BaseCommand>();; private final List<BaseCommand> commandlist = new ArrayList<BaseCommand>();
/** /**
* 插件主类 * 插件主类
*/ */
Yum main; Yum main;;
/**
* 已注册命令列表(包括别名)
*/
List<String> RegisterCommandList = new ArrayList<String>();
/** /**
* 注册子命令 * 注册子命令
@ -45,7 +45,7 @@ public class HandlerCommand implements CommandExecutor, TabCompleter {
* @param yum * @param yum
* - 插件主类 * - 插件主类
*/ */
public HandlerCommand(Yum yum) { public HandlerCommand(final Yum yum) {
this.main = yum; this.main = yum;
registerCommand(new CommandList(yum)); registerCommand(new CommandList(yum));
registerCommand(new CommandInstall(yum)); registerCommand(new CommandInstall(yum));
@ -70,8 +70,8 @@ public class HandlerCommand implements CommandExecutor, TabCompleter {
* - 数组开始位置 * - 数组开始位置
* @return 转移后的数组字符串 * @return 转移后的数组字符串
*/ */
public static String[] moveStrings(String[] args, int start) { public static String[] moveStrings(final String[] args, final int start) {
String[] ret = new String[args.length - start]; final String[] ret = new String[args.length - start];
System.arraycopy(args, start, ret, 0, ret.length); System.arraycopy(args, start, ret, 0, ret.length);
return ret; return ret;
} }
@ -82,25 +82,28 @@ public class HandlerCommand implements CommandExecutor, TabCompleter {
* @return - 返回已注册的命令List * @return - 返回已注册的命令List
*/ */
public List<String> getRegisterCommands() { public List<String> getRegisterCommands() {
List<String> cmds = new ArrayList<String>(); final List<String> cmds = new ArrayList<String>();
for (BaseCommand command : commandlist) for (final BaseCommand command : commandlist) {
cmds.addAll(command.getCommandList()); cmds.addAll(command.getCommandList());
}
return cmds; return cmds;
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { public boolean onCommand(final CommandSender sender, final Command cmd, final String label, final String[] args) {
if (args.length == 0) if (args.length == 0) {
return true;
String subcmd = args[0];
if (subcmd.equalsIgnoreCase("help")) {
sender.sendMessage("§6=========YUM插件帮助列表=========");
for (BaseCommand command : commandlist)
sender.sendMessage(String.format("§6/yum §a%1$s %2$s §6- §b%3$s", command.getName(), command.getPossibleArguments(), command.getDescription()));
return true; return true;
} }
String[] subargs = moveStrings(args, 1); final String subcmd = args[0];
for (BaseCommand command : commandlist) if (subcmd.equalsIgnoreCase("help")) {
sender.sendMessage("§6=========YUM插件帮助列表=========");
for (final BaseCommand command : commandlist) {
sender.sendMessage(String.format("§6/yum §a%1$s %2$s §6- §b%3$s", command.getName(), command.getPossibleArguments(), command.getDescription()));
}
return true;
}
final String[] subargs = moveStrings(args, 1);
for (final BaseCommand command : commandlist) {
if (command.isValidTrigger(subcmd)) { if (command.isValidTrigger(subcmd)) {
if (!command.hasPermission(sender)) { if (!command.hasPermission(sender)) {
sender.sendMessage("§c你没有此命令的权限!"); sender.sendMessage("§c你没有此命令的权限!");
@ -110,40 +113,40 @@ public class HandlerCommand implements CommandExecutor, TabCompleter {
sender.sendMessage("§c控制台无法使用此命令!"); sender.sendMessage("§c控制台无法使用此命令!");
return true; return true;
} }
if (subargs.length >= command.getMinimumArguments()) if (subargs.length >= command.getMinimumArguments()) {
try { try {
command.execute(sender, subcmd, subargs); command.execute(sender, subcmd, subargs);
return true; return true;
} catch (CommandException e) { } catch (final CommandException e) {
sender.sendMessage(e.getMessage()); sender.sendMessage(e.getMessage());
} }
else } else {
sender.sendMessage("§c错误的参数 §e使用方法 /yum " + command.getName() + command.getPossibleArguments()); sender.sendMessage("§c错误的参数 §e使用方法 /yum " + command.getName() + command.getPossibleArguments());
}
} }
}
return false; return false;
} }
@Override @Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) { public List<String> onTabComplete(final CommandSender sender, final Command command, final String label, final String[] args) {
if (sender.isOp() || sender.hasPermission("yum.admin") || sender.hasPermission("yum." + args[0])) { if (sender.isOp() || sender.hasPermission("yum.admin") || sender.hasPermission("yum." + args[0])) {
List<String> completions = new ArrayList<>(); final List<String> completions = new ArrayList<>();
if (args.length == 1) { if (args.length == 1) {
String partialCommand = args[0]; final String partialCommand = args[0];
List<String> commands = RegisterCommandList; final List<String> commands = RegisterCommandList;
StringUtil.copyPartialMatches(partialCommand, commands, completions); StringUtil.copyPartialMatches(partialCommand, commands, completions);
} }
if (args.length == 2) { if (args.length == 2) {
String partialPlugin = args[1]; final String partialPlugin = args[1];
List<String> plugins = null; List<String> plugins = null;
if (args[0].equalsIgnoreCase("install")) if (args[0].equalsIgnoreCase("install")) {
plugins = YumManager.repo.getAllPluginName(); plugins = YumManager.repo.getAllPluginName();
else if (args[0].equalsIgnoreCase("repo")) } else if (args[0].equalsIgnoreCase("repo")) {
plugins = Arrays.asList(new String[] { "add", plugins = Arrays.asList(new String[] { "add", "list", "clean", "update" });
"list", } else {
"clean",
"update" });
else
plugins = YumManager.plugman.getPluginNames(false); plugins = YumManager.plugman.getPluginNames(false);
}
StringUtil.copyPartialMatches(partialPlugin, plugins, completions); StringUtil.copyPartialMatches(partialPlugin, plugins, completions);
} }
Collections.sort(completions); Collections.sort(completions);
@ -158,7 +161,7 @@ public class HandlerCommand implements CommandExecutor, TabCompleter {
* @param command * @param command
* - 被注册的命令类 * - 被注册的命令类
*/ */
public void registerCommand(BaseCommand command) { public void registerCommand(final BaseCommand command) {
commandlist.add(command); commandlist.add(command);
} }

View File

@ -19,7 +19,7 @@ import org.bukkit.plugin.Plugin;
public class DownloadManager { public class DownloadManager {
Plugin plugin; Plugin plugin;
public DownloadManager(Plugin main) { public DownloadManager(final Plugin main) {
this.plugin = main; this.plugin = main;
} }
@ -30,8 +30,8 @@ public class DownloadManager {
* - 地址 * - 地址
* @return 文件名称 * @return 文件名称
*/ */
public String getFileName(String url) { public String getFileName(final String url) {
int end = url.lastIndexOf('/'); final int end = url.lastIndexOf('/');
return url.substring(end + 1); return url.substring(end + 1);
} }
@ -42,22 +42,10 @@ public class DownloadManager {
* - 地址 * - 地址
* @return 文件名称 * @return 文件名称
*/ */
public String getFileName(URL url) { public String getFileName(final URL url) {
return getFileName(url.getFile()); return getFileName(url.getFile());
} }
private String getPer(int per) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 11; i++)
if (per > i)
sb.append("==");
else if (per == i)
sb.append("> ");
else
sb.append(" ");
return sb.toString();
}
/** /**
* 从网络下载文件 * 从网络下载文件
* *
@ -67,7 +55,7 @@ public class DownloadManager {
* - 下载地址 * - 下载地址
* @return 是否成功 * @return 是否成功
*/ */
public boolean run(CommandSender sender, String urlstring) { public boolean run(final CommandSender sender, final String urlstring) {
return run(sender, urlstring, new File("plugins", getFileName(urlstring))); return run(sender, urlstring, new File("plugins", getFileName(urlstring)));
} }
@ -82,11 +70,11 @@ public class DownloadManager {
* - 保存文件 * - 保存文件
* @return 是否成功 * @return 是否成功
*/ */
public boolean run(CommandSender sender, String urlstring, File file) { public boolean run(final CommandSender sender, final String urlstring, final File file) {
try { try {
URL url = new URL(urlstring); final URL url = new URL(urlstring);
return run(sender, url, file); return run(sender, url, file);
} catch (MalformedURLException e) { } catch (final MalformedURLException e) {
sender.sendMessage("§4错误: §c无法识别的URL地址..."); sender.sendMessage("§4错误: §c无法识别的URL地址...");
sender.sendMessage("§4地址: §c" + urlstring); sender.sendMessage("§4地址: §c" + urlstring);
return false; return false;
@ -104,15 +92,16 @@ public class DownloadManager {
* - 保存文件 * - 保存文件
* @return 是否成功 * @return 是否成功
*/ */
public boolean run(CommandSender sender, URL url, File file) { public boolean run(CommandSender sender, final URL url, final File file) {
BufferedInputStream in = null; BufferedInputStream in = null;
FileOutputStream fout = null; FileOutputStream fout = null;
if (sender == null) if (sender == null) {
sender = Bukkit.getConsoleSender(); sender = Bukkit.getConsoleSender();
}
try { try {
sender.sendMessage("§6开始下载: §3" + getFileName(url)); sender.sendMessage("§6开始下载: §3" + getFileName(url));
sender.sendMessage("§6下载地址: §3" + url.toString()); sender.sendMessage("§6下载地址: §3" + url.toString());
int fileLength = url.openConnection().getContentLength(); final int fileLength = url.openConnection().getContentLength();
if (fileLength < 0) { if (fileLength < 0) {
sender.sendMessage("§6下载: §c文件 " + file.getName() + " 获取长度错误(可能是网络问题)!"); sender.sendMessage("§6下载: §c文件 " + file.getName() + " 获取长度错误(可能是网络问题)!");
sender.sendMessage("§6文件: §c " + file.getName() + " 下载失败!"); sender.sendMessage("§6文件: §c " + file.getName() + " 下载失败!");
@ -124,38 +113,42 @@ public class DownloadManager {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
sender.sendMessage("§6创建新目录: §d" + file.getParentFile().getAbsolutePath()); sender.sendMessage("§6创建新目录: §d" + file.getParentFile().getAbsolutePath());
} }
if (file.exists()) if (file.exists()) {
file.delete(); file.delete();
}
file.createNewFile(); file.createNewFile();
sender.sendMessage("§6创建新文件: §d" + file.getAbsolutePath()); sender.sendMessage("§6创建新文件: §d" + file.getAbsolutePath());
fout = new FileOutputStream(file); fout = new FileOutputStream(file);
byte[] data = new byte[1024]; final byte[] data = new byte[1024];
long downloaded = 0L; long downloaded = 0L;
int count; int count;
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
while ((count = in.read(data)) != -1) { while ((count = in.read(data)) != -1) {
downloaded += count; downloaded += count;
fout.write(data, 0, count); fout.write(data, 0, count);
int percent = (int) (downloaded * 100L / fileLength); final int percent = (int) (downloaded * 100L / fileLength);
if (percent % 10 == 0) if (percent % 10 == 0) {
if (fileLength < 102400 || System.currentTimeMillis() - time > 1000) { if (fileLength < 102400 || System.currentTimeMillis() - time > 1000) {
sender.sendMessage(String.format("§6已下载: §a" + getPer(percent / 10) + " %s%%", percent)); sender.sendMessage(String.format("§6已下载: §a" + getPer(percent / 10) + " %s%%", percent));
time = System.currentTimeMillis(); time = System.currentTimeMillis();
} }
}
} }
sender.sendMessage("§6文件: §a " + file.getName() + " 下载完成!"); sender.sendMessage("§6文件: §a " + file.getName() + " 下载完成!");
return true; return true;
} catch (Exception ex) { } catch (final Exception ex) {
sender.sendMessage("§6异常: §c" + ex.getMessage()); sender.sendMessage("§6异常: §c" + ex.getMessage());
sender.sendMessage("§6文件: §c" + file.getName() + " 下载失败!"); sender.sendMessage("§6文件: §c" + file.getName() + " 下载失败!");
return false; return false;
} finally { } finally {
try { try {
if (in != null) if (in != null) {
in.close(); in.close();
if (fout != null) }
if (fout != null) {
fout.close(); fout.close();
} catch (Exception ex) { }
} catch (final Exception ex) {
} }
} }
} }
@ -167,7 +160,7 @@ public class DownloadManager {
* - 下载地址 * - 下载地址
* @return 是否成功 * @return 是否成功
*/ */
public boolean run(String urlstring) { public boolean run(final String urlstring) {
return run(null, urlstring); return run(null, urlstring);
} }
@ -180,7 +173,7 @@ public class DownloadManager {
* - 保存文件 * - 保存文件
* @return 是否成功 * @return 是否成功
*/ */
public boolean run(String urlstring, File file) { public boolean run(final String urlstring, final File file) {
return run(null, urlstring, file); return run(null, urlstring, file);
} }
@ -193,8 +186,22 @@ public class DownloadManager {
* - 保存文件 * - 保存文件
* @return 是否成功 * @return 是否成功
*/ */
public boolean run(URL url, File file) { public boolean run(final URL url, final File file) {
return run(null, url, file); return run(null, url, file);
} }
private String getPer(final int per) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < 11; i++) {
if (per > i) {
sb.append("==");
} else if (per == i) {
sb.append("> ");
} else {
sb.append(" ");
}
}
return sb.toString();
}
} }

View File

@ -7,9 +7,9 @@ import cn.citycraft.Yum.manager.Repositories.TagInfo;
public class PluginInfo { public class PluginInfo {
public Plugin plugin; public Plugin plugin;
public String url;
public String repo; public String repo;
public List<TagInfo> tags; public List<TagInfo> tags;
public String url;
public String getFileName() { public String getFileName() {
return String.format("%1$s-%2$s.jar", plugin.artifactId, plugin.version); return String.format("%1$s-%2$s.jar", plugin.artifactId, plugin.version);
@ -19,14 +19,16 @@ public class PluginInfo {
return getMavenUrl(null); return getMavenUrl(null);
} }
public String getMavenUrl(String version) { public String getMavenUrl(final String version) {
String ver = version; String ver = version;
if (ver == null && tags != null) if (ver == null && tags != null) {
for (TagInfo tagInfo : tags) for (final TagInfo tagInfo : tags) {
if (tagInfo.tag.equalsIgnoreCase("1.7.10")) { if (tagInfo.tag.equalsIgnoreCase("1.7.10")) {
ver = tagInfo.version; ver = tagInfo.version;
break; break;
} }
}
}
return String.format(url + (url.endsWith("/") ? "" : "/") + "%1$s/%2$s/%3$s/%2$s-%3$s.jar", plugin.groupId.replace(".", "/"), plugin.artifactId, ver == null ? plugin.version : ver); return String.format(url + (url.endsWith("/") ? "" : "/") + "%1$s/%2$s/%3$s/%2$s-%3$s.jar", plugin.groupId.replace(".", "/"), plugin.artifactId, ver == null ? plugin.version : ver);
} }
} }

View File

@ -37,7 +37,7 @@ import cn.citycraft.PluginHelper.utils.StringUtil;
public class PluginsManager { public class PluginsManager {
Plugin main; Plugin main;
public PluginsManager(Plugin plugin) { public PluginsManager(final Plugin plugin) {
this.main = plugin; this.main = plugin;
} }
@ -50,7 +50,7 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean deletePlugin(CommandSender sender, Plugin plugin) { public boolean deletePlugin(final CommandSender sender, final Plugin plugin) {
return unload(sender, plugin) && getPluginFile(plugin).delete(); return unload(sender, plugin) && getPluginFile(plugin).delete();
} }
@ -61,7 +61,7 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean deletePlugin(Plugin plugin) { public boolean deletePlugin(final Plugin plugin) {
return deletePlugin(Bukkit.getConsoleSender(), plugin); return deletePlugin(Bukkit.getConsoleSender(), plugin);
} }
@ -71,18 +71,21 @@ public class PluginsManager {
* @param plugin * @param plugin
* - 插件 * - 插件
*/ */
public void disable(Plugin plugin) { public void disable(final Plugin plugin) {
if ((plugin != null) && (plugin.isEnabled())) if ((plugin != null) && (plugin.isEnabled())) {
Bukkit.getPluginManager().disablePlugin(plugin); Bukkit.getPluginManager().disablePlugin(plugin);
}
} }
/** /**
* 关闭所有插件 * 关闭所有插件
*/ */
public void disableAll() { public void disableAll() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (!isIgnored(plugin)) if (!isIgnored(plugin)) {
disable(plugin); disable(plugin);
}
}
} }
/** /**
@ -91,18 +94,21 @@ public class PluginsManager {
* @param plugin * @param plugin
* - 插件 * - 插件
*/ */
public void enable(Plugin plugin) { public void enable(final Plugin plugin) {
if ((plugin != null) && (!plugin.isEnabled())) if ((plugin != null) && (!plugin.isEnabled())) {
Bukkit.getPluginManager().enablePlugin(plugin); Bukkit.getPluginManager().enablePlugin(plugin);
}
} }
/** /**
* 启用所有插件 * 启用所有插件
*/ */
public void enableAll() { public void enableAll() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (!isIgnored(plugin)) if (!isIgnored(plugin)) {
enable(plugin); enable(plugin);
}
}
} }
/** /**
@ -112,7 +118,7 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 格式化的插件名称 * @return 格式化的插件名称
*/ */
public String getFormattedName(Plugin plugin) { public String getFormattedName(final Plugin plugin) {
return getFormattedName(plugin, false); return getFormattedName(plugin, false);
} }
@ -125,11 +131,12 @@ public class PluginsManager {
* - 是否包括版本 * - 是否包括版本
* @return 格式化的插件名称 * @return 格式化的插件名称
*/ */
public String getFormattedName(Plugin plugin, boolean includeVersions) { public String getFormattedName(final Plugin plugin, final boolean includeVersions) {
ChatColor color = plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED; final ChatColor color = plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED;
String pluginName = color + plugin.getName(); String pluginName = color + plugin.getName();
if (includeVersions) if (includeVersions) {
pluginName = pluginName + " (" + plugin.getDescription().getVersion() + ")"; pluginName = pluginName + " (" + plugin.getDescription().getVersion() + ")";
}
return pluginName; return pluginName;
} }
@ -140,7 +147,7 @@ public class PluginsManager {
* - 名称 * - 名称
* @return 插件 * @return 插件
*/ */
public Plugin getPluginByName(String name) { public Plugin getPluginByName(final String name) {
return Bukkit.getPluginManager().getPlugin(name); return Bukkit.getPluginManager().getPlugin(name);
} }
@ -151,7 +158,7 @@ public class PluginsManager {
* - 名称 * - 名称
* @return 插件 * @return 插件
*/ */
public Plugin getPluginByName(String[] args, int start) { public Plugin getPluginByName(final String[] args, final int start) {
return getPluginByName(StringUtil.consolidateStrings(args, start)); return getPluginByName(StringUtil.consolidateStrings(args, start));
} }
@ -162,22 +169,23 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 插件的绝对路径 * @return 插件的绝对路径
*/ */
public File getPluginFile(Plugin plugin) { public File getPluginFile(final Plugin plugin) {
File file = null; File file = null;
ClassLoader cl = plugin.getClass().getClassLoader(); final ClassLoader cl = plugin.getClass().getClassLoader();
if ((cl instanceof URLClassLoader)) { if ((cl instanceof URLClassLoader)) {
@SuppressWarnings("resource") @SuppressWarnings("resource")
URLClassLoader ucl = (URLClassLoader) cl; final URLClassLoader ucl = (URLClassLoader) cl;
URL url = ucl.getURLs()[0]; final URL url = ucl.getURLs()[0];
file = new File(url.getFile()); file = new File(url.getFile());
} }
return file; return file;
} }
public List<String> getPluginNames(boolean fullName) { public List<String> getPluginNames(final boolean fullName) {
List<String> plugins = new ArrayList<String>(); final List<String> plugins = new ArrayList<String>();
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
plugins.add(fullName ? plugin.getDescription().getFullName() : plugin.getName()); plugins.add(fullName ? plugin.getDescription().getFullName() : plugin.getName());
}
return plugins; return plugins;
} }
@ -188,10 +196,11 @@ public class PluginsManager {
* - 插件名称 * - 插件名称
* @return 插件版本 * @return 插件版本
*/ */
public String getPluginVersion(String name) { public String getPluginVersion(final String name) {
Plugin plugin = getPluginByName(name); final Plugin plugin = getPluginByName(name);
if ((plugin != null) && (plugin.getDescription() != null)) if ((plugin != null) && (plugin.getDescription() != null)) {
return plugin.getDescription().getVersion(); return plugin.getDescription().getVersion();
}
return null; return null;
} }
@ -202,21 +211,23 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 插件命令 * @return 插件命令
*/ */
public String getUsages(Plugin plugin) { public String getUsages(final Plugin plugin) {
List<String> parsedCommands = new ArrayList<String>(); final List<String> parsedCommands = new ArrayList<String>();
Map<String, Map<String, Object>> commands = plugin.getDescription().getCommands(); final Map<String, Map<String, Object>> commands = plugin.getDescription().getCommands();
if (commands != null) { if (commands != null) {
Iterator<Entry<String, Map<String, Object>>> commandsIt = commands.entrySet().iterator(); final Iterator<Entry<String, Map<String, Object>>> commandsIt = commands.entrySet().iterator();
while (commandsIt.hasNext()) { while (commandsIt.hasNext()) {
Entry<String, Map<String, Object>> thisEntry = commandsIt.next(); final Entry<String, Map<String, Object>> thisEntry = commandsIt.next();
if (thisEntry != null) if (thisEntry != null) {
parsedCommands.add(thisEntry.getKey()); parsedCommands.add(thisEntry.getKey());
}
} }
} }
if (parsedCommands.isEmpty()) if (parsedCommands.isEmpty()) {
return null; return null;
}
return Joiner.on(", ").join(parsedCommands); return Joiner.on(", ").join(parsedCommands);
} }
@ -227,7 +238,7 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否 * @return 是否
*/ */
public boolean isIgnored(Plugin plugin) { public boolean isIgnored(final Plugin plugin) {
return isIgnored(plugin.getName()); return isIgnored(plugin.getName());
} }
@ -238,10 +249,12 @@ public class PluginsManager {
* - 插件名称 * - 插件名称
* @return 是否 * @return 是否
*/ */
public boolean isIgnored(String plugin) { public boolean isIgnored(final String plugin) {
for (String name : new ArrayList<String>()) for (final String name : new ArrayList<String>()) {
if (name.equalsIgnoreCase(plugin)) if (name.equalsIgnoreCase(plugin)) {
return true; return true;
}
}
return false; return false;
} }
@ -254,15 +267,17 @@ public class PluginsManager {
* - 插件名称 * - 插件名称
* @return 是否成功 * @return 是否成功
*/ */
public boolean load(CommandSender sender, String name) { public boolean load(CommandSender sender, final String name) {
Plugin target = null; Plugin target = null;
String filename = null; String filename = null;
if (sender == null) if (sender == null) {
sender = Bukkit.getConsoleSender(); sender = Bukkit.getConsoleSender();
if (!name.endsWith(".jar")) }
if (!name.endsWith(".jar")) {
filename = name + ".jar"; filename = name + ".jar";
File pluginDir = new File("plugins"); }
File updateDir = new File(pluginDir, "update"); final File pluginDir = new File("plugins");
final File updateDir = new File(pluginDir, "update");
if (!pluginDir.isDirectory()) { if (!pluginDir.isDirectory()) {
sender.sendMessage("§c插件目录不存在或IO错误!"); sender.sendMessage("§c插件目录不存在或IO错误!");
return false; return false;
@ -272,16 +287,18 @@ public class PluginsManager {
if (!pluginFile.isFile() && !new File(updateDir, filename).isFile()) { if (!pluginFile.isFile() && !new File(updateDir, filename).isFile()) {
pluginFile = null; pluginFile = null;
for (File file : pluginDir.listFiles()) for (final File file : pluginDir.listFiles()) {
if (file.getName().endsWith(".jar")) if (file.getName().endsWith(".jar")) {
try { try {
PluginDescriptionFile desc = main.getPluginLoader().getPluginDescription(file); final PluginDescriptionFile desc = main.getPluginLoader().getPluginDescription(file);
if (desc.getName().equalsIgnoreCase(name)) { if (desc.getName().equalsIgnoreCase(name)) {
pluginFile = file; pluginFile = file;
break; break;
} }
} catch (InvalidDescriptionException e) { } catch (final InvalidDescriptionException e) {
} }
}
}
if (pluginFile == null) { if (pluginFile == null) {
sender.sendMessage("§6载入: §c在插件目录和更新目录均未找到 " + name + " 插件 请确认文件是否存在!"); sender.sendMessage("§6载入: §c在插件目录和更新目录均未找到 " + name + " 插件 请确认文件是否存在!");
return false; return false;
@ -290,19 +307,19 @@ public class PluginsManager {
try { try {
target = Bukkit.getPluginManager().loadPlugin(pluginFile); target = Bukkit.getPluginManager().loadPlugin(pluginFile);
} catch (InvalidDescriptionException e) { } catch (final InvalidDescriptionException e) {
sender.sendMessage("§4异常: §c" + e.getMessage()); sender.sendMessage("§4异常: §c" + e.getMessage());
sender.sendMessage("§c插件: " + name + " 的plugin.yml文件存在错误!"); sender.sendMessage("§c插件: " + name + " 的plugin.yml文件存在错误!");
return false; return false;
} catch (UnsupportedClassVersionError e) { } catch (final UnsupportedClassVersionError e) {
sender.sendMessage("§4异常: §c" + e.getMessage()); sender.sendMessage("§4异常: §c" + e.getMessage());
sender.sendMessage("§c服务器或JAVA的版本低于插件: " + name + " 所需要的版本!!"); sender.sendMessage("§c服务器或JAVA的版本低于插件: " + name + " 所需要的版本!!");
return false; return false;
} catch (InvalidPluginException e) { } catch (final InvalidPluginException e) {
sender.sendMessage("§4异常: §c" + e.getMessage()); sender.sendMessage("§4异常: §c" + e.getMessage());
sender.sendMessage("§c文件: " + name + " 不是一个可载入的插件!"); sender.sendMessage("§c文件: " + name + " 不是一个可载入的插件!");
return false; return false;
} catch (UnknownDependencyException e) { } catch (final UnknownDependencyException e) {
sender.sendMessage("§4异常: §c" + e.getMessage()); sender.sendMessage("§4异常: §c" + e.getMessage());
sender.sendMessage("§c插件: " + name + " 缺少部分依赖项目!"); sender.sendMessage("§c插件: " + name + " 缺少部分依赖项目!");
return false; return false;
@ -321,7 +338,7 @@ public class PluginsManager {
* - 插件名称 * - 插件名称
* @return 是否成功 * @return 是否成功
*/ */
public boolean load(String name) { public boolean load(final String name) {
return load(Bukkit.getConsoleSender(), name); return load(Bukkit.getConsoleSender(), name);
} }
@ -334,9 +351,10 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean reload(CommandSender sender, Plugin plugin) { public boolean reload(final CommandSender sender, final Plugin plugin) {
if (plugin != null) if (plugin != null) {
return unload(sender, plugin) && load(sender, plugin.getName()); return unload(sender, plugin) && load(sender, plugin.getName());
}
return false; return false;
} }
@ -349,9 +367,10 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean reload(CommandSender sender, String name) { public boolean reload(final CommandSender sender, final String name) {
if (name != null) if (name != null) {
return unload(sender, name) && load(sender, name); return unload(sender, name) && load(sender, name);
}
return false; return false;
} }
@ -362,7 +381,7 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean reload(Plugin plugin) { public boolean reload(final Plugin plugin) {
return reload(Bukkit.getConsoleSender(), plugin); return reload(Bukkit.getConsoleSender(), plugin);
} }
@ -370,18 +389,22 @@ public class PluginsManager {
* 重载所有插件 * 重载所有插件
*/ */
public void reloadAll() { public void reloadAll() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (!isIgnored(plugin)) if (!isIgnored(plugin)) {
reload(plugin); reload(plugin);
}
}
} }
/** /**
* 重载所有插件 * 重载所有插件
*/ */
public void reloadAll(CommandSender sender) { public void reloadAll(final CommandSender sender) {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (!isIgnored(plugin)) if (!isIgnored(plugin)) {
reload(sender, plugin); reload(sender, plugin);
}
}
} }
/** /**
@ -393,7 +416,7 @@ public class PluginsManager {
* - 插件 * - 插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean unload(CommandSender sender, Plugin plugin) { public boolean unload(final CommandSender sender, final Plugin plugin) {
return unload(sender, plugin.getName()); return unload(sender, plugin.getName());
} }
@ -407,10 +430,11 @@ public class PluginsManager {
* @return 是否成功 * @return 是否成功
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public boolean unload(CommandSender sender, String name) { public boolean unload(CommandSender sender, final String name) {
if (sender == null) if (sender == null) {
sender = Bukkit.getConsoleSender(); sender = Bukkit.getConsoleSender();
PluginManager pluginManager = Bukkit.getPluginManager(); }
final PluginManager pluginManager = Bukkit.getPluginManager();
SimpleCommandMap commandMap = null; SimpleCommandMap commandMap = null;
List<Plugin> plugins = null; List<Plugin> plugins = null;
Map<String, Plugin> lookupNames = null; Map<String, Plugin> lookupNames = null;
@ -420,26 +444,26 @@ public class PluginsManager {
return false; return false;
} }
try { try {
Field pluginsField = pluginManager.getClass().getDeclaredField("plugins"); final Field pluginsField = pluginManager.getClass().getDeclaredField("plugins");
pluginsField.setAccessible(true); pluginsField.setAccessible(true);
plugins = (List<Plugin>) pluginsField.get(pluginManager); plugins = (List<Plugin>) pluginsField.get(pluginManager);
Field lookupNamesField = pluginManager.getClass().getDeclaredField("lookupNames"); final Field lookupNamesField = pluginManager.getClass().getDeclaredField("lookupNames");
lookupNamesField.setAccessible(true); lookupNamesField.setAccessible(true);
lookupNames = (Map<String, Plugin>) lookupNamesField.get(pluginManager); lookupNames = (Map<String, Plugin>) lookupNamesField.get(pluginManager);
Field commandMapField = pluginManager.getClass().getDeclaredField("commandMap"); final Field commandMapField = pluginManager.getClass().getDeclaredField("commandMap");
commandMapField.setAccessible(true); commandMapField.setAccessible(true);
commandMap = (SimpleCommandMap) commandMapField.get(pluginManager); commandMap = (SimpleCommandMap) commandMapField.get(pluginManager);
Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); final Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands");
knownCommandsField.setAccessible(true); knownCommandsField.setAccessible(true);
knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap); knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
} catch (Exception e) { } catch (final Exception e) {
sender.sendMessage("§4异常: §c" + e.getMessage() + " 插件 " + name + " 卸载失败!"); sender.sendMessage("§4异常: §c" + e.getMessage() + " 插件 " + name + " 卸载失败!");
return false; return false;
} }
for (Plugin next : pluginManager.getPlugins()) for (final Plugin next : pluginManager.getPlugins()) {
if (next.getName().equals(name)) { if (next.getName().equals(name)) {
pluginManager.disablePlugin(next); pluginManager.disablePlugin(next);
if ((plugins != null) && (plugins.contains(next))) { if ((plugins != null) && (plugins.contains(next))) {
@ -453,10 +477,10 @@ public class PluginsManager {
} }
if (commandMap != null) { if (commandMap != null) {
for (Iterator<Map.Entry<String, Command>> it = knownCommands.entrySet().iterator(); it.hasNext();) { for (final Iterator<Map.Entry<String, Command>> it = knownCommands.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Command> entry = it.next(); final Map.Entry<String, Command> entry = it.next();
if ((entry.getValue() instanceof PluginCommand)) { if ((entry.getValue() instanceof PluginCommand)) {
PluginCommand command = (PluginCommand) entry.getValue(); final PluginCommand command = (PluginCommand) entry.getValue();
if (command.getPlugin() == next) { if (command.getPlugin() == next) {
command.unregister(commandMap); command.unregister(commandMap);
it.remove(); it.remove();
@ -465,7 +489,14 @@ public class PluginsManager {
} }
sender.sendMessage("§6卸载: §a注销插件 " + name + " 的所有命令!"); sender.sendMessage("§6卸载: §a注销插件 " + name + " 的所有命令!");
} }
final ClassLoader cl = next.getClass().getClassLoader();
try {
((URLClassLoader) cl).close();
} catch (final IOException ex) {
}
System.gc();
} }
}
sender.sendMessage("§6卸载: §a插件 " + name + " 已成功卸载!"); sender.sendMessage("§6卸载: §a插件 " + name + " 已成功卸载!");
return true; return true;
} }
@ -477,7 +508,7 @@ public class PluginsManager {
* - 卸载插件 * - 卸载插件
* @return 是否成功 * @return 是否成功
*/ */
public boolean unload(Plugin plugin) { public boolean unload(final Plugin plugin) {
return unload(Bukkit.getConsoleSender(), plugin); return unload(Bukkit.getConsoleSender(), plugin);
} }
@ -486,7 +517,7 @@ public class PluginsManager {
* *
* @return 是否成功 * @return 是否成功
*/ */
public boolean upgrade(CommandSender sender) { public boolean upgrade(final CommandSender sender) {
sender.sendMessage("§6升级: §a开始升级 服务器更新 目录下的所有插件!"); sender.sendMessage("§6升级: §a开始升级 服务器更新 目录下的所有插件!");
return upgrade(sender, null, null); return upgrade(sender, null, null);
} }
@ -500,31 +531,33 @@ public class PluginsManager {
* - 更新目录 * - 更新目录
* @return 是否成功 * @return 是否成功
*/ */
public boolean upgrade(CommandSender sender, File directory, Plugin plugin) { public boolean upgrade(final CommandSender sender, final File directory, final Plugin plugin) {
boolean result = false; boolean result = false;
PluginLoader loader = main.getPluginLoader(); final PluginLoader loader = main.getPluginLoader();
File updateDirectory; File updateDirectory;
if (directory == null || !directory.isDirectory()) if (directory == null || !directory.isDirectory()) {
updateDirectory = Bukkit.getServer().getUpdateFolderFile(); updateDirectory = Bukkit.getServer().getUpdateFolderFile();
else } else {
updateDirectory = directory; updateDirectory = directory;
}
try { try {
sender.sendMessage("§6升级: §b从 " + updateDirectory.getCanonicalPath() + " 文件夹检索插件插件!"); sender.sendMessage("§6升级: §b从 " + updateDirectory.getCanonicalPath() + " 文件夹检索插件插件!");
} catch (SecurityException | IOException e1) { } catch (SecurityException | IOException e1) {
sender.sendMessage("§4异常: §c文件夹 " + updateDirectory.getName() + " 权限不足或IO错误!"); sender.sendMessage("§4异常: §c文件夹 " + updateDirectory.getName() + " 权限不足或IO错误!");
return false; return false;
} }
for (File file : updateDirectory.listFiles()) { for (final File file : updateDirectory.listFiles()) {
PluginDescriptionFile description = null; PluginDescriptionFile description = null;
try { try {
description = loader.getPluginDescription(file); description = loader.getPluginDescription(file);
String name = description.getName(); final String name = description.getName();
if (plugin != null && !name.equals(plugin.getName())) if (plugin != null && !name.equals(plugin.getName())) {
continue; continue;
}
result = true; result = true;
sender.sendMessage("§6升级: §a开始升级 " + name + " 插件!"); sender.sendMessage("§6升级: §a开始升级 " + name + " 插件!");
reload(sender, name); reload(sender, name);
} catch (InvalidDescriptionException e) { } catch (final InvalidDescriptionException e) {
sender.sendMessage("§4异常: §c" + e.getMessage()); sender.sendMessage("§4异常: §c" + e.getMessage());
sender.sendMessage("§4文件: §c" + file.getName() + " 的plugin.yml文件存在错误!"); sender.sendMessage("§4文件: §c" + file.getName() + " 的plugin.yml文件存在错误!");
} }
@ -538,7 +571,7 @@ public class PluginsManager {
* *
* @return 是否成功 * @return 是否成功
*/ */
public boolean upgrade(CommandSender sender, Plugin plugin) { public boolean upgrade(final CommandSender sender, final Plugin plugin) {
return upgrade(sender, null, plugin); return upgrade(sender, null, plugin);
} }
@ -547,7 +580,7 @@ public class PluginsManager {
* *
* @return 是否成功 * @return 是否成功
*/ */
public boolean upgrade(File directory) { public boolean upgrade(final File directory) {
Bukkit.getConsoleSender().sendMessage("§6升级: §a开始升级 " + directory.getName() + " 目录下的所有插件!"); Bukkit.getConsoleSender().sendMessage("§6升级: §a开始升级 " + directory.getName() + " 目录下的所有插件!");
return upgrade(Bukkit.getConsoleSender(), directory, null); return upgrade(Bukkit.getConsoleSender(), directory, null);
} }

View File

@ -15,22 +15,22 @@ import java.util.List;
public class Repositories { public class Repositories {
public class PackageInfo { public class PackageInfo {
public String name; public String name;
public String url;
public List<Plugin> plugins = new ArrayList<>(); public List<Plugin> plugins = new ArrayList<>();
public String url;
} }
public class Plugin { public class Plugin {
public String groupId;
public String artifactId; public String artifactId;
public String description; public String description;
public String version; public String groupId;
public List<TagInfo> tags; public List<TagInfo> tags;
public String version;
} }
public class Repository { public class Repository {
public String id; public String id;
public String url;
public String type; public String type;
public String url;
} }
public class TagInfo { public class TagInfo {

View File

@ -32,37 +32,40 @@ import cn.citycraft.Yum.manager.Repositories.Repository;;
*/ */
public class RepositoryManager { public class RepositoryManager {
Gson gson; Gson gson;
List<String> repos; org.bukkit.plugin.Plugin main;
HashMap<String, PluginInfo> plugins; HashMap<String, PluginInfo> plugins;
org.bukkit.plugin.Plugin main; List<String> repos;
public RepositoryManager(org.bukkit.plugin.Plugin plugin) { public RepositoryManager(final org.bukkit.plugin.Plugin plugin) {
this.main = plugin; this.main = plugin;
gson = new Gson(); gson = new Gson();
plugins = new HashMap<String, PluginInfo>(); plugins = new HashMap<String, PluginInfo>();
repos = new ArrayList<String>(); repos = new ArrayList<String>();
} }
public boolean addPackage(CommandSender sender, String urlstring) { public boolean addPackage(final CommandSender sender, final String urlstring) {
String json = getHtml(urlstring); final String json = getHtml(urlstring);
if (json.isEmpty()) if (json.isEmpty()) {
return false; return false;
PackageInfo pkg = jsonToPackage(json); }
if (pkg == null) final PackageInfo pkg = jsonToPackage(json);
if (pkg == null) {
return false; return false;
}
updatePackage(sender, pkg); updatePackage(sender, pkg);
return true; return true;
} }
public boolean addRepositories(CommandSender sender, String urlstring) { public boolean addRepositories(final CommandSender sender, final String urlstring) {
if (urlstring.isEmpty()) if (urlstring.isEmpty()) {
return false; return false;
}
repos.add(urlstring); repos.add(urlstring);
return updateRepositories(sender, urlstring); return updateRepositories(sender, urlstring);
} }
public void cacheToJson(FileConfiguration config) { public void cacheToJson(final FileConfiguration config) {
config.set("repocache", gson.toJson(repos)); config.set("repocache", gson.toJson(repos));
config.set("plugincache", gson.toJson(plugins)); config.set("plugincache", gson.toJson(plugins));
} }
@ -72,97 +75,106 @@ public class RepositoryManager {
} }
public List<PluginInfo> getAllPlugin() { public List<PluginInfo> getAllPlugin() {
List<PluginInfo> li = new ArrayList<PluginInfo>(); final List<PluginInfo> li = new ArrayList<PluginInfo>();
for (Entry<String, PluginInfo> plugin : plugins.entrySet()) for (final Entry<String, PluginInfo> plugin : plugins.entrySet()) {
li.add(plugin.getValue()); li.add(plugin.getValue());
}
return li; return li;
} }
public List<String> getAllPluginName() { public List<String> getAllPluginName() {
List<String> li = new ArrayList<String>(); final List<String> li = new ArrayList<String>();
for (Entry<String, PluginInfo> plugin : plugins.entrySet()) for (final Entry<String, PluginInfo> plugin : plugins.entrySet()) {
li.add(plugin.getValue().plugin.artifactId); li.add(plugin.getValue().plugin.artifactId);
}
return li; return li;
} }
public List<String> getAllPluginsInfo() { public List<String> getAllPluginsInfo() {
List<String> li = new ArrayList<String>(); final List<String> li = new ArrayList<String>();
for (Entry<String, PluginInfo> plugin : plugins.entrySet()) { for (final Entry<String, PluginInfo> plugin : plugins.entrySet()) {
Plugin pl = plugin.getValue().plugin; final Plugin pl = plugin.getValue().plugin;
li.add(String.format("§d%s §a%s(%s) §6- §e%s", plugin.getValue().repo, pl.artifactId, pl.version, pl.description)); li.add(String.format("§d%s §a%s(%s) §6- §e%s", plugin.getValue().repo, pl.artifactId, pl.version, pl.description));
} }
return li; return li;
} }
public String getHtml(String urlstring) { public String getHtml(final String urlstring) {
String html = ""; String html = "";
try { try {
URL url = new URL(urlstring); final URL url = new URL(urlstring);
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), Charsets.UTF_8)); final BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), Charsets.UTF_8));
String line; String line;
while ((line = br.readLine()) != null) while ((line = br.readLine()) != null) {
html += line; html += line;
}
return html; return html;
} catch (IOException e) { } catch (final IOException e) {
return null; return null;
} }
} }
public PluginInfo getPlugin(String name) { public PluginInfo getPlugin(final String name) {
for (Entry<String, PluginInfo> plugin : plugins.entrySet()) for (final Entry<String, PluginInfo> plugin : plugins.entrySet()) {
if (plugin.getValue().plugin.artifactId.equalsIgnoreCase(name)) if (plugin.getValue().plugin.artifactId.equalsIgnoreCase(name)) {
return plugin.getValue(); return plugin.getValue();
}
}
return null; return null;
} }
public List<PluginInfo> getPluginInfo(String name) { public List<PluginInfo> getPluginInfo(final String name) {
List<PluginInfo> li = new ArrayList<PluginInfo>(); final List<PluginInfo> li = new ArrayList<PluginInfo>();
for (Entry<String, PluginInfo> plugin : plugins.entrySet()) for (final Entry<String, PluginInfo> plugin : plugins.entrySet()) {
if (plugin.getValue().plugin.artifactId.equalsIgnoreCase(name)) if (plugin.getValue().plugin.artifactId.equalsIgnoreCase(name)) {
li.add(plugin.getValue()); li.add(plugin.getValue());
}
}
return li; return li;
} }
public PluginInfo getPluginInfo(String groupId, String artifactId) { public PluginInfo getPluginInfo(final String groupId, final String artifactId) {
return plugins.get(groupId + "." + artifactId); return plugins.get(groupId + "." + artifactId);
} }
public boolean jsonToCache(FileConfiguration config) { public boolean jsonToCache(final FileConfiguration config) {
String repocache = config.getString("repocache"); final String repocache = config.getString("repocache");
String plugincache = config.getString("plugincache"); final String plugincache = config.getString("plugincache");
try { try {
if (!repocache.isEmpty()) if (!repocache.isEmpty()) {
repos = gson.fromJson(repocache, new TypeToken<List<String>>() { repos = gson.fromJson(repocache, new TypeToken<List<String>>() {
}.getType()); }.getType());
if (!plugincache.isEmpty()) }
if (!plugincache.isEmpty()) {
plugins = gson.fromJson(plugincache, new TypeToken<HashMap<String, PluginInfo>>() { plugins = gson.fromJson(plugincache, new TypeToken<HashMap<String, PluginInfo>>() {
}.getType()); }.getType());
}
return true; return true;
} catch (JsonSyntaxException e) { } catch (final JsonSyntaxException e) {
return false; return false;
} }
} }
public PackageInfo jsonToPackage(String json) { public PackageInfo jsonToPackage(final String json) {
try { try {
return gson.fromJson(json, PackageInfo.class); return gson.fromJson(json, PackageInfo.class);
} catch (JsonSyntaxException e) { } catch (final JsonSyntaxException e) {
return null; return null;
} }
} }
public List<Repository> jsonToRepositories(String json) { public List<Repository> jsonToRepositories(final String json) {
try { try {
return gson.fromJson(json, new TypeToken<List<Repository>>() { return gson.fromJson(json, new TypeToken<List<Repository>>() {
}.getType()); }.getType());
} catch (JsonSyntaxException e) { } catch (final JsonSyntaxException e) {
return new ArrayList<Repository>(); return new ArrayList<Repository>();
} }
} }
public void updatePackage(CommandSender sender, PackageInfo pkg) { public void updatePackage(final CommandSender sender, final PackageInfo pkg) {
for (Plugin plugin : pkg.plugins) { for (final Plugin plugin : pkg.plugins) {
PluginInfo pi = new PluginInfo(); final PluginInfo pi = new PluginInfo();
pi.plugin = plugin; pi.plugin = plugin;
pi.url = pkg.url; pi.url = pkg.url;
pi.repo = pkg.name; pi.repo = pkg.name;
@ -171,29 +183,36 @@ public class RepositoryManager {
sender.sendMessage("§6仓库: §e" + pkg.name + " §a更新成功!"); sender.sendMessage("§6仓库: §e" + pkg.name + " §a更新成功!");
} }
public boolean updateRepositories(CommandSender sender) { public boolean updateRepositories(final CommandSender sender) {
plugins.clear(); plugins.clear();
for (String string : repos) for (final String string : repos) {
if (updateRepositories(sender, string)) if (updateRepositories(sender, string)) {
sender.sendMessage("§6源: §e" + string + " §a更新成功!"); sender.sendMessage("§6源: §e" + string + " §a更新成功!");
else } else {
sender.sendMessage("§6源: §e" + string + " §c更新失败!"); sender.sendMessage("§6源: §e" + string + " §c更新失败!");
}
}
return true; return true;
} }
public boolean updateRepositories(CommandSender sender, String urlstring) { public boolean updateRepositories(CommandSender sender, String urlstring) {
if (sender == null) if (sender == null) {
sender = Bukkit.getConsoleSender(); sender = Bukkit.getConsoleSender();
if (!urlstring.endsWith("repo.info")) }
if (!urlstring.endsWith("repo.info")) {
urlstring = urlstring + "/repo.info"; urlstring = urlstring + "/repo.info";
String json = getHtml(urlstring); }
if (json.isEmpty()) final String json = getHtml(urlstring);
if (json.isEmpty()) {
return false; return false;
List<Repository> lrepo = jsonToRepositories(json); }
if (lrepo.isEmpty()) final List<Repository> lrepo = jsonToRepositories(json);
if (lrepo.isEmpty()) {
return false; return false;
for (Repository repository : lrepo) }
for (final Repository repository : lrepo) {
addPackage(sender, repository.url); addPackage(sender, repository.url);
}
return true; return true;
} }
} }

View File

@ -19,38 +19,41 @@ public class YumManager {
Plugin plugin; Plugin plugin;
public YumManager(Plugin plugin) { public YumManager(final Plugin plugin) {
this.plugin = plugin; this.plugin = plugin;
plugman = new PluginsManager(plugin); plugman = new PluginsManager(plugin);
download = new DownloadManager(plugin); download = new DownloadManager(plugin);
repo = new RepositoryManager(plugin); repo = new RepositoryManager(plugin);
} }
public static boolean install(CommandSender sender, String pluginname) { public static boolean install(final CommandSender sender, final String pluginname) {
return install(sender, pluginname, null); return install(sender, pluginname, null);
} }
public static boolean install(CommandSender sender, String pluginname, String version) { public static boolean install(final CommandSender sender, final String pluginname, final String version) {
PluginInfo pi = repo.getPlugin(pluginname); final PluginInfo pi = repo.getPlugin(pluginname);
if (pi != null) if (pi != null) {
if (download.run(sender, pi.getMavenUrl(version))) if (download.run(sender, pi.getMavenUrl(version))) {
return plugman.load(sender, pluginname); return plugman.load(sender, pluginname);
}
}
return false; return false;
} }
public static boolean update(CommandSender sender, Plugin plugin) { public static boolean update(final CommandSender sender, final Plugin plugin) {
return update(sender, plugin, null); return update(sender, plugin, null);
} }
public static boolean update(CommandSender sender, Plugin plugin, String version) { public static boolean update(final CommandSender sender, final Plugin plugin, final String version) {
PluginInfo pi = repo.getPlugin(plugin.getName()); final PluginInfo pi = repo.getPlugin(plugin.getName());
if (pi != null) { if (pi != null) {
if (download.run(sender, pi.getMavenUrl(version), new File(Bukkit.getUpdateFolderFile(), plugman.getPluginFile(plugin).getName()))) { if (download.run(sender, pi.getMavenUrl(version), new File(Bukkit.getUpdateFolderFile(), plugman.getPluginFile(plugin).getName()))) {
sender.sendMessage("§6更新: §a已下载插件 " + plugin.getName() + " 到update文件夹 重启后自动更新(或使用upgrade直接升级)!"); sender.sendMessage("§6更新: §a已下载插件 " + plugin.getName() + " 到update文件夹 重启后自动更新(或使用upgrade直接升级)!");
return true; return true;
} }
} else } else {
sender.sendMessage("§6更新: §c仓库缓存中未找到插件 " + plugin.getName()); sender.sendMessage("§6更新: §c仓库缓存中未找到插件 " + plugin.getName());
}
return false; return false;
} }
} }