diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java index 285f6f3..47e03c3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java @@ -22,10 +22,11 @@ import org.lwjgl.glfw.GLFW; import com.google.common.eventbus.EventBus; import ru.windcorp.progressia.client.graphics.input.*; +import ru.windcorp.progressia.common.util.crash.ReportingEventBus; public class InputHandler { - private static final EventBus INPUT_EVENT_BUS = new EventBus("Input"); + private static final EventBus INPUT_EVENT_BUS = ReportingEventBus.create("Input"); // KeyEvent diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 7424bd9..e1034be 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -40,6 +40,7 @@ import ru.windcorp.progressia.client.graphics.input.bus.InputBus; import ru.windcorp.progressia.client.graphics.input.bus.InputListener; import ru.windcorp.progressia.common.util.Named; import ru.windcorp.progressia.common.util.crash.CrashReports; +import ru.windcorp.progressia.common.util.crash.ReportingEventBus; public class Component extends Named { @@ -455,7 +456,7 @@ public class Component extends Named { public void addListener(Object listener) { if (eventBus == null) { - eventBus = new EventBus(getName()); + eventBus = ReportingEventBus.create(getName()); } eventBus.register(listener); diff --git a/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java b/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java new file mode 100644 index 0000000..48ffade --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java @@ -0,0 +1,55 @@ +package ru.windcorp.progressia.common.hacks; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.concurrent.Executor; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.SubscriberExceptionHandler; +import com.google.common.util.concurrent.MoreExecutors; + +import ru.windcorp.progressia.common.util.crash.CrashReports; + +/** + * This class had to be written because there is not legal way to instantiate a non-async + * {@link EventBus} with both a custom identifier and a custom exception handler. Which + * is a shame. Guava maintainers know about the issue but have rejected solutions multiple + * times without a clearly stated reason; looks like some dirty reflection will + * have to do. + * @author javapony + */ +public class GuavaEventBusHijacker { + + public static final Constructor THE_CONSTRUCTOR; + public static final Method DISPATCHER__PER_THREAD_DISPATCH_QUEUE; + + static { + try { + Class dispatcherClass = Class.forName("com.google.common.eventbus.Dispatcher"); + + THE_CONSTRUCTOR = EventBus.class.getDeclaredConstructor( + String.class, Executor.class, dispatcherClass, SubscriberExceptionHandler.class + ); + THE_CONSTRUCTOR.setAccessible(true); + + DISPATCHER__PER_THREAD_DISPATCH_QUEUE = dispatcherClass.getDeclaredMethod("perThreadDispatchQueue"); + DISPATCHER__PER_THREAD_DISPATCH_QUEUE.setAccessible(true); + } catch (Exception e) { + throw CrashReports.report(e, "Something went horribly wrong when setting up EventBus hijacking. Has Guava updated?"); + } + } + + public static EventBus newEventBus(String identifier, SubscriberExceptionHandler exceptionHandler) { + try { + return THE_CONSTRUCTOR.newInstance( + identifier, + MoreExecutors.directExecutor(), + DISPATCHER__PER_THREAD_DISPATCH_QUEUE.invoke(null), + exceptionHandler + ); + } catch (Exception e) { + throw CrashReports.report(e, "Something went horribly wrong when hijacking EventBus. Has Guava updated?"); + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java new file mode 100644 index 0000000..0633085 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java @@ -0,0 +1,18 @@ +package ru.windcorp.progressia.common.util.crash; + +import com.google.common.eventbus.EventBus; + +import ru.windcorp.progressia.common.hacks.GuavaEventBusHijacker; + +public class ReportingEventBus { + + private ReportingEventBus() {} + + public static EventBus create(String identifier) { + return GuavaEventBusHijacker.newEventBus(identifier, (throwable, context) -> { + // Makes sense to append identifier to messageFormat because different EventBuses are completely unrelated + throw CrashReports.crash(throwable, "Unexpected exception in EventBus " + identifier); + }); + } + +}