Improve event system and reflection
This commit is contained in:
parent
350b18219b
commit
2469e124bd
10 changed files with 188 additions and 84 deletions
|
@ -22,7 +22,16 @@ package de.staropensource.sosengine.base.classes.helpers;
|
|||
import de.staropensource.sosengine.base.EngineConfiguration;
|
||||
import de.staropensource.sosengine.base.annotations.EventListener;
|
||||
import de.staropensource.sosengine.base.classes.Event;
|
||||
import de.staropensource.sosengine.base.exceptions.UnexpectedThrowableException;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.InstanceMethodFromStaticContextException;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.InvalidMethodSignature;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.NoAccessException;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.StaticInitializerException;
|
||||
import de.staropensource.sosengine.base.logging.Logger;
|
||||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||
import de.staropensource.sosengine.base.reflection.Reflect;
|
||||
import de.staropensource.sosengine.base.reflection.ReflectionMethod;
|
||||
import de.staropensource.sosengine.base.types.CodePart;
|
||||
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||
import de.staropensource.sosengine.base.utility.ListFormatter;
|
||||
import lombok.Getter;
|
||||
|
@ -53,7 +62,7 @@ public class EventHelper {
|
|||
*
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
private static final HashMap<@NotNull Class<? extends Event>, LinkedList<@NotNull Method>> cachedEventListeners = new HashMap<>();
|
||||
private static final HashMap<@NotNull Class<? extends Event>, LinkedList<@NotNull ReflectionMethod>> cachedEventListeners = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs this class.
|
||||
|
@ -85,8 +94,8 @@ public class EventHelper {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
@NotNull
|
||||
public static LinkedList<Method> getAnnotatedMethods(@NotNull Class<? extends Event> clazz, boolean forceScanning) {
|
||||
LinkedList<Method> methods = new LinkedList<>();
|
||||
public static LinkedList<ReflectionMethod> getAnnotatedMethods(@NotNull Class<? extends Event> clazz, boolean forceScanning) {
|
||||
LinkedList<ReflectionMethod> methods = new LinkedList<>();
|
||||
|
||||
if (forceScanning || !cachedEventListeners.containsKey(clazz)) {
|
||||
// Scan entire classpath through Reflections library
|
||||
|
@ -103,10 +112,10 @@ public class EventHelper {
|
|||
// Sort event listeners not listening for this event out
|
||||
for (Method method : annotatedMethods)
|
||||
if (method.getAnnotation(EventListener.class).event() == clazz)
|
||||
methods.add(method);
|
||||
methods.add(Reflect.reflectOn(method));
|
||||
|
||||
// Sort 'methods' linked list after event priority
|
||||
methods.sort(Comparator.comparing(method0 -> method0.getAnnotation(EventListener.class).priority()));
|
||||
methods.sort(Comparator.comparing(method -> method.getAnnotation(EventListener.class).priority()));
|
||||
} else
|
||||
// 'forcedScanning' is false and matching event listeners are cached
|
||||
methods = cachedEventListeners.get(clazz);
|
||||
|
@ -122,25 +131,36 @@ public class EventHelper {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
@NotNull
|
||||
public static LinkedList<Method> getAnnotatedMethods(@NotNull Class<? extends Event> clazz) {
|
||||
public static LinkedList<ReflectionMethod> getAnnotatedMethods(@NotNull Class<? extends Event> clazz) {
|
||||
return getAnnotatedMethods(clazz, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes all matching event listeners without any arguments.
|
||||
*
|
||||
* @param clazz event class
|
||||
* @param event event class
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public static void invokeAnnotatedMethods(@NotNull Class<? extends Event> clazz) {
|
||||
public static void invokeAnnotatedMethods(@NotNull Class<? extends Event> event, Object... arguments) {
|
||||
Runnable eventCode = () -> {
|
||||
logCall(clazz);
|
||||
LoggerInstance logger = new LoggerInstance(new LogIssuer(EventHelper.class, event.getName(), CodePart.ENGINE));
|
||||
logCall(event);
|
||||
|
||||
for (Method method : getAnnotatedMethods(clazz)) {
|
||||
for (ReflectionMethod method : getAnnotatedMethods(event)) {
|
||||
try {
|
||||
method.invoke(null);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException |
|
||||
NullPointerException | ExceptionInInitializerError ignored) {
|
||||
method.invoke(arguments);
|
||||
} catch (UnexpectedThrowableException exception) {
|
||||
logger.crash("Event listener method " + method.getName() + " could not be called as an error occured during reflection", exception, true);
|
||||
} catch (NoAccessException exception) {
|
||||
logger.warn("Event listener method " + method.getName() + " could not be called as the method could not be accessed");
|
||||
} catch (InvalidMethodSignature exception) {
|
||||
logger.warn("Event listener method " + method.getName() + " has an invalid method signature");
|
||||
} catch (InvocationTargetException exception) {
|
||||
logger.crash("Event listener method " + method.getName() + " threw a throwable", exception.getTargetException(), true);
|
||||
} catch (InstanceMethodFromStaticContextException exception) {
|
||||
logger.warn("Event listener method " + method.getName() + " is not static. Event listener methods must be static for them to be called.");
|
||||
} catch (StaticInitializerException exception) {
|
||||
logger.crash("Event listener method " + method.getName() + " could not be called as the static initializer failed", exception.getThrowable(), true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -163,7 +183,7 @@ public class EventHelper {
|
|||
for (Class<? extends Event> event : cachedEventListeners.keySet())
|
||||
precomputeEventListeners(event);
|
||||
else {
|
||||
LinkedList<@NotNull Method> annotatedMethods = getAnnotatedMethods(clazz);
|
||||
LinkedList<@NotNull ReflectionMethod> annotatedMethods = getAnnotatedMethods(clazz);
|
||||
|
||||
if (cachedEventListeners.containsKey(clazz))
|
||||
cachedEventListeners.replace(clazz, annotatedMethods);
|
||||
|
|
|
@ -19,16 +19,12 @@
|
|||
|
||||
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.types.logging.LogIssuer;
|
||||
import de.staropensource.sosengine.base.types.logging.LogLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Called before a new log message is printed.
|
||||
*
|
||||
|
@ -59,20 +55,6 @@ public final class LogEvent implements Event {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
public void callEvent(@NotNull LogLevel level, @NotNull LogIssuer logIssuer, @NotNull String message) {
|
||||
Runnable eventCode = Thread.ofVirtual().start(() -> {
|
||||
// Uncommenting this would be a great way to cause a StackOverflowException!
|
||||
//EventHelper.logCall(getClass(), level, logIssuer, message);
|
||||
|
||||
for (Method method : EventHelper.getAnnotatedMethods(getClass())) {
|
||||
try {
|
||||
method.invoke(null, level, logIssuer, message);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {}
|
||||
}
|
||||
});
|
||||
|
||||
if (EngineConfiguration.getInstance().isOptimizeEvents())
|
||||
Thread.ofVirtual().start(eventCode);
|
||||
else
|
||||
eventCode.run();
|
||||
EventHelper.invokeAnnotatedMethods(getClass(), level, logIssuer, message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,11 @@
|
|||
|
||||
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.
|
||||
*
|
||||
|
@ -57,19 +53,6 @@ public final class ThrowableCatchEvent implements Event {
|
|||
* @since v1-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();
|
||||
EventHelper.invokeAnnotatedMethods(getClass(), throwable, identifier);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.sosengine.base.exceptions.reflection;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Thrown when trying to call a non-static method from a static context.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public class InstanceMethodFromStaticContextException extends Exception {
|
||||
/**
|
||||
* Constructs this exception.
|
||||
*
|
||||
* @param methodName name of the method
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public InstanceMethodFromStaticContextException(@NotNull String methodName) {
|
||||
super("Method " + methodName + " could not be called as the method is non-static and was called from a static context");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.sosengine.base.exceptions.reflection;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class InvalidMethodSignature extends Exception {
|
||||
public InvalidMethodSignature(@NotNull String methodName) {
|
||||
super("Method " + methodName + " has a different method signature");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.staropensource.sosengine.base.exceptions.reflection;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Thrown when an exception occurs
|
||||
* while executing a static initializer.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Getter
|
||||
@SuppressWarnings({ "unused", "JavadocDeclaration", "JavadocBlankLines" })
|
||||
public class StaticInitializerException extends Exception {
|
||||
/**
|
||||
* Contains the throwable supplied to the constructor.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*
|
||||
* -- GETTER --
|
||||
* Returns the throwable supplied to the constructor.
|
||||
*
|
||||
* @return throwable thrown by the static initializer
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private final Throwable throwable;
|
||||
|
||||
/**
|
||||
* Constructs this exception.
|
||||
*
|
||||
* @param throwable throwable thrown by the static initializer
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public StaticInitializerException(@NotNull Throwable throwable) {
|
||||
this.throwable = throwable;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import de.staropensource.sosengine.base.Engine;
|
|||
import de.staropensource.sosengine.base.EngineConfiguration;
|
||||
import de.staropensource.sosengine.base.classes.LoggerImpl;
|
||||
import de.staropensource.sosengine.base.classes.Placeholder;
|
||||
import de.staropensource.sosengine.base.classes.helpers.EventHelper;
|
||||
import de.staropensource.sosengine.base.events.LogEvent;
|
||||
import de.staropensource.sosengine.base.internal.placeholders.logger.*;
|
||||
import de.staropensource.sosengine.base.internal.types.QueuedLogMessage;
|
||||
|
@ -214,7 +215,7 @@ public final class Logger {
|
|||
base = loggerImplementation.postPlaceholder(level, issuer, base);
|
||||
|
||||
// Call event
|
||||
if (!issuer.getClazz().getName().equals("de.staropensource.sosengine.slf4j_compat.CompatibilityLogger"))
|
||||
if (!(issuer.getClazz().getName().equals("de.staropensource.sosengine.slf4j_compat.CompatibilityLogger") || issuer.getClazz().equals(EventHelper.class)))
|
||||
new LogEvent().callEvent(level, issuer, message);
|
||||
|
||||
// Print log message by invoking LoggerImpl#print
|
||||
|
|
|
@ -21,7 +21,10 @@ package de.staropensource.sosengine.base.reflection;
|
|||
|
||||
import de.staropensource.sosengine.base.exceptions.UnexpectedCheckEndException;
|
||||
import de.staropensource.sosengine.base.exceptions.UnexpectedThrowableException;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.InstanceMethodFromStaticContextException;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.InvalidMethodSignature;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.NoAccessException;
|
||||
import de.staropensource.sosengine.base.exceptions.reflection.StaticInitializerException;
|
||||
import de.staropensource.sosengine.base.internal.reflection.ReflectionAccessWidener;
|
||||
import de.staropensource.sosengine.base.types.reflection.VisibilityModifier;
|
||||
import lombok.Getter;
|
||||
|
@ -310,11 +313,12 @@ public final class ReflectionMethod {
|
|||
/**
|
||||
* Returns the specified annotation or {@code null} if not found.
|
||||
*
|
||||
* @param annotation class
|
||||
* @param <T> annotation class
|
||||
* @param annotation annotation class
|
||||
* @return annotation or {@code null}
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
public Annotation getAnnotation(@NotNull Class<Annotation> annotation) {
|
||||
public <T extends Annotation> T getAnnotation(@NotNull Class<T> annotation) {
|
||||
return method.getAnnotation(annotation);
|
||||
}
|
||||
|
||||
|
@ -345,13 +349,16 @@ public final class ReflectionMethod {
|
|||
* Invokes the method.
|
||||
*
|
||||
* @return method return value
|
||||
* @throws NoAccessException if access to the method has been denied
|
||||
* @throws InvocationTargetException covers exceptions thrown by the method
|
||||
* @throws UnexpectedThrowableException if the {@code modifiers} field could not be found
|
||||
* @throws NoAccessException if access to the method has been denied
|
||||
* @throws InvalidMethodSignature if the method signature is incorrect
|
||||
* @throws InvocationTargetException covers exceptions thrown by the method
|
||||
* @throws InstanceMethodFromStaticContextException when the target method is non-static and called from a static context
|
||||
* @throws StaticInitializerException when an the static initializer fails
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Nullable
|
||||
public Object invoke() throws NoAccessException, InvocationTargetException, UnexpectedThrowableException {
|
||||
public Object invoke() throws UnexpectedThrowableException, NoAccessException, InvalidMethodSignature, InvocationTargetException, InstanceMethodFromStaticContextException, StaticInitializerException {
|
||||
return invoke(new Object[0]);
|
||||
}
|
||||
|
||||
|
@ -359,13 +366,16 @@ public final class ReflectionMethod {
|
|||
* Invokes the method.
|
||||
*
|
||||
* @return method return value
|
||||
* @throws NoAccessException if access to the method has been denied
|
||||
* @throws InvocationTargetException covers exceptions thrown by the method
|
||||
* @throws UnexpectedThrowableException if the {@code modifiers} field could not be found
|
||||
* @throws NoAccessException if access to the method has been denied
|
||||
* @throws InvalidMethodSignature if the method signature is incorrect
|
||||
* @throws InvocationTargetException covers exceptions thrown by the method
|
||||
* @throws InstanceMethodFromStaticContextException when the target method is non-static and called from a static context
|
||||
* @throws StaticInitializerException when an the static initializer fails
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@Nullable
|
||||
public Object invoke(Object... args) throws NoAccessException, InvocationTargetException, UnexpectedThrowableException {
|
||||
public Object invoke(Object... args) throws UnexpectedThrowableException, NoAccessException, InvalidMethodSignature, InvocationTargetException, InstanceMethodFromStaticContextException, StaticInitializerException {
|
||||
Object returnValue;
|
||||
|
||||
// Allow access to method
|
||||
|
@ -377,6 +387,12 @@ public final class ReflectionMethod {
|
|||
} catch (IllegalAccessException exception) {
|
||||
//ReflectionAccessWidener.lockModifications(this, updatedModifiers); // Lock method before throwing exception
|
||||
throw new NoAccessException("method", getName());
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new InvalidMethodSignature(getName());
|
||||
} catch (NullPointerException exception) {
|
||||
throw new InstanceMethodFromStaticContextException(getName());
|
||||
} catch (ExceptionInInitializerError exception) {
|
||||
throw new StaticInitializerException(exception.getCause());
|
||||
}
|
||||
|
||||
// Return return value from method
|
||||
|
|
|
@ -21,14 +21,8 @@ package de.staropensource.sosengine.graphics.events;
|
|||
|
||||
import de.staropensource.sosengine.base.classes.Event;
|
||||
import de.staropensource.sosengine.base.classes.helpers.EventHelper;
|
||||
import de.staropensource.sosengine.base.events.LogEvent;
|
||||
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||
import de.staropensource.sosengine.base.types.logging.LogLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Called when a graphics error occurs.
|
||||
*
|
||||
|
@ -44,7 +38,7 @@ public class GraphicsApiErrorEvent implements Event {
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
* @deprecated use the {@code callEvent} method with arguments
|
||||
* @see LogEvent#callEvent(LogLevel, LogIssuer, String)
|
||||
* @see #callEvent(String)
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
|
@ -57,12 +51,6 @@ public class GraphicsApiErrorEvent implements Event {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
public void callEvent(@NotNull String error) {
|
||||
EventHelper.logCall(getClass());
|
||||
|
||||
for (Method method : EventHelper.getAnnotatedMethods(getClass())) {
|
||||
try {
|
||||
method.invoke(null, error);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {}
|
||||
}
|
||||
EventHelper.invokeAnnotatedMethods(getClass(), error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,6 @@ import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
|||
import de.staropensource.sosengine.base.types.logging.LogLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Called when a graphics error occurs.
|
||||
*
|
||||
|
@ -57,12 +54,6 @@ public class GraphicsErrorEvent implements Event {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
public void callEvent(@NotNull String error) {
|
||||
EventHelper.logCall(getClass());
|
||||
|
||||
for (Method method : EventHelper.getAnnotatedMethods(getClass())) {
|
||||
try {
|
||||
method.invoke(null, error);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NullPointerException | ExceptionInInitializerError ignored) {}
|
||||
}
|
||||
EventHelper.invokeAnnotatedMethods(getClass(), error);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue