001    package org.bukkit.command;
002    
003    import java.util.List;
004    
005    import org.apache.commons.lang.Validate;
006    import org.bukkit.plugin.Plugin;
007    
008    /**
009     * Represents a {@link Command} belonging to a plugin
010     */
011    public final class PluginCommand extends Command implements PluginIdentifiableCommand {
012        private final Plugin owningPlugin;
013        private CommandExecutor executor;
014        private TabCompleter completer;
015    
016        protected PluginCommand(String name, Plugin owner) {
017            super(name);
018            this.executor = owner;
019            this.owningPlugin = owner;
020            this.usageMessage = "";
021        }
022    
023        /**
024         * Executes the command, returning its success
025         *
026         * @param sender Source object which is executing this command
027         * @param commandLabel The alias of the command used
028         * @param args All arguments passed to the command, split via ' '
029         * @return true if the command was successful, otherwise false
030         */
031        @Override
032        public boolean execute(CommandSender sender, String commandLabel, String[] args) {
033            boolean success = false;
034    
035            if (!owningPlugin.isEnabled()) {
036                return false;
037            }
038    
039            if (!testPermission(sender)) {
040                return true;
041            }
042    
043            try {
044                success = executor.onCommand(sender, this, commandLabel, args);
045            } catch (Throwable ex) {
046                throw new CommandException("Unhandled exception executing command '" + commandLabel + "' in plugin " + owningPlugin.getDescription().getFullName(), ex);
047            }
048    
049            if (!success && usageMessage.length() > 0) {
050                for (String line : usageMessage.replace("<command>", commandLabel).split("\n")) {
051                    sender.sendMessage(line);
052                }
053            }
054    
055            return success;
056        }
057    
058        /**
059         * Sets the {@link CommandExecutor} to run when parsing this command
060         *
061         * @param executor New executor to run
062         */
063        public void setExecutor(CommandExecutor executor) {
064            this.executor = executor == null ? owningPlugin : executor;
065        }
066    
067        /**
068         * Gets the {@link CommandExecutor} associated with this command
069         *
070         * @return CommandExecutor object linked to this command
071         */
072        public CommandExecutor getExecutor() {
073            return executor;
074        }
075    
076        /**
077         * Sets the {@link TabCompleter} to run when tab-completing this command.
078         * <p>
079         * If no TabCompleter is specified, and the command's executor implements
080         * TabCompleter, then the executor will be used for tab completion.
081         *
082         * @param completer New tab completer
083         */
084        public void setTabCompleter(TabCompleter completer) {
085            this.completer = completer;
086        }
087    
088        /**
089         * Gets the {@link TabCompleter} associated with this command.
090         *
091         * @return TabCompleter object linked to this command
092         */
093        public TabCompleter getTabCompleter() {
094            return completer;
095        }
096    
097        /**
098         * Gets the owner of this PluginCommand
099         *
100         * @return Plugin that owns this command
101         */
102        public Plugin getPlugin() {
103            return owningPlugin;
104        }
105    
106        /**
107         * {@inheritDoc}
108         * <p>
109         * Delegates to the tab completer if present.
110         * <p>
111         * If it is not present or returns null, will delegate to the current
112         * command executor if it implements {@link TabCompleter}. If a non-null
113         * list has not been found, will default to standard player name
114         * completion in {@link
115         * Command#tabComplete(CommandSender, String, String[])}.
116         * <p>
117         * This method does not consider permissions.
118         *
119         * @throws CommandException if the completer or executor throw an
120         *     exception during the process of tab-completing.
121         * @throws IllegalArgumentException if sender, alias, or args is null
122         */
123        @Override
124        public java.util.List<String> tabComplete(CommandSender sender, String alias, String[] args) throws CommandException, IllegalArgumentException {
125            Validate.notNull(sender, "Sender cannot be null");
126            Validate.notNull(args, "Arguments cannot be null");
127            Validate.notNull(alias, "Alias cannot be null");
128    
129            List<String> completions = null;
130            try {
131                if (completer != null) {
132                    completions = completer.onTabComplete(sender, this, alias, args);
133                }
134                if (completions == null && executor instanceof TabCompleter) {
135                    completions = ((TabCompleter) executor).onTabComplete(sender, this, alias, args);
136                }
137            } catch (Throwable ex) {
138                StringBuilder message = new StringBuilder();
139                message.append("Unhandled exception during tab completion for command '/").append(alias).append(' ');
140                for (String arg : args) {
141                    message.append(arg).append(' ');
142                }
143                message.deleteCharAt(message.length() - 1).append("' in plugin ").append(owningPlugin.getDescription().getFullName());
144                throw new CommandException(message.toString(), ex);
145            }
146    
147            if (completions == null) {
148                return super.tabComplete(sender, alias, args);
149            }
150            return completions;
151        }
152    
153        @Override
154        public String toString() {
155            StringBuilder stringBuilder = new StringBuilder(super.toString());
156            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
157            stringBuilder.append(", ").append(owningPlugin.getDescription().getFullName()).append(')');
158            return stringBuilder.toString();
159        }
160    }