diff --git a/base/src/main/java/de/staropensource/sosengine/base/events/ThrowableCatchEvent.java b/base/src/main/java/de/staropensource/sosengine/base/events/ThrowableCatchEvent.java new file mode 100644 index 00000000..dd5aa5b7 --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/events/ThrowableCatchEvent.java @@ -0,0 +1,76 @@ +/* + * STAROPENSOURCE ENGINE SOURCE FILE + * Copyright (c) 2024 The StarOpenSource Engine Contributors + * Licensed under the GNU Affero General Public License v3 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.staropensource.sosengine.base.events; + +import de.staropensource.sosengine.base.EngineConfiguration; +import de.staropensource.sosengine.base.classes.Event; +import de.staropensource.sosengine.base.classes.helpers.EventHelper; +import de.staropensource.sosengine.base.utility.Miscellaneous; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Called when an exception is caught. + * + * @see Miscellaneous#exec + * @see Miscellaneous#executeSafely(Runnable) + * @since 1-alpha0 + */ +public class ThrowableCatchEvent implements Event { + /** + * Constructor. + */ + public ThrowableCatchEvent() {} + + /** + * {@inheritDoc} + * @deprecated use the {@code callEvent} method with arguments + * @see ThrowableCatchEvent#callEvent(Throwable, String) + */ + @Deprecated + @Override + public void callEvent() {} + + /** + * Calls the event and notifies all annotated methods. + * + * @param throwable caught throwable + * @param identifier an identifier given to the runnable + * @since 1-alpha0 + */ + public void callEvent(@NotNull Throwable throwable, @NotNull String identifier) { + Runnable eventCode = Thread.ofVirtual().start(() -> { + EventHelper.logCall(getClass(), throwable, identifier); + + for (Method method : EventHelper.getAnnotatedMethods(getClass())) { + try { + method.invoke(null, throwable, identifier); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {} + } + }); + + if (EngineConfiguration.getInstance().isOptimizeEvents()) + Thread.ofVirtual().start(eventCode); + else + eventCode.run(); + } +} diff --git a/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java b/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java index a9b1173b..3f9d7a40 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java +++ b/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java @@ -19,6 +19,7 @@ package de.staropensource.sosengine.base.utility; +import de.staropensource.sosengine.base.events.ThrowableCatchEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -94,4 +95,19 @@ public final class Miscellaneous { public static Set getMapValue(@NotNull Map map, @Nullable Object value) { return map.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), value)).map(Map.Entry::getKey).collect(Collectors.toSet()); } + + /** + * Executes a {@link Runnable} and emits {@link ThrowableCatchEvent} if a throwable is caught. + * + * @param runnable {@link Runnable} to execute + * @param identifier some identifier to distinguish {@link Runnable}s + * @since 1-alpha1 + */ + public static void executeSafely(@NotNull Runnable runnable, @NotNull String identifier) { + try { + runnable.run(); + } catch (Throwable throwable) { + new ThrowableCatchEvent().callEvent(throwable, identifier); + } + } }