Overhauled command handling and suggestion support.

This commit is contained in:
sk89q
2014-06-28 16:30:02 -07:00
parent 2258513104
commit 33e1e0b1f1
24 changed files with 536 additions and 224 deletions

View File

@ -25,7 +25,6 @@ import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.InputType;
import com.sk89q.worldedit.event.platform.PlayerInputEvent;
import com.sk89q.worldedit.extension.input.ParserContext;
@ -740,22 +739,6 @@ public class WorldEdit {
return event.isCancelled();
}
/**
*
* @param player
* @param split
* @return whether the command was processed
*/
public boolean handleCommand(Player player, String[] split) {
CommandEvent event = new CommandEvent(player, split);
getEventBus().post(event);
return event.isCancelled();
}
public String[] commandDetection(String[] split) {
return getPlatformManager().getCommandManager().commandDetection(split);
}
/**
* Executes a WorldEdit script.
*

View File

@ -546,8 +546,8 @@ public class UtilityCommands {
if (description.getHelp() != null) {
actor.print(description.getHelp());
} else if (description.getDescription() != null) {
actor.print(description.getDescription());
} else if (description.getShortDescription() != null) {
actor.print(description.getShortDescription());
} else {
actor.print("No further help is available.");
}

View File

@ -30,20 +30,20 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class CommandEvent extends AbstractCancellable {
private final Actor actor;
private final String[] args;
private final String arguments;
/**
* Create a new instance.
*
* @param actor the player
* @param args the arguments
* @param arguments the arguments
*/
public CommandEvent(Actor actor, String[] args) {
public CommandEvent(Actor actor, String arguments) {
checkNotNull(actor);
checkNotNull(args);
checkNotNull(arguments);
this.actor = actor;
this.args = args;
this.arguments = arguments;
}
/**
@ -60,8 +60,8 @@ public class CommandEvent extends AbstractCancellable {
*
* @return the arguments
*/
public String[] getArguments() {
return args;
public String getArguments() {
return arguments;
}
}

View File

@ -0,0 +1,90 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.event.platform;
import com.sk89q.worldedit.event.Event;
import com.sk89q.worldedit.extension.platform.Actor;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Posted when suggestions for auto-completion are requested for command input.
*/
public class CommandSuggestionEvent extends Event {
private final Actor actor;
private final String arguments;
private List<String> suggestions = Collections.emptyList();
/**
* Create a new instance.
*
* @param actor the player
* @param arguments the arguments
*/
public CommandSuggestionEvent(Actor actor, String arguments) {
checkNotNull(actor);
checkNotNull(arguments);
this.actor = actor;
this.arguments = arguments;
}
/**
* Get the actor that issued the command.
*
* @return the actor that issued the command
*/
public Actor getActor() {
return actor;
}
/**
* Get the arguments.
*
* @return the arguments
*/
public String getArguments() {
return arguments;
}
/**
* Get the list of suggestions that are to be presented.
*
* @return the list of suggestions
*/
public List<String> getSuggestions() {
return suggestions;
}
/**
* Set the list of suggestions that are to be presented.
*
* @param suggestions the list of suggestions
*/
public void setSuggestions(List<String> suggestions) {
checkNotNull(suggestions);
this.suggestions = suggestions;
}
}

View File

@ -30,8 +30,9 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.*;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.internal.command.ActorAuthorizer;
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
import com.sk89q.worldedit.internal.command.CommandPermissionsHandler;
import com.sk89q.worldedit.internal.command.WorldEditBinding;
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
import com.sk89q.worldedit.session.request.Request;
@ -87,11 +88,11 @@ public final class CommandManager {
// Set up the commands manager
ParametricBuilder builder = new ParametricBuilder();
builder.setAuthorizer(new ActorAuthorizer());
builder.addBinding(new WorldEditBinding(worldEdit));
builder.attach(new CommandPermissionsHandler());
builder.attach(new WorldEditExceptionConverter(worldEdit));
builder.attach(new LegacyCommandsHandler());
builder.attach(new CommandLoggingHandler(worldEdit, logger));
builder.addExceptionConverter(new WorldEditExceptionConverter(worldEdit));
builder.addInvokeListener(new LegacyCommandsHandler());
builder.addInvokeListener(new CommandLoggingHandler(worldEdit, logger));
dispatcher = new CommandGraph()
.builder(builder)
@ -171,8 +172,6 @@ public final class CommandManager {
}
public String[] commandDetection(String[] split) {
split[0] = split[0].substring(1);
// Quick script shortcut
if (split[0].matches("^[^/].*\\.js$")) {
String[] newSplit = new String[split.length + 1];
@ -185,13 +184,14 @@ public final class CommandManager {
String searchCmd = split[0].toLowerCase();
// Try to detect the command
if (dispatcher.contains(searchCmd)) {
} else if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
split[0] = "/" + split[0];
} else if (split[0].length() >= 2 && split[0].charAt(0) == '/'
&& dispatcher.contains(searchCmd.substring(1))) {
split[0] = split[0].substring(1);
if (!dispatcher.contains(searchCmd)) {
if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
split[0] = "/" + split[0];
} else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && dispatcher.contains(searchCmd.substring(1))) {
split[0] = split[0].substring(1);
}
}
return split;
}
@ -200,7 +200,7 @@ public final class CommandManager {
Request.reset();
Actor actor = platformManager.createProxyActor(event.getActor());
String split[] = commandDetection(event.getArguments());
String split[] = commandDetection(event.getArguments().split(" "));
// No command found!
if (!dispatcher.contains(split[0])) {
@ -216,7 +216,7 @@ public final class CommandManager {
long start = System.currentTimeMillis();
try {
dispatcher.call(Joiner.on(" ").join(split), locals);
dispatcher.call(null, Joiner.on(" ").join(split), locals);
} catch (CommandPermissionsException e) {
actor.printError("You don't have permission to do this.");
} catch (InvalidUsageException e) {
@ -255,6 +255,15 @@ public final class CommandManager {
event.setCancelled(true);
}
@Subscribe
public void handleCommandSuggestion(CommandSuggestionEvent event) {
try {
event.setSuggestions(dispatcher.getSuggestions(event.getArguments()));
} catch (CommandException e) {
event.getActor().printError(e.getMessage());
}
}
/**
* Get the command dispatcher instance.
*

View File

@ -19,23 +19,22 @@
package com.sk89q.worldedit.internal.command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.command.parametric.PermissionsHandler;
import com.sk89q.worldedit.util.auth.Authorizer;
public class CommandPermissionsHandler extends PermissionsHandler {
public CommandPermissionsHandler() {
}
/**
* Implementation of an authorizer that uses {@link Actor#hasPermission(String)}.
*/
public class ActorAuthorizer implements Authorizer {
@Override
protected boolean hasPermission(CommandContext context, String permission) {
Actor sender = context.getLocals().get(Actor.class);
public boolean testPermission(CommandLocals locals, String permission) {
Actor sender = locals.get(Actor.class);
if (sender == null) {
throw new RuntimeException("Uh oh! No 'Actor' specified so that we can check permissions");
} else {
return sender.hasPermission(permission);
}
}
}

View File

@ -0,0 +1,38 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.auth;
import com.sk89q.minecraft.util.commands.CommandLocals;
/**
* Tests whether permission is granted.
*/
public interface Authorizer {
/**
* Tests whether permission is granted for the given context.
*
* @param locals locals
* @param permission the permission string
* @return true if permitted
*/
boolean testPermission(CommandLocals locals, String permission);
}

View File

@ -0,0 +1,35 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.auth;
import com.sk89q.minecraft.util.commands.CommandLocals;
/**
* An implementation of {@link Authorizer} that always returns false for
* tests of permissions.
*/
public class NullAuthorizer implements Authorizer {
@Override
public boolean testPermission(CommandLocals locals, String permission) {
return false;
}
}

View File

@ -22,7 +22,8 @@ package com.sk89q.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import java.util.Collection;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
/**
@ -39,13 +40,17 @@ public interface CommandCallable {
/**
* Execute the correct command based on the input.
* </p>
* The implementing class must perform the necessary permission checks.
*
* @param alias the alias that was used to invoke this command,
* which may be null if this is a "root" command
* @param arguments the arguments
* @param locals the locals
* @return the called command, or null if there was no command found
* @throws CommandException thrown on a command error
*/
boolean call(String arguments, CommandLocals locals) throws CommandException;
boolean call(@Nullable String alias, String arguments, CommandLocals locals) throws CommandException;
/**
* Get a list of suggestions based on input.
@ -54,7 +59,7 @@ public interface CommandCallable {
* @return a list of suggestions
* @throws CommandException thrown if there was a parsing error
*/
Collection<String> getSuggestions(String arguments) throws CommandException;
List<String> getSuggestions(String arguments) throws CommandException;
/**
* Get an object describing this command.
@ -63,4 +68,12 @@ public interface CommandCallable {
*/
Description getDescription();
/**
* Test whether this command can be executed with the given context.
*
* @param locals the locals
* @return true if execution is permitted
*/
boolean testPermission(CommandLocals locals);
}

View File

@ -38,7 +38,7 @@ public interface Description {
*
* @return a description, or null if no description is available
*/
String getDescription();
String getShortDescription();
/**
* Get a longer help text about this command.

View File

@ -49,7 +49,7 @@ public class SimpleDescription implements Description {
}
@Override
public String getDescription() {
public String getShortDescription() {
return description;
}
@ -57,7 +57,7 @@ public class SimpleDescription implements Description {
* Set the description of the command.
*
* @param description the description
* @see #getDescription()
* @see #getShortDescription()
*/
public void setDescription(String description) {
this.description = description;

View File

@ -25,6 +25,7 @@ import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import javax.annotation.Nullable;
import java.util.*;
/**
@ -89,20 +90,20 @@ public class SimpleDispatcher implements Dispatcher {
}
@Override
public boolean call(String arguments, CommandLocals locals) throws CommandException {
public boolean call(@Nullable String alias, String arguments, CommandLocals locals) throws CommandException {
String[] split = CommandContext.split(arguments);
Set<String> aliases = getPrimaryAliases();
if (aliases.isEmpty()) {
throw new InvalidUsageException("This command has no sub-commands.", getDescription());
} else if (split.length != 0) {
} else if (split.length > 0) {
String subCommand = split[0];
String subArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length));
CommandMapping mapping = get(subCommand);
String passedArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length));
if (mapping != null) {
try {
mapping.getCallable().call(passedArguments, locals);
mapping.getCallable().call(subCommand, subArguments, locals);
} catch (CommandException e) {
e.prependStack(subCommand);
throw e;
@ -119,22 +120,26 @@ public class SimpleDispatcher implements Dispatcher {
}
@Override
public Collection<String> getSuggestions(String arguments) throws CommandException {
public List<String> getSuggestions(String arguments) throws CommandException {
String[] split = CommandContext.split(arguments);
if (split.length == 0) {
return getAllAliases();
return new ArrayList<String>(getAllAliases());
} else if (split.length == 1) {
String prefix = split[0];
List<String> suggestions = new ArrayList<String>();
if (!prefix.isEmpty()) {
List<String> suggestions = new ArrayList<String>();
for (String alias : getAllAliases()) {
if (alias.startsWith(prefix)) {
suggestions.add(alias);
for (String alias : getAllAliases()) {
if (alias.startsWith(prefix)) {
suggestions.add(alias);
}
}
}
return suggestions;
return suggestions;
} else {
return new ArrayList<String>(getAllAliases());
}
} else {
String subCommand = split[0];
CommandMapping mapping = get(subCommand);
@ -153,6 +158,17 @@ public class SimpleDispatcher implements Dispatcher {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
for (CommandMapping mapping : getCommands()) {
if (mapping.getCallable().testPermission(locals)) {
return true;
}
}
return false;
}
/**
* Get a list of subcommands for display.
*

View File

@ -79,14 +79,14 @@ public class DispatcherNode {
*
* @param object the object provided to the {@link ParametricBuilder}
* @return this object
* @see ParametricBuilder#register(com.sk89q.worldedit.util.command.Dispatcher, Object)
* @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object)
*/
public DispatcherNode build(Object object) {
ParametricBuilder builder = graph.getBuilder();
if (builder == null) {
throw new RuntimeException("No ParametricBuilder set");
}
builder.register(getDispatcher(), object);
builder.registerMethodsAsCommands(getDispatcher(), object);
return this;
}

View File

@ -24,6 +24,8 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.util.auth.Authorizer;
import com.sk89q.worldedit.util.auth.NullAuthorizer;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
@ -39,6 +41,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Creates commands using annotations placed on methods and individual parameters of
* such methods.
@ -52,6 +56,7 @@ public class ParametricBuilder {
private final Paranamer paranamer = new CachingParanamer();
private final List<InvokeListener> invokeListeners = new ArrayList<InvokeListener>();
private final List<ExceptionConverter> exceptionConverters = new ArrayList<ExceptionConverter>();
private Authorizer authorizer = new NullAuthorizer();
/**
* Create a new builder.
@ -115,7 +120,7 @@ public class ParametricBuilder {
* @param listener the listener
* @see InvokeHandler the handler
*/
public void attach(InvokeListener listener) {
public void addInvokeListener(InvokeListener listener) {
invokeListeners.add(listener);
}
@ -128,7 +133,7 @@ public class ParametricBuilder {
* @param converter the converter
* @see ExceptionConverter for an explanation
*/
public void attach(ExceptionConverter converter) {
public void addExceptionConverter(ExceptionConverter converter) {
exceptionConverters.add(converter);
}
@ -141,7 +146,7 @@ public class ParametricBuilder {
* @param object the object contain the methods
* @throws ParametricException thrown if the commands cannot be registered
*/
public void register(Dispatcher dispatcher, Object object) throws ParametricException {
public void registerMethodsAsCommands(Dispatcher dispatcher, Object object) throws ParametricException {
for (Method method : object.getClass().getDeclaredMethods()) {
Command definition = method.getAnnotation(Command.class);
if (definition != null) {
@ -201,5 +206,23 @@ public class ParametricBuilder {
List<ExceptionConverter> getExceptionConverters() {
return exceptionConverters;
}
/**
* Get the authorizer.
*
* @return the authorizer
*/
public Authorizer getAuthorizer() {
return authorizer;
}
/**
* Set the authorizer.
*
* @param authorizer the authorizer
*/
public void setAuthorizer(Authorizer authorizer) {
checkNotNull(authorizer);
this.authorizer = authorizer;
}
}

View File

@ -23,6 +23,7 @@ import com.sk89q.minecraft.util.commands.*;
import com.sk89q.worldedit.util.command.*;
import com.sk89q.worldedit.util.command.binding.Switch;
import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -40,6 +41,7 @@ class ParametricCallable implements CommandCallable {
private final ParameterData[] parameters;
private final Set<Character> valueFlags = new HashSet<Character>();
private final SimpleDescription description = new SimpleDescription();
private final CommandPermissions commandPermissions;
/**
* Create a new instance.
@ -50,11 +52,7 @@ class ParametricCallable implements CommandCallable {
* @param definition the command definition annotation
* @throws ParametricException thrown on an error
*/
ParametricCallable(
ParametricBuilder builder,
Object object, Method method,
Command definition) throws ParametricException {
ParametricCallable(ParametricBuilder builder, Object object, Method method, Command definition) throws ParametricException {
this.builder = builder;
this.object = object;
this.method = method;
@ -101,8 +99,7 @@ class ParametricCallable implements CommandCallable {
}
}
parameter.setName(names.length > 0 ?
names[i] : generateName(type, parameter.getClassifier(), i));
parameter.setName(names.length > 0 ? names[i] : generateName(type, parameter.getClassifier(), i));
// Track all value flags
if (parameter.isValueFlag()) {
@ -115,9 +112,7 @@ class ParametricCallable implements CommandCallable {
// Don't know how to parse for this type of value
if (parameter.getBinding() == null) {
throw new ParametricException(
"Don't know how to handle the parameter type '" + type + "' in\n" +
method.toGenericString());
throw new ParametricException("Don't know how to handle the parameter type '" + type + "' in\n" + method.toGenericString());
}
}
@ -159,11 +154,19 @@ class ParametricCallable implements CommandCallable {
// Set parameters
description.setParameters(userParameters);
// Get permissions annotation
commandPermissions = method.getAnnotation(CommandPermissions.class);
}
@Override
public boolean call(String stringArguments, CommandLocals locals) throws CommandException {
String[] split = CommandContext.split(stringArguments);
public boolean call(@Nullable String alias, String stringArguments, CommandLocals locals) throws CommandException {
// Test permission
if (!testPermission(locals)) {
throw new CommandPermissionsException();
}
String[] split = CommandContext.split(alias + " " + stringArguments);
CommandContext context = new CommandContext(split, getValueFlags(), false, locals);
Object[] args = new Object[parameters.length];
@ -218,12 +221,9 @@ class ParametricCallable implements CommandCallable {
handler.postInvoke(handler, method, parameters, args, context);
}
} catch (MissingParameterException e) {
throw new InvalidUsageException(
"Too few parameters!", getDescription());
throw new InvalidUsageException("Too few parameters!", getDescription());
} catch (UnconsumedParameterException e) {
throw new InvalidUsageException(
"Too many parameters! Unused parameters: "
+ e.getUnconsumed(), getDescription());
throw new InvalidUsageException("Too many parameters! Unused parameters: " + e.getUnconsumed(), getDescription());
} catch (ParameterException e) {
if (e.getCause() != null) {
for (ExceptionConverter converter : builder.getExceptionConverters()) {
@ -231,10 +231,10 @@ class ParametricCallable implements CommandCallable {
}
}
assert parameter != null;
String name = parameter.getName();
throw new InvalidUsageException("For parameter '" + name + "': "
+ e.getMessage(), getDescription());
throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), getDescription());
} catch (InvocationTargetException e) {
for (ExceptionConverter converter : builder.getExceptionConverters()) {
converter.convert(e.getCause());
@ -252,7 +252,7 @@ class ParametricCallable implements CommandCallable {
}
@Override
public Collection<String> getSuggestions(String stringArguments) throws CommandException {
public List<String> getSuggestions(String stringArguments) throws CommandException {
String[] split = CommandContext.split(stringArguments);
CommandContext context = new CommandContext(split, getValueFlags());
@ -281,13 +281,11 @@ class ParametricCallable implements CommandCallable {
ParameterData lastConsumer = null;
String lastConsumed = null;
for (int i = 0; i < parameters.length; i++) {
ParameterData parameter = parameters[i];
for (ParameterData parameter : parameters) {
if (parameter.getFlag() != null) {
continue; // We already handled flags
}
try {
scoped.mark();
parameter.getBinding().bind(parameter, scoped, true);
@ -306,8 +304,8 @@ class ParametricCallable implements CommandCallable {
if (lastConsumer != null) {
return lastConsumer.getBinding()
.getSuggestions(lastConsumer, lastConsumed);
// For /command| value1 value2
// This should never occur
// For /command| value1 value2
// This should never occur
} else {
throw new RuntimeException("Invalid suggestion context");
}
@ -352,7 +350,22 @@ class ParametricCallable implements CommandCallable {
public SimpleDescription getDescription() {
return description;
}
@Override
public boolean testPermission(CommandLocals locals) {
if (commandPermissions != null) {
for (String perm : commandPermissions.value()) {
if (builder.getAuthorizer().testPermission(locals, perm)) {
return true;
}
}
return false;
} else {
return true;
}
}
/**
* Get the right {@link ArgumentStack}.
*

View File

@ -1,67 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.command.parametric;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import java.lang.reflect.Method;
/**
* A handler for the {@link CommandPermissions} annotation.
*/
public abstract class PermissionsHandler extends AbstractInvokeListener implements InvokeHandler {
@Override
public InvokeHandler createInvokeHandler() {
return this;
}
@Override
public void preProcess(Object object, Method method,
ParameterData[] parameters, CommandContext context)
throws CommandException, ParameterException {
CommandPermissions annotation = method.getAnnotation(CommandPermissions.class);
if (annotation != null) {
for (String perm : annotation.value()) {
if (hasPermission(context, perm)) {
return;
}
}
throw new CommandPermissionsException();
}
}
@Override
public void preInvoke(Object object, Method method, ParameterData[] parameters,
Object[] args, CommandContext context) throws CommandException {
}
@Override
public void postInvoke(Object object, Method method, ParameterData[] parameters,
Object[] args, CommandContext context) throws CommandException {
}
protected abstract boolean hasPermission(CommandContext context, String permission);
}