diff --git a/base/src/main/java/de/staropensource/sosengine/base/Engine.java b/base/src/main/java/de/staropensource/sosengine/base/Engine.java index ee2bfe3e..01397621 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/Engine.java +++ b/base/src/main/java/de/staropensource/sosengine/base/Engine.java @@ -91,9 +91,6 @@ public final class Engine { // Initialize classes initializeClasses(); - // Initialize events - initializeEvents(); - // Populate crash content populateCrashContent(); @@ -119,14 +116,6 @@ public final class Engine { new ShortcodeConverter(); } - /** - * Initializes all events. - * - * @since 1-alpha0 - */ - private void initializeEvents() { - } - /** * This method populates the Crash Handler's content with the default set of content. * diff --git a/base/src/main/java/de/staropensource/sosengine/base/annotations/EventListener.java b/base/src/main/java/de/staropensource/sosengine/base/annotations/EventListener.java index fbadd1ed..c57b533d 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/annotations/EventListener.java +++ b/base/src/main/java/de/staropensource/sosengine/base/annotations/EventListener.java @@ -20,15 +20,29 @@ package de.staropensource.sosengine.base.annotations; import de.staropensource.sosengine.base.classes.Event; +import de.staropensource.sosengine.base.classes.EventPriority; import java.lang.annotation.*; /** * Annotation for registering events on methods. */ +@SuppressWarnings("unused") @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface EventListener { + /** + * The event to listen for. + * + * @return the event the method listens for + */ Class event(); + + /** + * The priority of the event. + * + * @return the event priority + */ + EventPriority priority(); } diff --git a/base/src/main/java/de/staropensource/sosengine/base/classes/Event.java b/base/src/main/java/de/staropensource/sosengine/base/classes/Event.java index 61d23bff..178f0a77 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/classes/Event.java +++ b/base/src/main/java/de/staropensource/sosengine/base/classes/Event.java @@ -1,131 +1,14 @@ -/* - 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.classes; -import de.staropensource.sosengine.base.annotations.EventListener; -import de.staropensource.sosengine.base.logging.Logger; -import de.staropensource.sosengine.base.types.CodePart; -import de.staropensource.sosengine.base.types.LogIssuer; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; -import org.reflections.Reflections; -import org.reflections.scanners.Scanners; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - /** * Represents an event. * * @since 1-alpha0 */ -@Getter -@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" }) -public abstract class Event { +@SuppressWarnings({ "unused" }) +public interface Event { /** - * Instance. - * - * @since 1-alpha0 - * - * -- GETTER -- - * Returns the extending {@link Event} instance. - * - * @return extending {@link Event} instance - * @since 1-alpha0 + * Calls the event. */ - @Getter() - protected static Event instance; - - /** - * The name of the event. - * - * @since 1-alpha0 - * - * -- GETTER -- - * Returns the name of the event. - * - * @return the event name - * @since 1-alpha0 - */ - @NotNull - private final String eventName; - - /** - * Constructor. - * - * @since 1-alpha0 - */ - public Event() { - this.eventName = this.getClass().getName().replace(this.getClass().getPackage() + ".", ""); - - // Only allow one instance - if (instance == null) - instance = this; - else - Logger.crash(new LogIssuer(getClass(), CodePart.ENGINE), "Tried reinitializing " + getClass().getName() + " twice"); - } - - /** - * Returns all annotated methods. - * - * @return list of annotated methods - * @since 1-alpha0 - */ - @NotNull - protected List getAnnotatedMethods() { - List methods = new ArrayList<>(); - - Reflections reflections = new Reflections( - new ConfigurationBuilder() - .setUrls(ClasspathHelper.forJavaClassPath()) - .setScanners(Scanners.MethodsAnnotated) - ); - Set annotatedMethods = reflections.getMethodsAnnotatedWith(EventListener.class); - - for (Method method : annotatedMethods) - if (method.getAnnotation(EventListener.class).event() == this.getClass()) - methods.add(method); - - return methods; - } - - /** - * Invokes all annotated methods without any arguments. - */ - protected void invokeAnnotatedMethods() { - for (Method method : getAnnotatedMethods()) { - try { - method.invoke(null); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {} - } - } - - /** - * Calls the event and notifies all annotated methods about it. - * - * @since 1-alpha0 - */ - public abstract void callEvent(); + void callEvent(); } diff --git a/base/src/main/java/de/staropensource/sosengine/base/classes/EventPriority.java b/base/src/main/java/de/staropensource/sosengine/base/classes/EventPriority.java new file mode 100644 index 00000000..e62a7010 --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/classes/EventPriority.java @@ -0,0 +1,39 @@ +package de.staropensource.sosengine.base.classes; + +/** + * Determines in which order events are processed. + */ +@SuppressWarnings("unused") +public enum EventPriority { + /** + * Events with this priority are processed first. + * This event is exclusive to subsystems and should not be used by applications. + */ + EXTREMELY_IMPORTANT, + + /** + * Events with this priority are processed after {@code EXTREMELY_IMPORTANT}. + */ + VERY_IMPORTANT, + + /** + * Events with this priority are processed after {@code VERY_IMPORTANT}. + */ + IMPORTANT, + + /** + * Events with this priority are processed after {@code IMPORTANT}. + */ + UNIMPORTANT, + + /** + * Events with this priority are processed after {@code UNIMPORTANT}. + */ + VERY_UNIMPORTANT, + + /** + * Events with this priority are processed last. + * This event is exclusive to subsystems and should not be used by applications. + */ + EXTREMELY_UNIMPORTANT, +} diff --git a/base/src/main/java/de/staropensource/sosengine/base/events/EngineCrashEvent.java b/base/src/main/java/de/staropensource/sosengine/base/events/EngineCrashEvent.java index 203c8ebf..03c760cd 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/events/EngineCrashEvent.java +++ b/base/src/main/java/de/staropensource/sosengine/base/events/EngineCrashEvent.java @@ -20,6 +20,7 @@ package de.staropensource.sosengine.base.events; import de.staropensource.sosengine.base.classes.Event; +import de.staropensource.sosengine.base.utility.EventHelper; /** * Called in the event of an engine crash, just before the JVM exists. @@ -27,10 +28,10 @@ import de.staropensource.sosengine.base.classes.Event; * @since 1-alpha0 */ @SuppressWarnings({ "unused" }) -public final class EngineCrashEvent extends Event { +public final class EngineCrashEvent implements Event { /** {@inheritDoc} */ @Override public void callEvent() { - invokeAnnotatedMethods(); + EventHelper.invokeAnnotatedMethods(getClass()); } } diff --git a/base/src/main/java/de/staropensource/sosengine/base/events/LogEvent.java b/base/src/main/java/de/staropensource/sosengine/base/events/LogEvent.java index 5f1a8b9b..18648eed 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/events/LogEvent.java +++ b/base/src/main/java/de/staropensource/sosengine/base/events/LogEvent.java @@ -22,6 +22,7 @@ package de.staropensource.sosengine.base.events; import de.staropensource.sosengine.base.classes.Event; import de.staropensource.sosengine.base.types.LogIssuer; import de.staropensource.sosengine.base.types.LogLevel; +import de.staropensource.sosengine.base.utility.EventHelper; import org.jetbrains.annotations.NotNull; import java.lang.reflect.InvocationTargetException; @@ -33,16 +34,16 @@ import java.lang.reflect.Method; * @since 1-alpha0 */ @SuppressWarnings({ "unused" }) -public final class LogEvent extends Event { +public final class LogEvent implements Event { /** * {@inheritDoc} * @deprecated use the {@code callEvent} method with arguments - * @see LogEvent#callEventNew(LogLevel, LogIssuer, String) + * @see LogEvent#callEvent(LogLevel, LogIssuer, String) */ @Deprecated @Override public void callEvent() { - invokeAnnotatedMethods(); + EventHelper.invokeAnnotatedMethods(getClass()); } /** @@ -50,8 +51,8 @@ public final class LogEvent extends Event { * * @since 1-alpha0 */ - public void callEventNew(@NotNull LogLevel level, @NotNull LogIssuer logIssuer, @NotNull String message) { - for (Method method : getAnnotatedMethods()) { + public void callEvent(@NotNull LogLevel level, @NotNull LogIssuer logIssuer, @NotNull String message) { + for (Method method : EventHelper.getAnnotatedMethods(getClass())) { try { method.invoke(null, level, logIssuer, message); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {} diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java b/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java index a2de405c..78b4e140 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java @@ -144,7 +144,7 @@ public final class CrashHandler { Logger.getLoggerImplementation().print(LogLevel.CRASH, logIssuer, base); // Send EngineCrash event - EngineCrashEvent.getInstance().callEvent(); + new EngineCrashEvent().callEvent(); // Shutdown JVM if (EngineConfiguration.getInstance().isLoggerImmediateShutdown()) diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java b/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java index 6792edf3..0edd7ab8 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/Logger.java @@ -115,7 +115,7 @@ public final class Logger { base = loggerImplementation.postPlaceholder(level, logIssuer, base); // Call event - ((LogEvent) LogEvent.getInstance()).callEventNew(level, logIssuer, message); + new LogEvent().callEvent(level, logIssuer, message); // Print log message loggerImplementation.print(level, logIssuer, base); diff --git a/base/src/main/java/de/staropensource/sosengine/base/utility/EventHelper.java b/base/src/main/java/de/staropensource/sosengine/base/utility/EventHelper.java new file mode 100644 index 00000000..8415bf55 --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/utility/EventHelper.java @@ -0,0 +1,82 @@ +/* + 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.utility; + +import de.staropensource.sosengine.base.annotations.EventListener; +import de.staropensource.sosengine.base.classes.Event; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.reflections.Reflections; +import org.reflections.scanners.Scanners; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; + +/** + * Represents an event. + * + * @since 1-alpha0 + */ +@Getter +@SuppressWarnings({ "unused" }) +public class EventHelper { + /** + * Returns all annotated methods. + * + * @return list of annotated methods + * @since 1-alpha0 + */ + @NotNull + public static LinkedList getAnnotatedMethods(Class clazz) { + LinkedList methods = new LinkedList<>(); + + Reflections reflections = new Reflections( + new ConfigurationBuilder() + .setUrls(ClasspathHelper.forJavaClassPath()) + .setScanners(Scanners.MethodsAnnotated) + ); + Set annotatedMethods = reflections.getMethodsAnnotatedWith(EventListener.class); + + for (Method method : annotatedMethods) + if (method.getAnnotation(EventListener.class).event() == clazz) + methods.add(method); + + // Sort 'methods' linked list + methods.sort(Comparator.comparing(method0 -> method0.getAnnotation(EventListener.class).priority())); + + return methods; + } + + /** + * Invokes all annotated methods without any arguments. + * + * @since 1-alpha0 + */ + public static void invokeAnnotatedMethods(Class clazz) { + for (Method method : getAnnotatedMethods(clazz)) { + try { + method.invoke(null); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {} + } + } +}