mirror of
https://github.com/PaperMC/Waterfall.git
synced 2024-11-24 19:25:16 +01:00
2cab85cbef
This patch was heavily intented to fix a server side issue which is generally no longer relevant, not to mention the cost of interning only cements this patch into it's grave
700 lines
29 KiB
Diff
700 lines
29 KiB
Diff
From 7a399e781d556697922a04ff6fd85ca5a5484d4b Mon Sep 17 00:00:00 2001
|
|
From: theminecoder <theminecoder.dev@gmail.com>
|
|
Date: Wed, 22 Apr 2020 14:00:44 +1000
|
|
Subject: [PATCH] Add exception reporting event
|
|
|
|
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/event/ProxyExceptionEvent.java b/api/src/main/java/io/github/waterfallmc/waterfall/event/ProxyExceptionEvent.java
|
|
new file mode 100644
|
|
index 00000000..ee6cb5dd
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/event/ProxyExceptionEvent.java
|
|
@@ -0,0 +1,27 @@
|
|
+package io.github.waterfallmc.waterfall.event;
|
|
+
|
|
+import com.google.common.base.Preconditions;
|
|
+import io.github.waterfallmc.waterfall.exception.ProxyException;
|
|
+import net.md_5.bungee.api.plugin.Event;
|
|
+
|
|
+/**
|
|
+ * Called whenever an exception is thrown in a recoverable section of the server.
|
|
+ */
|
|
+public class ProxyExceptionEvent extends Event {
|
|
+
|
|
+ private ProxyException exception;
|
|
+
|
|
+ public ProxyExceptionEvent(ProxyException exception) {
|
|
+ this.exception = Preconditions.checkNotNull(exception, "exception");
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the wrapped exception that was thrown.
|
|
+ *
|
|
+ * @return Exception thrown
|
|
+ */
|
|
+ public ProxyException getException() {
|
|
+ return exception;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyCommandException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyCommandException.java
|
|
new file mode 100644
|
|
index 00000000..644a4cd6
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyCommandException.java
|
|
@@ -0,0 +1,64 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.CommandSender;
|
|
+import net.md_5.bungee.api.plugin.Command;
|
|
+
|
|
+import static com.google.common.base.Preconditions.checkNotNull;
|
|
+
|
|
+/**
|
|
+ * Thrown when a command throws an exception
|
|
+ */
|
|
+public class ProxyCommandException extends ProxyException {
|
|
+
|
|
+ private final Command command;
|
|
+ private final CommandSender commandSender;
|
|
+ private final String[] arguments;
|
|
+
|
|
+ public ProxyCommandException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
|
+ super(message, cause);
|
|
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
|
+ this.arguments = checkNotNull(arguments, "arguments");
|
|
+ this.command = checkNotNull(command, "command");
|
|
+ }
|
|
+
|
|
+ public ProxyCommandException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
|
+ super(cause);
|
|
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
|
+ this.arguments = checkNotNull(arguments, "arguments");
|
|
+ this.command = checkNotNull(command, "command");
|
|
+ }
|
|
+
|
|
+ protected ProxyCommandException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace);
|
|
+ this.commandSender = checkNotNull(commandSender, "commandSender");
|
|
+ this.arguments = checkNotNull(arguments, "arguments");
|
|
+ this.command = checkNotNull(command, "command");
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the command which threw the exception
|
|
+ *
|
|
+ * @return exception throwing command
|
|
+ */
|
|
+ public Command getCommand() {
|
|
+ return command;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the command sender which executed the command request
|
|
+ *
|
|
+ * @return command sender of exception thrown command request
|
|
+ */
|
|
+ public CommandSender getCommandSender() {
|
|
+ return commandSender;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the arguments which threw the exception for the command
|
|
+ *
|
|
+ * @return arguments of exception thrown command request
|
|
+ */
|
|
+ public String[] getArguments() {
|
|
+ return arguments;
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyEventException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyEventException.java
|
|
new file mode 100644
|
|
index 00000000..b9842dc5
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyEventException.java
|
|
@@ -0,0 +1,53 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.plugin.Event;
|
|
+import net.md_5.bungee.api.plugin.Listener;
|
|
+
|
|
+import static com.google.common.base.Preconditions.checkNotNull;
|
|
+
|
|
+/**
|
|
+ * Exception thrown when a server event listener throws an exception
|
|
+ */
|
|
+//TODO Find a better way to retrieve the plugin for this. Currently the event register/bake process
|
|
+// doesnt leave a reference to the plugin so there's no way to know what one is being used at any given time
|
|
+public class ProxyEventException extends ProxyException {
|
|
+
|
|
+ private final Listener listener;
|
|
+ private final Event event;
|
|
+
|
|
+ public ProxyEventException(String message, Throwable cause, Listener listener, Event event) {
|
|
+ super(message, cause);
|
|
+ this.listener = checkNotNull(listener, "listener");
|
|
+ this.event = checkNotNull(event, "event");
|
|
+ }
|
|
+
|
|
+ public ProxyEventException(Throwable cause, Listener listener, Event event) {
|
|
+ super(cause);
|
|
+ this.listener = checkNotNull(listener, "listener");
|
|
+ this.event = checkNotNull(event, "event");
|
|
+ }
|
|
+
|
|
+ protected ProxyEventException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Listener listener, Event event) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace);
|
|
+ this.listener = checkNotNull(listener, "listener");
|
|
+ this.event = checkNotNull(event, "event");
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the listener which threw the exception
|
|
+ *
|
|
+ * @return event listener
|
|
+ */
|
|
+ public Listener getListener() {
|
|
+ return listener;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the event which caused the exception
|
|
+ *
|
|
+ * @return event
|
|
+ */
|
|
+ public Event getEvent() {
|
|
+ return event;
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyException.java
|
|
new file mode 100644
|
|
index 00000000..b9fbbbe8
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyException.java
|
|
@@ -0,0 +1,23 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+/**
|
|
+ * Wrapper exception for all exceptions that are thrown by the server.
|
|
+ */
|
|
+public class ProxyException extends Exception {
|
|
+
|
|
+ public ProxyException(String message) {
|
|
+ super(message);
|
|
+ }
|
|
+
|
|
+ public ProxyException(String message, Throwable cause) {
|
|
+ super(message, cause);
|
|
+ }
|
|
+
|
|
+ public ProxyException(Throwable cause) {
|
|
+ super(cause);
|
|
+ }
|
|
+
|
|
+ protected ProxyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace);
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyInternalException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyInternalException.java
|
|
new file mode 100644
|
|
index 00000000..acc64c29
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyInternalException.java
|
|
@@ -0,0 +1,34 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import io.github.waterfallmc.waterfall.event.ProxyExceptionEvent;
|
|
+import net.md_5.bungee.api.ProxyServer;
|
|
+
|
|
+/**
|
|
+ * Thrown when the internal server throws a recoverable exception.
|
|
+ */
|
|
+public class ProxyInternalException extends ProxyException {
|
|
+
|
|
+ public ProxyInternalException(String message) {
|
|
+ super(message);
|
|
+ }
|
|
+
|
|
+ public ProxyInternalException(String message, Throwable cause) {
|
|
+ super(message, cause);
|
|
+ }
|
|
+
|
|
+ public ProxyInternalException(Throwable cause) {
|
|
+ super(cause);
|
|
+ }
|
|
+
|
|
+ protected ProxyInternalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace);
|
|
+ }
|
|
+
|
|
+ public static void reportInternalException(Throwable cause) {
|
|
+ try {
|
|
+ ProxyServer.getInstance().getPluginManager().callEvent(new ProxyExceptionEvent(new ProxyInternalException(cause)));;
|
|
+ } catch (Throwable t) {
|
|
+ t.printStackTrace(); // Don't want to rethrow!
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginEnableDisableException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginEnableDisableException.java
|
|
new file mode 100644
|
|
index 00000000..54dc7da0
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginEnableDisableException.java
|
|
@@ -0,0 +1,20 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.plugin.Plugin;
|
|
+
|
|
+/**
|
|
+ * Thrown whenever there is an exception with any enabling or disabling of plugins.
|
|
+ */
|
|
+public class ProxyPluginEnableDisableException extends ProxyPluginException {
|
|
+ public ProxyPluginEnableDisableException(String message, Throwable cause, Plugin responsiblePlugin) {
|
|
+ super(message, cause, responsiblePlugin);
|
|
+ }
|
|
+
|
|
+ public ProxyPluginEnableDisableException(Throwable cause, Plugin responsiblePlugin) {
|
|
+ super(cause, responsiblePlugin);
|
|
+ }
|
|
+
|
|
+ protected ProxyPluginEnableDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginException.java
|
|
new file mode 100644
|
|
index 00000000..b0de7a4b
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginException.java
|
|
@@ -0,0 +1,36 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.plugin.Plugin;
|
|
+
|
|
+import static com.google.common.base.Preconditions.checkNotNull;
|
|
+
|
|
+/**
|
|
+ * Wrapper exception for all cases to which a plugin can be immediately blamed for
|
|
+ */
|
|
+public class ProxyPluginException extends ProxyException {
|
|
+ public ProxyPluginException(String message, Throwable cause, Plugin responsiblePlugin) {
|
|
+ super(message, cause);
|
|
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
|
+ }
|
|
+
|
|
+ public ProxyPluginException(Throwable cause, Plugin responsiblePlugin) {
|
|
+ super(cause);
|
|
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
|
+ }
|
|
+
|
|
+ protected ProxyPluginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace);
|
|
+ this.responsiblePlugin = checkNotNull(responsiblePlugin, "responsiblePlugin");
|
|
+ }
|
|
+
|
|
+ private final Plugin responsiblePlugin;
|
|
+
|
|
+ /**
|
|
+ * Gets the plugin which is directly responsible for the exception being thrown
|
|
+ *
|
|
+ * @return plugin which is responsible for the exception throw
|
|
+ */
|
|
+ public Plugin getResponsiblePlugin() {
|
|
+ return responsiblePlugin;
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginMessageException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginMessageException.java
|
|
new file mode 100644
|
|
index 00000000..9e24e09c
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyPluginMessageException.java
|
|
@@ -0,0 +1,64 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
+import net.md_5.bungee.api.plugin.Plugin;
|
|
+
|
|
+import static com.google.common.base.Preconditions.checkNotNull;
|
|
+
|
|
+/**
|
|
+ * Thrown when an incoming plugin message channel throws an exception
|
|
+ */
|
|
+public class ProxyPluginMessageException extends ProxyPluginException {
|
|
+
|
|
+ private final ProxiedPlayer player;
|
|
+ private final String channel;
|
|
+ private final byte[] data;
|
|
+
|
|
+ public ProxyPluginMessageException(String message, Throwable cause, Plugin responsiblePlugin, ProxiedPlayer player, String channel, byte[] data) {
|
|
+ super(message, cause, responsiblePlugin);
|
|
+ this.player = checkNotNull(player, "player");
|
|
+ this.channel = checkNotNull(channel, "channel");
|
|
+ this.data = checkNotNull(data, "data");
|
|
+ }
|
|
+
|
|
+ public ProxyPluginMessageException(Throwable cause, Plugin responsiblePlugin, ProxiedPlayer player, String channel, byte[] data) {
|
|
+ super(cause, responsiblePlugin);
|
|
+ this.player = checkNotNull(player, "player");
|
|
+ this.channel = checkNotNull(channel, "channel");
|
|
+ this.data = checkNotNull(data, "data");
|
|
+ }
|
|
+
|
|
+ protected ProxyPluginMessageException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Plugin responsiblePlugin, ProxiedPlayer player, String channel, byte[] data) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace, responsiblePlugin);
|
|
+ this.player = checkNotNull(player, "player");
|
|
+ this.channel = checkNotNull(channel, "channel");
|
|
+ this.data = checkNotNull(data, "data");
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the channel to which the error occurred from recieving data from
|
|
+ *
|
|
+ * @return exception channel
|
|
+ */
|
|
+ public String getChannel() {
|
|
+ return channel;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the data to which the error occurred from
|
|
+ *
|
|
+ * @return exception data
|
|
+ */
|
|
+ public byte[] getData() {
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the player which the plugin message causing the exception originated from
|
|
+ *
|
|
+ * @return exception player
|
|
+ */
|
|
+ public ProxiedPlayer getPlayer() {
|
|
+ return player;
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxySchedulerException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxySchedulerException.java
|
|
new file mode 100644
|
|
index 00000000..0d574ecc
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxySchedulerException.java
|
|
@@ -0,0 +1,37 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.scheduler.ScheduledTask;
|
|
+
|
|
+import static com.google.common.base.Preconditions.checkNotNull;
|
|
+
|
|
+/**
|
|
+ * Thrown when a plugin's scheduler fails with an exception
|
|
+ */
|
|
+public class ProxySchedulerException extends ProxyPluginException {
|
|
+
|
|
+ private final ScheduledTask task;
|
|
+
|
|
+ public ProxySchedulerException(String message, Throwable cause, ScheduledTask task) {
|
|
+ super(message, cause, task.getOwner());
|
|
+ this.task = checkNotNull(task, "task");
|
|
+ }
|
|
+
|
|
+ public ProxySchedulerException(Throwable cause, ScheduledTask task) {
|
|
+ super(cause, task.getOwner());
|
|
+ this.task = checkNotNull(task, "task");
|
|
+ }
|
|
+
|
|
+ protected ProxySchedulerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, ScheduledTask task) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace, task.getOwner());
|
|
+ this.task = checkNotNull(task, "task");
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the task which threw the exception
|
|
+ *
|
|
+ * @return exception throwing task
|
|
+ */
|
|
+ public ScheduledTask getTask() {
|
|
+ return task;
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyTabCompleteException.java b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyTabCompleteException.java
|
|
new file mode 100644
|
|
index 00000000..5bf57ec1
|
|
--- /dev/null
|
|
+++ b/api/src/main/java/io/github/waterfallmc/waterfall/exception/ProxyTabCompleteException.java
|
|
@@ -0,0 +1,22 @@
|
|
+package io.github.waterfallmc.waterfall.exception;
|
|
+
|
|
+import net.md_5.bungee.api.CommandSender;
|
|
+import net.md_5.bungee.api.plugin.Command;
|
|
+
|
|
+/**
|
|
+ * Called when a tab-complete request throws an exception
|
|
+ */
|
|
+public class ProxyTabCompleteException extends ProxyCommandException {
|
|
+
|
|
+ public ProxyTabCompleteException(String message, Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
|
+ super(message, cause, command, commandSender, arguments);
|
|
+ }
|
|
+
|
|
+ public ProxyTabCompleteException(Throwable cause, Command command, CommandSender commandSender, String[] arguments) {
|
|
+ super(cause, command, commandSender, arguments);
|
|
+ }
|
|
+
|
|
+ protected ProxyTabCompleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Command command, CommandSender commandSender, String[] arguments) {
|
|
+ super(message, cause, enableSuppression, writableStackTrace, command, commandSender, arguments);
|
|
+ }
|
|
+}
|
|
diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
|
|
index 70d3736b..431d4d6f 100644
|
|
--- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
|
|
+++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
|
|
@@ -24,6 +24,11 @@ import java.util.Stack;
|
|
import java.util.jar.JarEntry;
|
|
import java.util.jar.JarFile;
|
|
import java.util.logging.Level;
|
|
+import io.github.waterfallmc.waterfall.event.ProxyExceptionEvent; // Waterfall
|
|
+import io.github.waterfallmc.waterfall.exception.ProxyCommandException; // Waterfall
|
|
+import io.github.waterfallmc.waterfall.exception.ProxyEventException; // Waterfall
|
|
+import io.github.waterfallmc.waterfall.exception.ProxyPluginEnableDisableException; // Waterfall
|
|
+import io.github.waterfallmc.waterfall.exception.ProxyTabCompleteException; // Waterfall
|
|
import lombok.RequiredArgsConstructor;
|
|
import net.md_5.bungee.api.ChatColor;
|
|
import net.md_5.bungee.api.CommandSender;
|
|
@@ -31,6 +36,7 @@ import net.md_5.bungee.api.ProxyServer;
|
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
import net.md_5.bungee.event.EventBus;
|
|
import net.md_5.bungee.event.EventHandler;
|
|
+import net.md_5.bungee.event.EventHandlerMethod; //Waterfall - Exception event
|
|
import org.yaml.snakeyaml.Yaml;
|
|
import org.yaml.snakeyaml.constructor.Constructor;
|
|
import org.yaml.snakeyaml.introspector.PropertyUtils;
|
|
@@ -178,10 +184,9 @@ public final class PluginManager
|
|
}
|
|
|
|
String[] args = Arrays.copyOfRange( split, 1, split.length );
|
|
- try
|
|
- {
|
|
if ( tabResults == null )
|
|
{
|
|
+ try { // Waterfall - split command & tab complete exception handlers for exception event
|
|
if ( proxy.getConfig().isLogCommands() )
|
|
{
|
|
proxy.getLogger().log( Level.INFO, "{0} executed command: /{1}", new Object[]
|
|
@@ -190,18 +195,28 @@ public final class PluginManager
|
|
} );
|
|
}
|
|
command.execute( sender, args );
|
|
+ // Waterfall start - split command & tab complete exception handlers for exception event
|
|
+ } catch ( Exception ex ) {
|
|
+ sender.sendMessage( ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details." );
|
|
+ ProxyServer.getInstance().getLogger().log( Level.WARNING, "Error in dispatching command", ex );
|
|
+ this.callEvent( new ProxyExceptionEvent( new ProxyCommandException( ex, command, sender, args ) ) ); //Waterfall - throw error event
|
|
+ }
|
|
+ // Waterfall end
|
|
} else if ( commandLine.contains( " " ) && command instanceof TabExecutor )
|
|
{
|
|
+ try { // Waterfall - split command & tab complete exception handlers for exception event
|
|
for ( String s : ( (TabExecutor) command ).onTabComplete( sender, args ) )
|
|
{
|
|
tabResults.add( s );
|
|
}
|
|
- }
|
|
- } catch ( Exception ex )
|
|
- {
|
|
+ // Waterfall start - split command & tab complete exception handlers for exception event
|
|
+ } catch ( Exception ex ) {
|
|
sender.sendMessage( ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details." );
|
|
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Error in dispatching command", ex );
|
|
+ this.callEvent( new ProxyExceptionEvent( new ProxyTabCompleteException( ex, command, sender, args ) ) ); //Waterfall - throw error event
|
|
}
|
|
+ // Waterfall end
|
|
+ }
|
|
return true;
|
|
}
|
|
|
|
@@ -289,7 +304,11 @@ public final class PluginManager
|
|
} );
|
|
} catch ( Throwable t )
|
|
{
|
|
- ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + plugin.getDescription().getName(), t );
|
|
+ // Waterfall start - throw exception event
|
|
+ String msg = "Exception encountered when loading plugin: " + plugin.getDescription().getName();
|
|
+ ProxyServer.getInstance().getLogger().log( Level.WARNING, msg, t );
|
|
+ this.callEvent( new ProxyExceptionEvent( new ProxyPluginEnableDisableException( msg, t, plugin) ) );
|
|
+ // Waterfall end
|
|
}
|
|
}
|
|
}
|
|
@@ -431,7 +450,7 @@ public final class PluginManager
|
|
Preconditions.checkNotNull( event, "event" );
|
|
|
|
long start = System.nanoTime();
|
|
- eventBus.post( event );
|
|
+ eventBus.post( event, this::handleEventException ); //Waterfall - pass exception handler below
|
|
event.postCall();
|
|
|
|
long elapsed = System.nanoTime() - start;
|
|
@@ -445,6 +464,14 @@ public final class PluginManager
|
|
return event;
|
|
}
|
|
|
|
+ //Waterfall start - Exception handler passed to event bus to fire the exception event
|
|
+ private <T extends Event> void handleEventException(String msg, T event, EventHandlerMethod method, Throwable ex) {
|
|
+ if( !(event instanceof ProxyExceptionEvent) ) {
|
|
+ this.callEvent( new ProxyExceptionEvent( new ProxyEventException( msg, ex, (Listener) method.getListener(), event) ) );
|
|
+ }
|
|
+ }
|
|
+ //Waterfall end
|
|
+
|
|
/**
|
|
* Register a {@link Listener} for receiving called events. Methods in this
|
|
* Object which wish to receive events must be annotated with the
|
|
diff --git a/event/src/main/java/net/md_5/bungee/event/EventBus.java b/event/src/main/java/net/md_5/bungee/event/EventBus.java
|
|
index f5bd1f98..d7c3b90d 100644
|
|
--- a/event/src/main/java/net/md_5/bungee/event/EventBus.java
|
|
+++ b/event/src/main/java/net/md_5/bungee/event/EventBus.java
|
|
@@ -33,7 +33,8 @@ public class EventBus
|
|
this.logger = ( logger == null ) ? Logger.getLogger( Logger.GLOBAL_LOGGER_NAME ) : logger;
|
|
}
|
|
|
|
- public void post(Object event)
|
|
+ // Waterfall - Add generic to signature so we don't have to cast in exception handler
|
|
+ public <T> void post(T event, EventExceptionHandler<T> exceptionHandler)
|
|
{
|
|
EventHandlerMethod[] handlers = byEventBaked.get( event.getClass() );
|
|
|
|
@@ -52,7 +53,9 @@ public class EventBus
|
|
throw new Error( "Method rejected target/argument: " + event, ex );
|
|
} catch ( InvocationTargetException ex )
|
|
{
|
|
- logger.log( Level.WARNING, MessageFormat.format( "Error dispatching event {0} to listener {1}", event, method.getListener() ), ex.getCause() );
|
|
+ String msg = MessageFormat.format( "Error dispatching event {0} to listener {1}", event, method.getListener() );
|
|
+ logger.log( Level.WARNING, msg, ex.getCause() );
|
|
+ if( exceptionHandler != null ) exceptionHandler.handleEventException( msg, event, method, ex ); //Waterfall - call passed exception handler
|
|
}
|
|
}
|
|
}
|
|
diff --git a/event/src/main/java/net/md_5/bungee/event/EventExceptionHandler.java b/event/src/main/java/net/md_5/bungee/event/EventExceptionHandler.java
|
|
new file mode 100644
|
|
index 00000000..088fe9b7
|
|
--- /dev/null
|
|
+++ b/event/src/main/java/net/md_5/bungee/event/EventExceptionHandler.java
|
|
@@ -0,0 +1,7 @@
|
|
+package net.md_5.bungee.event;
|
|
+
|
|
+public interface EventExceptionHandler<T> {
|
|
+
|
|
+ public void handleEventException(String msg, T event, EventHandlerMethod method, Throwable ex);
|
|
+
|
|
+}
|
|
diff --git a/event/src/test/java/net/md_5/bungee/event/EventBusTest.java b/event/src/test/java/net/md_5/bungee/event/EventBusTest.java
|
|
index 2c737675..72f14937 100644
|
|
--- a/event/src/test/java/net/md_5/bungee/event/EventBusTest.java
|
|
+++ b/event/src/test/java/net/md_5/bungee/event/EventBusTest.java
|
|
@@ -14,14 +14,14 @@ public class EventBusTest
|
|
public void testNestedEvents()
|
|
{
|
|
bus.register( this );
|
|
- bus.post( new FirstEvent() );
|
|
+ bus.post( new FirstEvent(), null ); // Waterfall - We dont need an exception handler here
|
|
Assert.assertEquals( 0, latch.getCount() );
|
|
}
|
|
|
|
@EventHandler
|
|
public void firstListener(FirstEvent event)
|
|
{
|
|
- bus.post( new SecondEvent() );
|
|
+ bus.post( new SecondEvent(), null ); // Waterfall - We dont need an exception handler here
|
|
Assert.assertEquals( 1, latch.getCount() );
|
|
latch.countDown();
|
|
}
|
|
@@ -39,4 +39,5 @@ public class EventBusTest
|
|
public static class SecondEvent
|
|
{
|
|
}
|
|
+
|
|
}
|
|
diff --git a/event/src/test/java/net/md_5/bungee/event/EventPriorityTest.java b/event/src/test/java/net/md_5/bungee/event/EventPriorityTest.java
|
|
index 351d3724..88f1346f 100644
|
|
--- a/event/src/test/java/net/md_5/bungee/event/EventPriorityTest.java
|
|
+++ b/event/src/test/java/net/md_5/bungee/event/EventPriorityTest.java
|
|
@@ -15,7 +15,7 @@ public class EventPriorityTest
|
|
{
|
|
bus.register( this );
|
|
bus.register( new EventPriorityListenerPartner() );
|
|
- bus.post( new PriorityTestEvent() );
|
|
+ bus.post( new PriorityTestEvent(), null ); // Waterfall - We dont need an exception handler here
|
|
Assert.assertEquals( 0, latch.getCount() );
|
|
}
|
|
|
|
diff --git a/event/src/test/java/net/md_5/bungee/event/UnregisteringListenerTest.java b/event/src/test/java/net/md_5/bungee/event/UnregisteringListenerTest.java
|
|
index fbfbd546..ae85a1d4 100644
|
|
--- a/event/src/test/java/net/md_5/bungee/event/UnregisteringListenerTest.java
|
|
+++ b/event/src/test/java/net/md_5/bungee/event/UnregisteringListenerTest.java
|
|
@@ -13,7 +13,7 @@ public class UnregisteringListenerTest
|
|
{
|
|
bus.register( this );
|
|
bus.unregister( this );
|
|
- bus.post( new TestEvent() );
|
|
+ bus.post( new TestEvent(), null ); // Waterfall - We dont need an exception handler here
|
|
}
|
|
|
|
@EventHandler
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
|
|
index a839cba5..a963c748 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
|
|
@@ -11,6 +11,8 @@ import com.google.gson.Gson;
|
|
import com.google.gson.GsonBuilder;
|
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|
import io.github.waterfallmc.waterfall.conf.WaterfallConfiguration;
|
|
+import io.github.waterfallmc.waterfall.event.ProxyExceptionEvent;
|
|
+import io.github.waterfallmc.waterfall.exception.ProxyPluginEnableDisableException;
|
|
import io.netty.bootstrap.ServerBootstrap;
|
|
import io.netty.channel.Channel;
|
|
import io.netty.channel.ChannelException;
|
|
@@ -476,7 +478,11 @@ public class BungeeCord extends ProxyServer
|
|
}
|
|
} catch ( Throwable t )
|
|
{
|
|
- getLogger().log( Level.SEVERE, "Exception disabling plugin " + plugin.getDescription().getName(), t );
|
|
+ // Waterfall start - throw exception event
|
|
+ String msg = "Exception disabling plugin " + plugin.getDescription().getName();
|
|
+ getLogger().log( Level.SEVERE, msg, t );
|
|
+ pluginManager.callEvent( new ProxyExceptionEvent( new ProxyPluginEnableDisableException( msg, t, plugin) ) );
|
|
+ // Waterfall end
|
|
}
|
|
getScheduler().cancel( plugin );
|
|
plugin.getExecutorService().shutdownNow();
|
|
diff --git a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeTask.java b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeTask.java
|
|
index 67db0cc4..02ec98fc 100644
|
|
--- a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeTask.java
|
|
+++ b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeTask.java
|
|
@@ -3,6 +3,9 @@ package net.md_5.bungee.scheduler;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.logging.Level;
|
|
+
|
|
+import io.github.waterfallmc.waterfall.event.ProxyExceptionEvent;
|
|
+import io.github.waterfallmc.waterfall.exception.ProxySchedulerException;
|
|
import lombok.Data;
|
|
import net.md_5.bungee.api.ProxyServer;
|
|
import net.md_5.bungee.api.plugin.Plugin;
|
|
@@ -63,7 +66,11 @@ public class BungeeTask implements Runnable, ScheduledTask
|
|
task.run();
|
|
} catch ( Throwable t )
|
|
{
|
|
- ProxyServer.getInstance().getLogger().log( Level.SEVERE, String.format( "Task %s encountered an exception", this ), t );
|
|
+ //Waterfall start - throw exception event
|
|
+ String msg = String.format( "Task %s encountered an exception", this );
|
|
+ ProxyServer.getInstance().getLogger().log( Level.SEVERE, msg, t );
|
|
+ ProxyServer.getInstance().getPluginManager().callEvent( new ProxyExceptionEvent( new ProxySchedulerException( msg, t, this ) ) );
|
|
+ //Waterfall end
|
|
}
|
|
|
|
// If we have a period of 0 or less, only run once
|
|
--
|
|
2.26.1
|
|
|