001package fr.aumgn.bukkitutils.command.executor; 002 003import java.lang.reflect.InvocationTargetException; 004import java.lang.reflect.Method; 005import java.util.HashSet; 006import java.util.Set; 007import java.util.logging.Level; 008 009import org.bukkit.Bukkit; 010import org.bukkit.ChatColor; 011import org.bukkit.command.CommandExecutor; 012import org.bukkit.command.CommandSender; 013import org.bukkit.entity.Player; 014 015import fr.aumgn.bukkitutils.command.Command; 016import fr.aumgn.bukkitutils.command.Commands; 017import fr.aumgn.bukkitutils.command.CommandsMessages; 018import fr.aumgn.bukkitutils.command.args.CommandArgs; 019import fr.aumgn.bukkitutils.command.args.CommandArgsParser; 020import fr.aumgn.bukkitutils.command.exception.CommandException; 021import fr.aumgn.bukkitutils.command.exception.CommandUsageError; 022import fr.aumgn.bukkitutils.glob.exceptions.GlobException; 023import fr.aumgn.bukkitutils.glob.exceptions.UnbalancedSquareBracketException; 024 025public class MethodCommandExecutor implements CommandExecutor { 026 027 private final CommandsMessages messages; 028 private final Commands instance; 029 private final Method preExecute; 030 private final Method method; 031 private final int min; 032 private final int max; 033 private final Set<Character> flags; 034 private final Set<Character> argsFlags; 035 private final boolean isPlayerCommand; 036 037 public MethodCommandExecutor(CommandsMessages messages, Commands instance, 038 Method preExecute, Method method, int min, int max, String flags, 039 String argsFlags) { 040 this.messages = messages; 041 this.instance = instance; 042 this.preExecute = preExecute; 043 this.method = method; 044 045 if (method.getParameterTypes().length > 1) { 046 this.min = min; 047 this.max = max; 048 } else { 049 this.min = -1; 050 this.max = 0; 051 } 052 this.flags = new HashSet<Character>(); 053 for (char flag : flags.toCharArray()) { 054 this.flags.add(flag); 055 } 056 this.argsFlags = new HashSet<Character>(); 057 for (char flag : argsFlags.toCharArray()) { 058 this.argsFlags.add(flag); 059 } 060 this.isPlayerCommand = Player.class.isAssignableFrom( 061 method.getParameterTypes()[0]); 062 } 063 064 public MethodCommandExecutor(CommandsMessages messages, Commands instance, 065 Method preExecute, Method method, Command command) { 066 this(messages, instance, preExecute, method, command.min(), 067 command.max(), command.flags(), command.argsFlags()); 068 } 069 070 @Override 071 public boolean onCommand(CommandSender sender, 072 org.bukkit.command.Command cmd, String lbl, String[] rawArgs) { 073 if (isPlayerCommand && !(sender instanceof Player)) { 074 sender.sendMessage(ChatColor.RED + messages.playerOnly()); 075 return true; 076 } 077 try { 078 CommandArgs args; 079 if (min >= 0) { 080 args = getArgs(rawArgs); 081 } else { 082 if (rawArgs.length > 0) { 083 throw new CommandUsageError( 084 messages.tooManyArguments(rawArgs.length, 0)); 085 } 086 args = null; 087 } 088 callCommand(lbl, sender, args); 089 } catch (GlobException exc) { 090 handleGlobException(exc); 091 } catch (CommandUsageError error) { 092 sender.sendMessage(ChatColor.RED + error.getMessage()); 093 return false; 094 } catch (Throwable thr) { 095 sender.sendMessage(ChatColor.RED + thr.getMessage()); 096 } 097 return true; 098 } 099 100 private CommandArgs getArgs(String[] rawArgs){ 101 CommandArgsParser parser = new CommandArgsParser(messages, rawArgs); 102 parser.validate(flags, argsFlags, min, max); 103 return new CommandArgs(messages, parser); 104 } 105 106 private void callCommand(String name, CommandSender sender, 107 CommandArgs args) throws Throwable { 108 try { 109 if (preExecute != null) { 110 preExecute.invoke(instance, sender, args); 111 } 112 if (args != null) { 113 method.invoke(instance, sender, args); 114 } else { 115 method.invoke(instance, sender); 116 } 117 } catch (InvocationTargetException exc) { 118 Throwable cause = exc.getCause(); 119 if (cause instanceof CommandException) { 120 throw cause; 121 } 122 unhandledError(name, args, cause); 123 } catch (IllegalArgumentException exc) { 124 unhandledError(name, args, exc); 125 } catch (IllegalAccessException exc) { 126 unhandledError(name, args, exc); 127 } 128 } 129 130 private void handleGlobException(GlobException exc) { 131 if (exc instanceof UnbalancedSquareBracketException) { 132 UnbalancedSquareBracketException usbExc; 133 usbExc = ((UnbalancedSquareBracketException) exc); 134 throw new CommandUsageError( 135 messages.globUnbalancedSquareBracket(usbExc.getGlob())); 136 } 137 138 throw new RuntimeException(exc); 139 } 140 141 private void unhandledError(String name, CommandArgs args, Throwable exc) { 142 if (!(exc instanceof org.bukkit.command.CommandException)) { 143 Bukkit.getLogger().severe( 144 "Exception occured while executing \""+ name + "\""); 145 if (args != null) { 146 if (args.hasFlags()) { 147 StringBuilder flagsString = new StringBuilder(); 148 for (char flag : args.flags()) { 149 flagsString.append(flag); 150 } 151 Bukkit.getLogger().severe( 152 "Flags : " + flagsString.toString()); 153 } 154 if (args.length() > 0) { 155 StringBuilder arguments = new StringBuilder(); 156 for (String arg : args.asList()) { 157 arguments.append(arg); 158 arguments.append(" "); 159 } 160 Bukkit.getLogger().severe( 161 "Arguments : " + arguments.toString()); 162 } 163 } 164 } 165 Bukkit.getLogger().log(Level.SEVERE, "Exception : ", exc); 166 } 167}