diff --git a/chunky/src/java/se/llbit/chunky/main/Chunky.java b/chunky/src/java/se/llbit/chunky/main/Chunky.java index 674ec7e04b..2ed96cbf65 100644 --- a/chunky/src/java/se/llbit/chunky/main/Chunky.java +++ b/chunky/src/java/se/llbit/chunky/main/Chunky.java @@ -44,6 +44,7 @@ import se.llbit.chunky.world.MaterialStore; import se.llbit.json.JsonArray; import se.llbit.json.JsonValue; +import se.llbit.log.ConsoleReceiver; import se.llbit.log.Level; import se.llbit.log.Log; import se.llbit.log.Receiver; @@ -237,6 +238,8 @@ public static void main(final String[] args) { break; } } catch (Throwable t) { + // set receiver in case an exception was thrown before it was set in one of the start modes. + Log.setReceiver(ConsoleReceiver.INSTANCE, Level.INFO, Level.WARNING, Level.ERROR); Log.error("Unchecked exception caused Chunky to close.", t); exitCode = 2; } diff --git a/lib/src/se/llbit/log/BufferingConsoleReceiver.java b/lib/src/se/llbit/log/BufferingConsoleReceiver.java new file mode 100644 index 0000000000..a20277ee2a --- /dev/null +++ b/lib/src/se/llbit/log/BufferingConsoleReceiver.java @@ -0,0 +1,28 @@ +package se.llbit.log; + +import java.util.ArrayList; +import java.util.List; + +public class BufferingConsoleReceiver extends Receiver { + public static final BufferingConsoleReceiver INSTANCE = new BufferingConsoleReceiver(); + + private final List bufferedEvents = new ArrayList<>(); + + protected BufferingConsoleReceiver() { + } + + @Override + public void logEvent(Level level, String message) { + this.bufferedEvents.add(new Event(level, message)); + } + + @Override + public boolean isBuffered() { + return true; + } + + @Override + public List getBufferedEvents() { + return this.bufferedEvents; + } +} diff --git a/lib/src/se/llbit/log/Log.java b/lib/src/se/llbit/log/Log.java index 542110dfbe..09ac9bbdb8 100644 --- a/lib/src/se/llbit/log/Log.java +++ b/lib/src/se/llbit/log/Log.java @@ -29,7 +29,7 @@ public class Log { private static final int WARNING = Level.WARNING.ordinal(); private static final int ERROR = Level.ERROR.ordinal(); private static final Receiver[] receiver = - {ConsoleReceiver.INSTANCE, ConsoleReceiver.INSTANCE, ConsoleReceiver.INSTANCE}; + {BufferingConsoleReceiver.INSTANCE, BufferingConsoleReceiver.INSTANCE, BufferingConsoleReceiver.INSTANCE}; static { try { @@ -51,7 +51,15 @@ public static void setReceiver(Receiver receiver, Level... levels) { throw new IllegalArgumentException("No log level specified for receiver."); } for (Level level : levels) { + Receiver previousReceiver = Log.receiver[level.ordinal()]; Log.receiver[level.ordinal()] = receiver; + + // flush the buffered receiver, if required. + if (previousReceiver.isBuffered()) { + previousReceiver.getBufferedEvents().stream() + .filter(event -> event.level == level) + .forEach(event -> receiver.logEvent(event.level, event.message)); + } } } diff --git a/lib/src/se/llbit/log/Receiver.java b/lib/src/se/llbit/log/Receiver.java index 03e8a56aca..e836b8c387 100644 --- a/lib/src/se/llbit/log/Receiver.java +++ b/lib/src/se/llbit/log/Receiver.java @@ -18,6 +18,8 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Collections; +import java.util.List; abstract public class Receiver { abstract public void logEvent(Level level, String message); @@ -37,4 +39,21 @@ public void logEvent(Level level, Throwable thrown) { logEvent(level, writer.toString()); } + public boolean isBuffered() { + return false; + } + + public List getBufferedEvents() { + return Collections.emptyList(); + } + + public static class Event { + public final Level level; + public final String message; + + public Event(Level level, String message) { + this.level = level; + this.message = message; + } + } }