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 2a9af66..b841253 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/Engine.java +++ b/base/src/main/java/de/staropensource/sosengine/base/Engine.java @@ -26,6 +26,7 @@ import de.staropensource.sosengine.base.classes.helpers.EventHelper; import de.staropensource.sosengine.base.data.information.EngineInformation; import de.staropensource.sosengine.base.data.versioning.StarOpenSourceVersioningSystem; import de.staropensource.sosengine.base.events.*; +import de.staropensource.sosengine.base.exceptions.NoAccessException; import de.staropensource.sosengine.base.exceptions.dependency.UnmetDependenciesException; import de.staropensource.sosengine.base.internal.events.InternalEngineShutdownEvent; import de.staropensource.sosengine.base.internal.types.DependencySubsystemVector; @@ -33,6 +34,7 @@ import de.staropensource.sosengine.base.logging.CrashHandler; import de.staropensource.sosengine.base.logging.Logger; import de.staropensource.sosengine.base.logging.LoggerInstance; import de.staropensource.sosengine.base.types.DependencyVector; +import de.staropensource.sosengine.base.types.EngineState; import de.staropensource.sosengine.base.types.immutable.ImmutableLinkedList; import de.staropensource.sosengine.base.utility.DependencyResolver; import de.staropensource.sosengine.base.utility.Miscellaneous; @@ -92,17 +94,17 @@ public final class Engine extends SubsystemClass { private static LoggerInstance logger; /** - * Contains if the engine is shutting down. + * Contains the engine state. * - * @since v1-alpha1 + * @since v1-alpha2 * -- GETTER -- - * Returns if the engine is shutting down. + * Returns the engine state. * - * @return shutdown status - * @since v1-alpha1 + * @return shutdown state + * @since v1-alpha2 */ @Getter - private boolean shuttingDown = false; + private @NotNull EngineState state = EngineState.UNKNOWN; /** * Contains the engine's shutdown handler. @@ -160,6 +162,8 @@ public final class Engine extends SubsystemClass { return; long initTime = Miscellaneous.measureExecutionTime(() -> { + state = EngineState.STARTUP; + // Initialize engine configuration new EngineConfiguration(); EngineConfiguration.getInstance().loadConfiguration(); @@ -185,6 +189,7 @@ public final class Engine extends SubsystemClass { } }); + state = EngineState.RUNNING; logger.info("Initialized sos!engine %engine_version% (commit %engine_git_commit_id_long%-%engine_git_branch%, dirty %engine_git_dirty%) in " + initTime + "ms"); } @@ -389,10 +394,9 @@ public final class Engine extends SubsystemClass { * @since v1-alpha0 */ public synchronized void shutdown(@Range(from = 0, to = 255) int exitCode) { - if (shuttingDown) { - logger.error("Already shutting down"); - return; - } + logger.info("Shutting engine down"); + if (state != EngineState.CRASHED) + state = EngineState.SHUTDOWN; // Make engine single-threaded Properties properties = new Properties(); @@ -403,16 +407,13 @@ public final class Engine extends SubsystemClass { // Flush log messages Logger.flushLogMessages(); - logger.info("Shutting engine down"); - shuttingDown = true; - logger.verb("Notifiying classes about shutdown"); new EngineShutdownEvent().callEvent(); logger.verb("Notifying subsystems about shutdown"); new InternalEngineShutdownEvent().callEvent(); - logger.verb("Shutting down JVM with code " + exitCode); + logger.verb("Invoking shutdown handler (code " + exitCode + ")"); shutdownHandler.shutdown((short) exitCode); } @@ -442,6 +443,20 @@ public final class Engine extends SubsystemClass { return new DependencyVector("engine", StarOpenSourceVersioningSystem.class, EngineInformation.getVersioningString()); } + /** + * Sets the engine state. + * + * @param state new state + * @throws NoAccessException if the caller class is unauthorized + * @since v1-alpha2 + */ + public void setState(@NotNull EngineState state) throws NoAccessException { + if (!Thread.currentThread().getStackTrace()[2].getClassName().startsWith("de.staropensource.sosengine.base.")) + throw new NoAccessException("Only classes inside the \"de.staropensource.sosengine.base\" package are allowed to call this method."); + + this.state = state; + } + /** * The default shutdown handler, which causes the JVM to exit. * @@ -460,6 +475,8 @@ public final class Engine extends SubsystemClass { /** {@inheritDoc} */ @Override public void shutdown(short exitCode) { + logger.warn("Terminating JVM"); + System.exit(exitCode); } } diff --git a/base/src/main/java/de/staropensource/sosengine/base/exceptions/NoAccessException.java b/base/src/main/java/de/staropensource/sosengine/base/exceptions/NoAccessException.java new file mode 100644 index 0000000..8af0b8b --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/exceptions/NoAccessException.java @@ -0,0 +1,50 @@ +/* + * 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.exceptions; + +import org.jetbrains.annotations.NotNull; + +/** + * Thrown when the caller class is not allowed to call the throwing method. + *

+ * Not to be confused with {@link de.staropensource.sosengine.base.exceptions.reflection.NoAccessException}, + * which handles access violations of reflection objects. + * + * @since v1-alpha2 + */ +@SuppressWarnings({ "unused" }) +public class NoAccessException extends RuntimeException { + /** + * Constructs this exception. + * + * @since v1-alpha2 + */ + public NoAccessException() {} + + /** + * Constructs this exception. + * + * @param message message + * @since v1-alpha2 + */ + public NoAccessException(@NotNull String message) { + super(message); + } +} 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 99d3e5d..49a1272 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 @@ -45,7 +45,6 @@ import java.util.List; */ @SuppressWarnings({ "unused", "JavadocDeclaration" }) public final class CrashHandler { - /** * Contains the template used to print a crash report. * @@ -117,6 +116,8 @@ Dear developer: FIX YOUR GODDAMN SHIT! Please check if your code or 3rd party su * @since v1-alpha0 */ public static synchronized void handleCrash(@NotNull Class issuerClass, @NotNull String issuerOrigin, @Nullable String issuerMetadata, @NotNull String message, @Nullable Throwable throwable, boolean throwableHandled) { + Engine.getInstance().setState(EngineState.CRASHED); + if (throwable == null) throwableHandled = false; diff --git a/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java b/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java new file mode 100644 index 0000000..0af32cd --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/types/EngineState.java @@ -0,0 +1,68 @@ +/* + * 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.types; + +/** + * Determines in which state the engine is currently in. + * + * @since v1-alpha2 + */ +@SuppressWarnings({ "unused" }) +public enum EngineState { + /** + * The state of the engine is currently unknown. + * The engine likely has not been initialized yet. + * + * @since v1-alpha2 + */ + UNKNOWN, + + /** + * The engine is currently starting up. + * Some parts of the engine may not be initialized + * yet and may be unsafe to access. + * + * @since v1-alpha2 + */ + STARTUP, + + /** + * The engine is in normal operation mode. + * + * @since v1-alpha2 + */ + RUNNING, + + /** + * The engine has crashed, either by itself or the application. + * + * @since v1-alpha2 + */ + CRASHED, + + /** + * The engine is shutting down. + * Some parts of the engine may have already + * shut down and may be unsafe to access. + * + * @since v1-alpha2 + */ + SHUTDOWN, +}