From a091853385cdd97eb0dfb3d643d0f99440a02f3a Mon Sep 17 00:00:00 2001 From: Wyatt Childers Date: Tue, 28 Jun 2016 19:36:34 -0400 Subject: [PATCH] Made the CommandManager responsible for exception converters as apposed to individual dispatchers Previously some exceptions were being handled only in the ParametricCallable, which lead to other dispatchers throwing the exception, and requesting that users report them. Fixes WORLDEDIT-3386 --- .../extension/platform/CommandManager.java | 51 ++++++++----------- .../util/command/fluent/DispatcherNode.java | 2 +- .../command/parametric/ParametricBuilder.java | 23 --------- .../parametric/ParametricCallable.java | 34 ++----------- 4 files changed, 26 insertions(+), 84 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 046d2202a..3a39c47e9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -28,41 +28,15 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.BiomeCommands; -import com.sk89q.worldedit.command.BrushCommands; -import com.sk89q.worldedit.command.ChunkCommands; -import com.sk89q.worldedit.command.ClipboardCommands; -import com.sk89q.worldedit.command.GeneralCommands; -import com.sk89q.worldedit.command.GenerationCommands; -import com.sk89q.worldedit.command.HistoryCommands; -import com.sk89q.worldedit.command.NavigationCommands; -import com.sk89q.worldedit.command.RegionCommands; -import com.sk89q.worldedit.command.SchematicCommands; -import com.sk89q.worldedit.command.ScriptingCommands; -import com.sk89q.worldedit.command.SelectionCommands; -import com.sk89q.worldedit.command.SnapshotCommands; -import com.sk89q.worldedit.command.SnapshotUtilCommands; -import com.sk89q.worldedit.command.SuperPickaxeCommands; -import com.sk89q.worldedit.command.ToolCommands; -import com.sk89q.worldedit.command.ToolUtilCommands; -import com.sk89q.worldedit.command.UtilityCommands; -import com.sk89q.worldedit.command.WorldEditCommands; +import com.sk89q.worldedit.command.*; import com.sk89q.worldedit.command.argument.ReplaceParser; import com.sk89q.worldedit.command.argument.TreeGeneratorParser; -import com.sk89q.worldedit.command.composition.ApplyCommand; -import com.sk89q.worldedit.command.composition.DeformCommand; -import com.sk89q.worldedit.command.composition.PaintCommand; -import com.sk89q.worldedit.command.composition.SelectionCommand; -import com.sk89q.worldedit.command.composition.ShapedBrushCommand; +import com.sk89q.worldedit.command.composition.*; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.function.factory.Deform; import com.sk89q.worldedit.function.factory.Deform.Mode; -import com.sk89q.worldedit.internal.command.ActorAuthorizer; -import com.sk89q.worldedit.internal.command.CommandLoggingHandler; -import com.sk89q.worldedit.internal.command.UserCommandCompleter; -import com.sk89q.worldedit.internal.command.WorldEditBinding; -import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; +import com.sk89q.worldedit.internal.command.*; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.InvalidUsageException; @@ -129,7 +103,6 @@ public final class CommandManager { builder.setAuthorizer(new ActorAuthorizer()); builder.setDefaultCompleter(new UserCommandCompleter(platformManager)); builder.addBinding(new WorldEditBinding(worldEdit)); - builder.addExceptionConverter(exceptionConverter); builder.addInvokeListener(new LegacyCommandsHandler()); builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog)); @@ -267,7 +240,23 @@ public final class CommandManager { long start = System.currentTimeMillis(); try { - dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]); + // This is a bit of a hack, since the call method can only throw CommandExceptions + // everything needs to be wrapped at least once. Which means to handle all WorldEdit + // exceptions without writing a hook into every dispatcher, we need to unwrap these + // exceptions and rethrow their converted form, if their is one. + try { + dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]); + } catch (Throwable t) { + // Use the exception converter to convert the exception if any of its causes + // can be converted, otherwise throw the original exception + Throwable next = t; + do { + exceptionConverter.convert(next); + next = next.getCause(); + } while (next != null); + + throw t; + } } catch (CommandPermissionsException e) { actor.printError("You are not permitted to do that. Are you in the right mode?"); } catch (InvalidUsageException e) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java index ce029b556..8bcbbfe85 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java @@ -68,7 +68,7 @@ public class DispatcherNode { * @param alias the list of aliases, where the first alias is the primary one */ public DispatcherNode register(CommandCallable callable, String... alias) { - dispatcher.registerCommand(callable, alias);; + dispatcher.registerCommand(callable, alias); return this; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java index 822826fed..b02178874 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java @@ -57,7 +57,6 @@ public class ParametricBuilder { private final Map bindings = new HashMap(); private final Paranamer paranamer = new CachingParanamer(); private final List invokeListeners = new ArrayList(); - private final List exceptionConverters = new ArrayList(); private Authorizer authorizer = new NullAuthorizer(); private CommandCompleter defaultCompleter = new NullCompleter(); @@ -126,19 +125,6 @@ public class ParametricBuilder { public void addInvokeListener(InvokeListener listener) { invokeListeners.add(listener); } - - /** - * Attach an exception converter to this builder in order to wrap unknown - * {@link Throwable}s into known {@link CommandException}s. - * - *

Exception converters are called in order that they are registered.

- * - * @param converter the converter - * @see ExceptionConverter for an explanation - */ - public void addExceptionConverter(ExceptionConverter converter) { - exceptionConverters.add(converter); - } /** * Build a list of commands from methods specially annotated with {@link Command} @@ -201,15 +187,6 @@ public class ParametricBuilder { return invokeListeners; } - /** - * Get the list of exception converters. - * - * @return a list of exception converters - */ - List getExceptionConverters() { - return exceptionConverters; - } - /** * Get the authorizer. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java index ea3bd0548..1c65de6c5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java @@ -20,30 +20,15 @@ package com.sk89q.worldedit.util.command.parametric; import com.google.common.primitives.Chars; -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.CommandLocals; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.CommandPermissionsException; -import com.sk89q.minecraft.util.commands.WrappedCommandException; -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.InvalidUsageException; -import com.sk89q.worldedit.util.command.MissingParameterException; -import com.sk89q.worldedit.util.command.Parameter; -import com.sk89q.worldedit.util.command.SimpleDescription; -import com.sk89q.worldedit.util.command.UnconsumedParameterException; +import com.sk89q.minecraft.util.commands.*; +import com.sk89q.worldedit.util.command.*; import com.sk89q.worldedit.util.command.binding.Switch; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * The implementation of a {@link CommandCallable} for the {@link ParametricBuilder}. @@ -255,17 +240,8 @@ class ParametricCallable implements CommandCallable { String name = parameter.getName(); throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this); - } catch (InvocationTargetException e) { - for (ExceptionConverter converter : builder.getExceptionConverters()) { - converter.convert(e.getCause()); - } - throw new WrappedCommandException(e); - } catch (IllegalArgumentException e) { - throw new WrappedCommandException(e); - } catch (CommandException e) { - throw e; - } catch (Throwable e) { - throw new WrappedCommandException(e); + } catch (Throwable t) { + throw new WrappedCommandException(t); } return true;