package com.hypixel.hytale.logger.backend; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.LogRecord; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class HytaleFileHandler extends Thread { public static final DateTimeFormatter LOG_FILE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"); public static final HytaleFileHandler INSTANCE = new HytaleFileHandler(); private final BlockingQueue logRecords = new LinkedBlockingQueue<>(); @Nullable private FileHandler fileHandler; public HytaleFileHandler() { super("HytaleLogger"); this.setDaemon(true); } @Override public void run() { if (this.fileHandler == null) { throw new IllegalStateException("Thread should not be started when no file handler exists!"); } else { try { while (!this.isInterrupted()) { this.fileHandler.publish(this.logRecords.take()); } } catch (InterruptedException var2) { Thread.currentThread().interrupt(); } } } @Nullable public FileHandler getFileHandler() { return this.fileHandler; } public void enable() { if (this.fileHandler != null) { throw new IllegalStateException("Already enabled!"); } else { try { Path logsDirectory = Paths.get("logs/"); if (!Files.isDirectory(logsDirectory)) { Files.createDirectory(logsDirectory); } String fileNamePart = "logs/" + LOG_FILE_DATE_FORMAT.format(LocalDateTime.now()); String fileName = fileNamePart + "_server.log"; if (Files.exists(Paths.get(fileName))) { fileName = fileNamePart + "%u_server.log"; } this.fileHandler = new FileHandler(fileName); this.fileHandler.setEncoding("UTF-8"); this.fileHandler.setLevel(Level.ALL); this.fileHandler.setFormatter(new HytaleLogFormatter(() -> false)); } catch (IOException var4) { throw new RuntimeException("Failed to create file handler!", var4); } this.start(); } } public void log(@Nonnull LogRecord logRecord) { if (!this.isAlive()) { if (this.fileHandler != null) { this.fileHandler.publish(logRecord); } } else { this.logRecords.add(logRecord); } } public void shutdown() { if (this.fileHandler != null) { this.interrupt(); try { this.join(); } catch (InterruptedException var2) { Thread.currentThread().interrupt(); } List list = new ObjectArrayList(); this.logRecords.drainTo(list); list.forEach(this.fileHandler::publish); this.fileHandler.flush(); this.fileHandler.close(); this.fileHandler = null; } } }