PageRenderTime 110ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/src/main/java/ru/tehkode/permissions/commands/CommandsManager.java

https://gitlab.com/Slind/PermissionsEx
Java | 255 lines | 181 code | 51 blank | 23 comment | 36 complexity | 84c1f12e4c68deacec9bb08b3b940311 MD5 | raw file
  1. /*
  2. * PermissionsEx - Permissions plugin for Bukkit
  3. * Copyright (C) 2011 t3hk0d3 http://www.tehkode.ru
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. package ru.tehkode.permissions.commands;
  20. import java.lang.reflect.InvocationTargetException;
  21. import java.lang.reflect.Method;
  22. import java.util.*;
  23. import java.util.Map.Entry;
  24. import java.util.logging.Logger;
  25. import java.util.regex.Matcher;
  26. import java.util.regex.Pattern;
  27. import org.bukkit.ChatColor;
  28. import org.bukkit.command.CommandSender;
  29. import org.bukkit.entity.Player;
  30. import org.bukkit.plugin.Plugin;
  31. import ru.tehkode.permissions.PermissionManager;
  32. import ru.tehkode.permissions.bukkit.PermissionsEx;
  33. import ru.tehkode.permissions.commands.exceptions.AutoCompleteChoicesException;
  34. import ru.tehkode.utils.StringUtils;
  35. /**
  36. * @author code
  37. */
  38. public class CommandsManager {
  39. protected static final Logger logger = Logger.getLogger("Minecraft");
  40. protected Map<String, Map<CommandSyntax, CommandBinding>> listeners = new LinkedHashMap<String, Map<CommandSyntax, CommandBinding>>();
  41. protected Plugin plugin;
  42. protected List<Plugin> helpPlugins = new LinkedList<Plugin>();
  43. public CommandsManager(Plugin plugin) {
  44. this.plugin = plugin;
  45. }
  46. public void register(CommandListener listener) {
  47. for (Method method : listener.getClass().getMethods()) {
  48. if (!method.isAnnotationPresent(Command.class)) {
  49. continue;
  50. }
  51. Command cmdAnnotation = method.getAnnotation(Command.class);
  52. Map<CommandSyntax, CommandBinding> commandListeners = listeners.get(cmdAnnotation.name());
  53. if (commandListeners == null) {
  54. commandListeners = new LinkedHashMap<CommandSyntax, CommandBinding>();
  55. listeners.put(cmdAnnotation.name(), commandListeners);
  56. }
  57. commandListeners.put(new CommandSyntax(cmdAnnotation.syntax()), new CommandBinding(listener, method));
  58. }
  59. listener.onRegistered(this);
  60. }
  61. public boolean execute(CommandSender sender, org.bukkit.command.Command command, String[] args) {
  62. Map<CommandSyntax, CommandBinding> callMap = this.listeners.get(command.getName());
  63. if (callMap == null) { // No commands registered
  64. return false;
  65. }
  66. CommandBinding selectedBinding = null;
  67. int argumentsLength = 0;
  68. String arguments = StringUtils.implode(args, " ");
  69. for (Entry<CommandSyntax, CommandBinding> entry : callMap.entrySet()) {
  70. CommandSyntax syntax = entry.getKey();
  71. if (!syntax.isMatch(arguments)) {
  72. continue;
  73. }
  74. if (selectedBinding != null && syntax.getRegexp().length() < argumentsLength) { // match, but there already more fitted variant
  75. continue;
  76. }
  77. CommandBinding binding = entry.getValue();
  78. binding.setParams(syntax.getMatchedArguments(arguments));
  79. selectedBinding = binding;
  80. }
  81. if (selectedBinding == null) { // there is fitting handler
  82. sender.sendMessage(ChatColor.RED + "Error in command syntax. Check command help.");
  83. return true;
  84. }
  85. // Check permission
  86. if (sender instanceof Player) { // this method are not public and required permission
  87. if (!selectedBinding.checkPermissions((Player) sender)) {
  88. logger.warning("User " + ((Player) sender).getName() + " tried to access chat command \""
  89. + command.getName() + " " + arguments
  90. + "\", but doesn't have permission to do this.");
  91. sender.sendMessage(ChatColor.RED + "Sorry, you don't have enough permissions.");
  92. return true;
  93. }
  94. }
  95. try {
  96. selectedBinding.call(this.plugin, sender, selectedBinding.getParams());
  97. } catch (InvocationTargetException e) {
  98. if (e.getTargetException() instanceof AutoCompleteChoicesException) {
  99. AutoCompleteChoicesException autocomplete = (AutoCompleteChoicesException) e.getTargetException();
  100. sender.sendMessage("Autocomplete for <" + autocomplete.getArgName() + ">:");
  101. sender.sendMessage(" " + StringUtils.implode(autocomplete.getChoices(), " "));
  102. } else {
  103. throw new RuntimeException(e.getTargetException());
  104. }
  105. } catch (Exception e) {
  106. logger.severe("There is bogus command handler for " + command.getName() + " command. (Is appropriate plugin is update?)");
  107. if (e.getCause() != null) {
  108. e.getCause().printStackTrace();
  109. } else {
  110. e.printStackTrace();
  111. }
  112. }
  113. return true;
  114. }
  115. public List<CommandBinding> getCommands() {
  116. List<CommandBinding> commands = new LinkedList<CommandBinding>();
  117. for (Map<CommandSyntax, CommandBinding> map : this.listeners.values()) {
  118. commands.addAll(map.values());
  119. }
  120. return commands;
  121. }
  122. protected class CommandSyntax {
  123. protected String originalSyntax;
  124. protected String regexp;
  125. protected List<String> arguments = new LinkedList<String>();
  126. public CommandSyntax(String syntax) {
  127. this.originalSyntax = syntax;
  128. this.regexp = this.prepareSyntaxRegexp(syntax);
  129. }
  130. public String getRegexp() {
  131. return regexp;
  132. }
  133. private String prepareSyntaxRegexp(String syntax) {
  134. String expression = syntax;
  135. Matcher argMatcher = Pattern.compile("(?:[\\s]+)?((\\<|\\[)([^\\>\\]]+)(?:\\>|\\]))").matcher(expression);
  136. //Matcher argMatcher = Pattern.compile("(\\<|\\[)([^\\>\\]]+)(?:\\>|\\])").matcher(expression);
  137. int index = 0;
  138. while (argMatcher.find()) {
  139. if (argMatcher.group(2).equals("[")) {
  140. expression = expression.replace(argMatcher.group(0), "(?:(?:[\\s]+)(\"[^\"]+\"|[^\\s]+))?");
  141. } else {
  142. expression = expression.replace(argMatcher.group(1), "(\"[^\"]+\"|[\\S]+)");
  143. }
  144. arguments.add(index++, argMatcher.group(3));
  145. }
  146. return expression;
  147. }
  148. public boolean isMatch(String str) {
  149. return str.matches(this.regexp);
  150. }
  151. public Map<String, String> getMatchedArguments(String str) {
  152. Map<String, String> matchedArguments = new HashMap<String, String>(this.arguments.size());
  153. if (this.arguments.size() > 0) {
  154. Matcher argMatcher = Pattern.compile(this.regexp).matcher(str);
  155. if (argMatcher.find()) {
  156. for (int index = 1; index <= argMatcher.groupCount(); index++) {
  157. String argumentValue = argMatcher.group(index);
  158. if (argumentValue == null || argumentValue.isEmpty()) {
  159. continue;
  160. }
  161. if (argumentValue.startsWith("\"") && argumentValue.endsWith("\"")) { // Trim boundary colons
  162. argumentValue = argumentValue.substring(1, argumentValue.length() - 1);
  163. }
  164. matchedArguments.put(this.arguments.get(index - 1), argumentValue);
  165. }
  166. }
  167. }
  168. return matchedArguments;
  169. }
  170. }
  171. public class CommandBinding {
  172. protected Object object;
  173. protected Method method;
  174. protected Map<String, String> params = new HashMap<String, String>();
  175. public CommandBinding(Object object, Method method) {
  176. this.object = object;
  177. this.method = method;
  178. }
  179. public Command getMethodAnnotation() {
  180. return this.method.getAnnotation(Command.class);
  181. }
  182. public Map<String, String> getParams() {
  183. return params;
  184. }
  185. public void setParams(Map<String, String> params) {
  186. this.params = params;
  187. }
  188. public boolean checkPermissions(Player player) {
  189. PermissionManager manager = PermissionsEx.getPermissionManager();
  190. String permission = this.getMethodAnnotation().permission();
  191. if (permission.contains("<")) {
  192. for (Entry<String, String> entry : this.getParams().entrySet()) {
  193. if (entry.getValue() != null) {
  194. permission = permission.replace("<" + entry.getKey() + ">", entry.getValue().toLowerCase());
  195. }
  196. }
  197. }
  198. return manager.has(player, permission);
  199. }
  200. public void call(Object... args) throws Exception {
  201. this.method.invoke(object, args);
  202. }
  203. }
  204. }