host.anzo.core.startup.StartupManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-core Show documentation
Show all versions of commons-core Show documentation
Commons library to make me happy.
package host.anzo.core.startup;
import host.anzo.commons.enums.ConsoleColors;
import host.anzo.commons.utils.ClassUtils;
import host.anzo.commons.utils.ConsoleUtils;
import host.anzo.commons.utils.SystemdUtils;
import host.anzo.commons.versioning.Version;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import host.anzo.classindex.ClassIndex;
import org.fusesource.jansi.AnsiConsole;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
* @author ANZO
* @since 27.12.2016
*/
@Slf4j
@StartupComponent("BeforeStart")
public class StartupManager {
@Getter(lazy=true)
private final static StartupManager instance = new StartupManager();
private @Getter long loadStartTime;
private @Getter long loadEndTime;
private boolean isStartupCompleted = false;
private final AtomicBoolean isShutDowning = new AtomicBoolean(false);
private StartupManager() {
System.setProperty("org.jooq.no-tips", "true");
System.setProperty("org.jooq.no-logo", "true");
AnsiConsole.systemInstall();
new File("./log/").mkdir();
try {
Version.getInstance().init(Class.forName(Thread.currentThread().getStackTrace()[4].getClassName()));
} catch (ClassNotFoundException ignored) {
}
ConsoleUtils.printSection("System Information");
log.info("Operating System: {} Build: {}, Arch: {}", System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"));
log.info("Available CPU(s): {}", Runtime.getRuntime().availableProcessors());
log.info("CPU Identifier: {}", System.getenv("PROCESSOR_IDENTIFIER"));
log.info("JVM: {} Build: {}", System.getProperty("java.vm.name"), System.getProperty("java.runtime.version"));
}
public > void startup(@NotNull Class sl) {
loadStartTime = System.currentTimeMillis();
final StartupInstance startup = new StartupInstance<>();
for(Class> clazz : ClassIndex.getAnnotated(StartupComponent.class)) {
final StartupComponent startupAnnotation = clazz.getAnnotation(StartupComponent.class);
SL key = null;
try {
key = Enum.valueOf(sl, startupAnnotation.value());
}
catch (Exception ignored) {
}
if (key != null) {
try {
final StartModule module = new StartModule<>(key, clazz);
startup.put(key, module);
}
catch (Exception e) {
log.error("Error while loading class [{}] with [{}] StartupLevel", clazz.getSimpleName(), startupAnnotation.value(), e);
}
}
}
// Assign before/after methods to proper startup modules
for (SL startupLevel : sl.getEnumConstants()) {
final List> modules = startup.get(startupLevel);
if (modules != null) {
for (StartModule module : modules) {
for (Map.Entry> entry : module.getBeforeMethods().entrySet()) {
final IStartupLevel otherStartupLevel = (IStartupLevel)Enum.valueOf(sl, entry.getKey());
for (StartupMethodInfo method : entry.getValue()) {
otherStartupLevel.addBefore(method);
}
}
for (Map.Entry> entry : module.getAfterMethods().entrySet()) {
final IStartupLevel otherStartupLevel = (IStartupLevel)Enum.valueOf(sl, entry.getKey());
for (StartupMethodInfo method : entry.getValue()) {
otherStartupLevel.addAfter(method);
}
}
}
}
}
for(Map.Entry>> entry : startup.getAll()) {
final List> invalidModules = new ArrayList<>();
final List> modules = entry.getValue();
for(StartModule module : modules) {
final Class> clazz = module.getClazz();
final Class>[] dependency = clazz.getAnnotation(StartupComponent.class).dependency();
for(Class> dep : dependency) {
final Optional> dependencyModule = modules.stream()
.filter(m -> m.getClazz().getCanonicalName().equals(dep.getCanonicalName()))
.findAny();
if(dependencyModule.isPresent()) {
module.addDependency(dependencyModule.get());
} else {
invalidModules.add(module);
log.warn("Not found dependency ({}) for {} on {} start level.", dep.getCanonicalName(), clazz.getCanonicalName(), module.getStartLevel().name());
}
}
}
modules.removeAll(invalidModules);
}
// Run registered components
for (SL startupLevel : sl.getEnumConstants()) {
ConsoleUtils.printSection(startupLevel.name(), ConsoleColors.Cyan);
final IStartupLevel startupInterface = ((IStartupLevel)startupLevel);
startupInterface.runBeforeMethods();
startupInterface.before();
if(startup.levelExists(startupLevel)) {
startup.runLevel(startupLevel);
}
else {
log.warn("No services found with level [{}] in current server instance! Consider to remove it from StartupLevel routine.", startupLevel);
}
startupInterface.runAfterMethods();
startupInterface.after();
}
isStartupCompleted = true;
loadEndTime = System.currentTimeMillis();
SystemdUtils.notifyReady();
log.info("{}Server loaded in [{}] second(s){}", ConsoleColors.Cyan.color(), getStartupTime(TimeUnit.SECONDS), ConsoleColors.Normal.color());
}
public void shutdown() {
if (this.isShutDowning.compareAndSet(false, true)) {
final Map>> classes = ClassIndex.getAnnotated(StartupComponent.class).stream()
.filter(IShutdownable.class::isAssignableFrom).collect(Collectors.groupingBy(item -> {
final StartupComponent component = item.getAnnotation(StartupComponent.class);
if (component != null) {
return component.shutdownPriority();
}
// TODO: Can happen for abstract methods (example: NetworkManager)
return EShutdownPriority.ORDINAL;
}));
for (EShutdownPriority shutdownPriority : EShutdownPriority.values()) {
final List> classesByPriority = classes.get(shutdownPriority);
if (classesByPriority != null) {
for (Class> clazz : classesByPriority) {
final Object singletonObject = ClassUtils.singletonInstance(clazz);
if (singletonObject != null) {
final IShutdownable shutdownable = (IShutdownable)singletonObject;
try {
log.info("Invoking [{}] onShutdown...", shutdownable.getClass().getSimpleName());
shutdownable.onShutdown();
}
catch (Exception e) {
log.error("Error while invoking [{}] onShutdown",shutdownable.getClass().getSimpleName(), e);
}
}
else {
log.error("Can't find singleton for IShutdownable=[{}]", clazz.getSimpleName());
}
}
}
}
log.info("Server shutdown routine complete!");
}
}
/**
* @return {@code true} if server startup routine completed, {@code false} otherwise
*/
public boolean isStartupCompleted() {
return isStartupCompleted;
}
/**
* @return {@code true} if server doing shutdown routine at this moment, {@code false} otherwise
*/
public boolean isShutDowning() {
return isShutDowning.get();
}
/**
* @param timeUnit time unit
* @return application loading time
*/
public long getStartupTime(@NotNull TimeUnit timeUnit) {
return timeUnit.convert(loadEndTime - loadStartTime, TimeUnit.MILLISECONDS);
}
/**
* @param timeUnit time unit
* @return application uptime
*/
public int getUptime(@NotNull TimeUnit timeUnit) {
return (int)timeUnit.convert(System.currentTimeMillis() - loadStartTime, TimeUnit.MILLISECONDS);
}
}