Improved concurrency, annotations
This commit is contained in:
@@ -5,6 +5,7 @@ import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
@@ -18,9 +19,8 @@ import mightypork.rogue.input.InputSystem;
|
||||
import mightypork.rogue.input.KeyStroke;
|
||||
import mightypork.rogue.render.DisplaySystem;
|
||||
import mightypork.rogue.sound.SoundSystem;
|
||||
import mightypork.rogue.util.SlickLogRedirector;
|
||||
import mightypork.utils.control.bus.EventBus;
|
||||
import mightypork.utils.control.bus.events.DestroyEvent;
|
||||
import mightypork.utils.control.bus.events.UpdateEvent;
|
||||
import mightypork.utils.control.interf.Destroyable;
|
||||
import mightypork.utils.control.interf.Updateable;
|
||||
import mightypork.utils.logging.Log;
|
||||
@@ -105,8 +105,10 @@ public class App implements AppAccess {
|
||||
{
|
||||
Log.i("Shutting down subsystems...");
|
||||
|
||||
if(bus() != null) {
|
||||
bus().send(new DestroyEvent());
|
||||
bus().destroy();
|
||||
}
|
||||
|
||||
Log.i("Terminating...");
|
||||
System.exit(0);
|
||||
@@ -124,8 +126,11 @@ public class App implements AppAccess {
|
||||
* Setup logging
|
||||
*/
|
||||
final LogInstance log = Log.create("runtime", Paths.LOGS, 10);
|
||||
log.setFileLevel(Level.WARNING);
|
||||
log.setSysoutLevel(Level.ALL);
|
||||
log.enable(Config.LOGGING_ENABLED);
|
||||
log.enableSysout(Config.LOG_TO_STDOUT);
|
||||
org.newdawn.slick.util.Log.setLogSystem(new SlickLogRedirector(log));
|
||||
|
||||
Log.f1("Initializing subsystems...");
|
||||
|
||||
@@ -134,7 +139,6 @@ public class App implements AppAccess {
|
||||
*/
|
||||
Log.f2("Initializing Event Bus...");
|
||||
eventBus = new EventBus();
|
||||
eventBus.enableLogging(Config.LOG_BUS);
|
||||
initChannels();
|
||||
|
||||
/*
|
||||
@@ -236,7 +240,7 @@ public class App implements AppAccess {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
bus().queue(new ActionRequest(RequestType.FULLSCREEN));
|
||||
bus().send(new ActionRequest(RequestType.FULLSCREEN));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -246,7 +250,7 @@ public class App implements AppAccess {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
bus().queue(new ActionRequest(RequestType.SCREENSHOT));
|
||||
bus().send(new ActionRequest(RequestType.SCREENSHOT));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -256,7 +260,7 @@ public class App implements AppAccess {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
bus().queue(new ActionRequest(RequestType.SHUTDOWN));
|
||||
bus().send(new ActionRequest(RequestType.SHUTDOWN));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,6 +76,4 @@ public class Config {
|
||||
public static boolean LOG_TO_STDOUT = true;
|
||||
public static boolean SINGLE_INSTANCE = true;
|
||||
|
||||
public static boolean LOG_BUS = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import mightypork.rogue.bus.Subsystem;
|
||||
import mightypork.rogue.bus.events.ActionRequest;
|
||||
import mightypork.rogue.bus.events.UpdateEvent;
|
||||
import mightypork.rogue.bus.events.ActionRequest.RequestType;
|
||||
import mightypork.rogue.bus.events.MainLoopTaskRequest;
|
||||
import mightypork.rogue.tasks.TaskTakeScreenshot;
|
||||
import mightypork.rogue.util.Utils;
|
||||
import mightypork.utils.control.bus.events.UpdateEvent;
|
||||
import mightypork.utils.control.timing.TimerDelta;
|
||||
|
||||
|
||||
@@ -38,17 +38,17 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener, MainL
|
||||
timer = new TimerDelta();
|
||||
|
||||
while (running) {
|
||||
Runnable r;
|
||||
while ((r = taskQueue.poll()) != null) {
|
||||
r.run();
|
||||
}
|
||||
|
||||
disp().beginFrame();
|
||||
|
||||
bus().send(new UpdateEvent(timer.getDelta()));
|
||||
|
||||
for (final Runnable r : regularTasks) {
|
||||
r.run();
|
||||
}
|
||||
|
||||
Runnable r;
|
||||
while ((r = taskQueue.poll()) != null) {
|
||||
r.run();
|
||||
for (final Runnable r2 : regularTasks) {
|
||||
r2.run();
|
||||
}
|
||||
|
||||
disp().endFrame();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.SingularEvent;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.control.bus.events.types.SingularEvent;
|
||||
|
||||
|
||||
/**
|
||||
@@ -11,6 +12,7 @@ import mightypork.utils.control.bus.SingularEvent;
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SingularEvent
|
||||
@QueuedEvent
|
||||
public class ActionRequest implements Event<ActionRequest.Listener> {
|
||||
|
||||
private final RequestType type;
|
||||
|
||||
+4
-2
@@ -1,7 +1,8 @@
|
||||
package mightypork.utils.control.bus.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.ImmediateEvent;
|
||||
import mightypork.utils.control.interf.Destroyable;
|
||||
|
||||
|
||||
@@ -10,6 +11,7 @@ import mightypork.utils.control.interf.Destroyable;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@ImmediateEvent
|
||||
public class DestroyEvent implements Event<Destroyable> {
|
||||
|
||||
@Override
|
||||
@@ -1,7 +1,8 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
@@ -11,6 +12,7 @@ import org.lwjgl.input.Keyboard;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@QueuedEvent
|
||||
public class KeyboardEvent implements Event<KeyboardEvent.Listener> {
|
||||
|
||||
private final int key;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.SingularEvent;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.control.bus.events.types.SingularEvent;
|
||||
|
||||
|
||||
/**
|
||||
@@ -11,6 +12,7 @@ import mightypork.utils.control.bus.SingularEvent;
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SingularEvent
|
||||
@QueuedEvent
|
||||
public class MainLoopTaskRequest implements Event<MainLoopTaskRequest.Listener> {
|
||||
|
||||
private final Runnable task;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
|
||||
|
||||
@@ -10,6 +11,7 @@ import mightypork.utils.math.coord.Coord;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@QueuedEvent
|
||||
public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
|
||||
|
||||
public static final int BUTTON_LEFT = 0;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
|
||||
|
||||
@@ -10,6 +11,7 @@ import mightypork.utils.math.coord.Coord;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@QueuedEvent
|
||||
public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> {
|
||||
|
||||
private final Coord move;
|
||||
|
||||
@@ -2,8 +2,9 @@ package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.rogue.loading.DeferredResource;
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.SingularEvent;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.control.bus.events.types.SingularEvent;
|
||||
|
||||
|
||||
/**
|
||||
@@ -12,6 +13,7 @@ import mightypork.utils.control.bus.SingularEvent;
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SingularEvent
|
||||
@QueuedEvent
|
||||
public class ResourceLoadRequest implements Event<ResourceLoadRequest.Listener> {
|
||||
|
||||
private final DeferredResource resource;
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.math.coord.Coord;
|
||||
|
||||
|
||||
/**
|
||||
* Screen resolution or mode was changed
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@QueuedEvent
|
||||
public class ScreenChangeEvent implements Event<ScreenChangeEvent.Listener> {
|
||||
|
||||
private final boolean fullscreen;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.SingularEvent;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.control.bus.events.types.SingularEvent;
|
||||
|
||||
|
||||
/**
|
||||
@@ -11,6 +12,7 @@ import mightypork.utils.control.bus.SingularEvent;
|
||||
* @author MightyPork
|
||||
*/
|
||||
@SingularEvent
|
||||
@QueuedEvent
|
||||
public class ScreenRequestEvent implements Event<ScreenRequestEvent.Listener> {
|
||||
|
||||
private final String scrName;
|
||||
|
||||
+5
-2
@@ -1,7 +1,8 @@
|
||||
package mightypork.utils.control.bus.events;
|
||||
package mightypork.rogue.bus.events;
|
||||
|
||||
|
||||
import mightypork.utils.control.bus.Event;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.ImmediateEvent;
|
||||
import mightypork.utils.control.interf.Updateable;
|
||||
|
||||
|
||||
@@ -10,6 +11,8 @@ import mightypork.utils.control.interf.Updateable;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
// sending via queue would hog the bus
|
||||
@ImmediateEvent
|
||||
public class UpdateEvent implements Event<Updateable> {
|
||||
|
||||
private final double deltaTime;
|
||||
@@ -36,7 +36,7 @@ public class FontBank extends AppAdapter {
|
||||
*/
|
||||
public void loadFont(String key, DeferredFont font)
|
||||
{
|
||||
bus().queue(new ResourceLoadRequest(font));
|
||||
bus().send(new ResourceLoadRequest(font));
|
||||
|
||||
fonts.put(key, font);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ScreenTestBouncy extends LayeredScreen {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
bus().queue(new ScreenRequestEvent("test.cat"));
|
||||
bus().send(new ScreenRequestEvent("test.cat"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ScreenTestCat extends LayeredScreen {
|
||||
public void run()
|
||||
{
|
||||
snd().fadeOutAllLoops();
|
||||
bus().schedule(new ActionRequest(RequestType.SHUTDOWN), 3);
|
||||
bus().sendDelayed(new ActionRequest(RequestType.SHUTDOWN), 3);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ScreenTestCat extends LayeredScreen {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
bus().queue(new ScreenRequestEvent("test.bouncy"));
|
||||
bus().send(new ScreenRequestEvent("test.bouncy"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,14 +92,14 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
|
||||
wasMouse = true;
|
||||
}
|
||||
|
||||
if (wasMouse && !moveSum.isZero()) bus().queue(new MouseMotionEvent(lastPos, moveSum));
|
||||
if (wasMouse && !moveSum.isZero()) bus().send(new MouseMotionEvent(lastPos, moveSum));
|
||||
|
||||
while (Keyboard.next()) {
|
||||
onKeyEvent();
|
||||
}
|
||||
|
||||
if (Display.isCloseRequested()) {
|
||||
bus().queue(new ActionRequest(RequestType.SHUTDOWN));
|
||||
bus().send(new ActionRequest(RequestType.SHUTDOWN));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
|
||||
}
|
||||
|
||||
if (button != -1 || wheeld != 0) {
|
||||
bus().queue(new MouseButtonEvent(pos, button, down, wheeld));
|
||||
bus().send(new MouseButtonEvent(pos, button, down, wheeld));
|
||||
}
|
||||
|
||||
moveSum.add_ip(move);
|
||||
@@ -132,7 +132,7 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
|
||||
final boolean down = Keyboard.getEventKeyState();
|
||||
final char c = Keyboard.getEventCharacter();
|
||||
|
||||
bus().queue(new KeyboardEvent(key, c, down));
|
||||
bus().send(new KeyboardEvent(key, c, down));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,10 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
|
||||
|
||||
// textures & fonts needs to be loaded in main thread
|
||||
if (def.getClass().isAnnotationPresent(MustLoadInMainThread.class)) {
|
||||
app.bus().queue(new MainLoopTaskRequest(new Runnable() {
|
||||
|
||||
Log.f3("<LOADER> Loading in main thread:\n "+Log.str(def));
|
||||
|
||||
app.bus().send(new MainLoopTaskRequest(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
@@ -75,6 +78,8 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
|
||||
continue;
|
||||
}
|
||||
|
||||
Log.f3("<LOADER> Loading async:\n "+Log.str(def));
|
||||
|
||||
exs.submit(new Runnable() {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,28 +27,28 @@ public abstract class BaseDeferredResource implements DeferredResource, Destroya
|
||||
@Override
|
||||
public synchronized final void load()
|
||||
{
|
||||
|
||||
if (loadAttempted) return;
|
||||
|
||||
loadAttempted = true;
|
||||
loadFailed = false;
|
||||
|
||||
if (isNull()) return;
|
||||
try {
|
||||
if (resource == null) throw new NullPointerException("Resource string cannot be null for non-null resource.");
|
||||
|
||||
Log.f3("<res> Loading: " + this);
|
||||
Log.f3("<RES> Loading: " + this);
|
||||
loadResource(resource);
|
||||
Log.f3("<res> Loaded: " + this + " loaded.");
|
||||
Log.f3("<RES> Loaded: " + this + " loaded.");
|
||||
} catch (final Exception e) {
|
||||
loadFailed = true;
|
||||
Log.e("Failed to load resource \"" + resource + "\"", e);
|
||||
Log.e("<RES> Failed to load \"" + resource + "\"", e);
|
||||
}
|
||||
|
||||
loadAttempted = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized final boolean isLoaded()
|
||||
public final boolean isLoaded()
|
||||
{
|
||||
if (isNull()) return false;
|
||||
|
||||
@@ -68,6 +68,7 @@ public abstract class BaseDeferredResource implements DeferredResource, Destroya
|
||||
if (isLoaded()) {
|
||||
return true;
|
||||
} else {
|
||||
Log.w("<RES> First use, not loaded yet - loading directly\n"+this);
|
||||
load();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ public class DisplaySystem extends Subsystem implements ConstraintContext {
|
||||
Display.update();
|
||||
}
|
||||
|
||||
bus().queue(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
bus().send(new ScreenChangeEvent(true, Display.isFullscreen(), getSize()));
|
||||
|
||||
} catch (final Throwable t) {
|
||||
Log.e("Failed to toggle fullscreen mode.", t);
|
||||
@@ -166,7 +166,7 @@ public class DisplaySystem extends Subsystem implements ConstraintContext {
|
||||
{
|
||||
// handle resize
|
||||
if (Display.wasResized()) {
|
||||
bus().queue(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
bus().send(new ScreenChangeEvent(false, Display.isFullscreen(), getSize()));
|
||||
}
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
@@ -225,7 +225,7 @@ public class DeferredAudio extends BaseDeferredResource {
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
if (!isLoaded()) return;
|
||||
if (!isLoaded() || backingAudio == null) return;
|
||||
|
||||
backingAudio.release();
|
||||
backingAudio = null;
|
||||
|
||||
@@ -149,7 +149,7 @@ public class SoundSystem extends Subsystem implements Updateable {
|
||||
private DeferredAudio getResource(String res)
|
||||
{
|
||||
final DeferredAudio a = new DeferredAudio(res);
|
||||
bus().queue(new ResourceLoadRequest(a));
|
||||
bus().send(new ResourceLoadRequest(a));
|
||||
|
||||
if (resources.contains(a)) throw new IllegalArgumentException("Sound resource " + res + " is already registered.");
|
||||
resources.add(a);
|
||||
|
||||
@@ -58,7 +58,7 @@ public class TextureBank extends AppAdapter {
|
||||
tx.setFilter(filter_min, filter_mag);
|
||||
tx.setWrap(wrap);
|
||||
|
||||
bus().queue(new ResourceLoadRequest(tx));
|
||||
bus().send(new ResourceLoadRequest(tx));
|
||||
|
||||
textures.put(key, tx);
|
||||
lastTx = tx;
|
||||
|
||||
@@ -5,6 +5,10 @@ import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.ImmediateEvent;
|
||||
import mightypork.utils.control.bus.events.types.QueuedEvent;
|
||||
import mightypork.utils.control.bus.events.types.SingularEvent;
|
||||
import mightypork.utils.control.interf.Destroyable;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
@@ -23,17 +27,16 @@ final public class EventBus implements Destroyable {
|
||||
private final BufferedHashSet<Object> clients = new BufferedHashSet<Object>();
|
||||
|
||||
/** Messages queued for delivery */
|
||||
private final DelayQueue<DelayedMessage> sendQueue = new DelayQueue<DelayedMessage>();
|
||||
private final DelayQueue<DelayedEvent> sendQueue = new DelayQueue<DelayedEvent>();
|
||||
|
||||
/** Queue polling thread */
|
||||
private final QueuePollingThread busThread;
|
||||
|
||||
/** Log all */
|
||||
private boolean logging = false;
|
||||
|
||||
/** Whether the bus was destroyed */
|
||||
private boolean dead = false;
|
||||
|
||||
public boolean logSending = false;
|
||||
|
||||
|
||||
/**
|
||||
* Make a new bus and start it's queue thread.
|
||||
@@ -44,23 +47,6 @@ final public class EventBus implements Destroyable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable a level of logging.
|
||||
*
|
||||
* @param level 0 none, 1 warning only, 2 all
|
||||
*/
|
||||
public void enableLogging(boolean level)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
logging = level;
|
||||
|
||||
for (final EventChannel<?, ?> ch : channels) {
|
||||
ch.enableLogging(logging);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a {@link EventChannel} to this bus.<br>
|
||||
* If a channel of matching types is already added, it is returned instead.
|
||||
@@ -81,25 +67,23 @@ final public class EventBus implements Destroyable {
|
||||
}
|
||||
|
||||
channels.add(channel);
|
||||
channel.enableLogging(logging);
|
||||
if (logging) Log.f3("<bus> Added chanel: " + Log.str(channel));
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a channel for given message and client type.
|
||||
* Add a channel for given event and client type.
|
||||
*
|
||||
* @param messageClass message type
|
||||
* @param eventClass event type
|
||||
* @param clientClass client type
|
||||
* @return the created channel instance
|
||||
*/
|
||||
public <F_EVENT extends Event<F_CLIENT>, F_CLIENT> EventChannel<?, ?> addChannel(Class<F_EVENT> messageClass, Class<F_CLIENT> clientClass)
|
||||
public <F_EVENT extends Event<F_CLIENT>, F_CLIENT> EventChannel<?, ?> addChannel(Class<F_EVENT> eventClass, Class<F_CLIENT> clientClass)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
final EventChannel<F_EVENT, F_CLIENT> channel = EventChannel.create(messageClass, clientClass);
|
||||
final EventChannel<F_EVENT, F_CLIENT> channel = EventChannel.create(eventClass, clientClass);
|
||||
return addChannel(channel);
|
||||
}
|
||||
|
||||
@@ -118,31 +102,54 @@ final public class EventBus implements Destroyable {
|
||||
|
||||
|
||||
/**
|
||||
* Add message to a queue
|
||||
* Send based on annotation.
|
||||
*
|
||||
* @param message message
|
||||
* @param event event
|
||||
*/
|
||||
public void queue(Event<?> message)
|
||||
public void send(Event<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
schedule(message, 0);
|
||||
if(event.getClass().isAnnotationPresent(QueuedEvent.class)) {
|
||||
sendQueued(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.getClass().isAnnotationPresent(ImmediateEvent.class)) {
|
||||
sendDirect(event);
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add message to a queue, scheduled for given time.
|
||||
* Add event to a queue
|
||||
*
|
||||
* @param message message
|
||||
* @param delay delay before message is dispatched
|
||||
* @param event event
|
||||
*/
|
||||
public void schedule(Event<?> message, double delay)
|
||||
public void sendQueued(Event<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
final DelayedMessage dm = new DelayedMessage(delay, message);
|
||||
sendDelayed(event, 0);
|
||||
}
|
||||
|
||||
if (logging) Log.f3("<bus> + [ Queuing: " + Log.str(message) + " ]");
|
||||
|
||||
/**
|
||||
* Add event to a queue, scheduled for given time.
|
||||
*
|
||||
* @param event event
|
||||
* @param delay delay before event is dispatched
|
||||
*/
|
||||
public void sendDelayed(Event<?> event, double delay)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
final DelayedEvent dm = new DelayedEvent(delay, event);
|
||||
|
||||
if(logSending) Log.f3("<bus> Q "+Log.str(event)+", t = +"+delay+"s");
|
||||
|
||||
sendQueue.add(dm);
|
||||
}
|
||||
@@ -153,9 +160,26 @@ final public class EventBus implements Destroyable {
|
||||
* Should be used for real-time events that require immediate response, such
|
||||
* as timing events.
|
||||
*
|
||||
* @param message message
|
||||
* @param event event
|
||||
*/
|
||||
public void send(Event<?> message)
|
||||
public void sendDirect(Event<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
if(logSending) Log.f3("<bus> D "+Log.str(event));
|
||||
|
||||
dispatch(event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send immediately.<br>
|
||||
* Should be used for real-time events that require immediate response, such
|
||||
* as timing events.
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
private void dispatch(Event<?> event)
|
||||
{
|
||||
assertLive();
|
||||
|
||||
@@ -163,29 +187,21 @@ final public class EventBus implements Destroyable {
|
||||
channels.setBuffering(true);
|
||||
clients.setBuffering(true);
|
||||
|
||||
if (logging) Log.f3("<bus> - [ Sending: " + Log.str(message) + " ]");
|
||||
|
||||
boolean sent = false;
|
||||
boolean channelAccepted = false;
|
||||
boolean accepted = false;
|
||||
|
||||
final boolean singular = message.getClass().isAnnotationPresent(SingularEvent.class);
|
||||
final boolean singular = event.getClass().isAnnotationPresent(SingularEvent.class);
|
||||
|
||||
for (final EventChannel<?, ?> b : channels) {
|
||||
if (b.canBroadcast(message)) {
|
||||
channelAccepted = true;
|
||||
sent |= b.broadcast(message, clients);
|
||||
if (b.canBroadcast(event)) {
|
||||
accepted = true;
|
||||
sent |= b.broadcast(event, clients);
|
||||
}
|
||||
|
||||
if (sent && singular) {
|
||||
break;
|
||||
}
|
||||
if (sent && singular) break;
|
||||
}
|
||||
|
||||
// more severe
|
||||
if (!channelAccepted) Log.w("<bus> Not accepted by any channel: " + Log.str(message));
|
||||
|
||||
// less severe
|
||||
if (logging && !sent) Log.w("<bus> Not delivered to any client: " + Log.str(message));
|
||||
if(!accepted) Log.e("<bus> Not accepted by any channel: " + Log.str(event));
|
||||
|
||||
channels.setBuffering(false);
|
||||
clients.setBuffering(false);
|
||||
@@ -206,8 +222,6 @@ final public class EventBus implements Destroyable {
|
||||
if (client == null) return;
|
||||
|
||||
clients.add(client);
|
||||
|
||||
if (logging) Log.f3("<bus> ADDING CLIENT " + client);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,8 +235,6 @@ final public class EventBus implements Destroyable {
|
||||
assertLive();
|
||||
|
||||
clients.remove(client);
|
||||
if (logging) Log.f3("<bus> REMOVING CLIENT " + client);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -241,16 +253,16 @@ final public class EventBus implements Destroyable {
|
||||
return false;
|
||||
}
|
||||
|
||||
private class DelayedMessage implements Delayed {
|
||||
private class DelayedEvent implements Delayed {
|
||||
|
||||
private final long due;
|
||||
private Event<?> theMessage = null;
|
||||
private Event<?> evt = null;
|
||||
|
||||
|
||||
public DelayedMessage(double seconds, Event<?> theMessage) {
|
||||
public DelayedEvent(double seconds, Event<?> event) {
|
||||
super();
|
||||
this.due = System.currentTimeMillis() + (long) (seconds * 1000);
|
||||
this.theMessage = theMessage;
|
||||
this.evt = event;
|
||||
}
|
||||
|
||||
|
||||
@@ -268,9 +280,9 @@ final public class EventBus implements Destroyable {
|
||||
}
|
||||
|
||||
|
||||
public Event<?> getMessage()
|
||||
public Event<?> getEvent()
|
||||
{
|
||||
return theMessage;
|
||||
return evt;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -288,19 +300,19 @@ final public class EventBus implements Destroyable {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
DelayedMessage dm;
|
||||
DelayedEvent evt;
|
||||
|
||||
while (!stopped) {
|
||||
dm = null;
|
||||
evt = null;
|
||||
|
||||
try {
|
||||
dm = sendQueue.take();
|
||||
evt = sendQueue.take();
|
||||
} catch (final InterruptedException ignored) {
|
||||
//
|
||||
}
|
||||
|
||||
if (dm != null) {
|
||||
send(dm.getMessage());
|
||||
if (evt != null) {
|
||||
dispatch(evt.getEvent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,79 +6,69 @@ import java.util.HashSet;
|
||||
|
||||
import mightypork.utils.control.bus.clients.DelegatingClient;
|
||||
import mightypork.utils.control.bus.clients.ToggleableClient;
|
||||
import mightypork.utils.control.bus.events.Event;
|
||||
import mightypork.utils.control.bus.events.types.SingularEvent;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Message channel, module of {@link EventBus}
|
||||
* Event delivery channel, module of {@link EventBus}
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <EVENT> message type
|
||||
* @param <EVENT> event type
|
||||
* @param <CLIENT> client (subscriber) type
|
||||
*/
|
||||
final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
|
||||
private final Class<CLIENT> clientClass;
|
||||
private final Class<EVENT> messageClass;
|
||||
private boolean logging = false;
|
||||
private final Class<EVENT> eventClass;
|
||||
|
||||
|
||||
/**
|
||||
* Create a channel
|
||||
*
|
||||
* @param messageClass event class
|
||||
* @param eventClass event class
|
||||
* @param clientClass client class
|
||||
*/
|
||||
public EventChannel(Class<EVENT> messageClass, Class<CLIENT> clientClass) {
|
||||
public EventChannel(Class<EVENT> eventClass, Class<CLIENT> clientClass) {
|
||||
|
||||
if (messageClass == null || clientClass == null) throw new NullPointerException("Null Message or Client class.");
|
||||
if (eventClass == null || clientClass == null) {
|
||||
throw new NullPointerException("Null Event or Client class.");
|
||||
}
|
||||
|
||||
this.clientClass = clientClass;
|
||||
this.messageClass = messageClass;
|
||||
this.eventClass = eventClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable logging of non-warning debug messages.
|
||||
* Try to broadcast a event.<br>
|
||||
* If event is of wrong type, <code>false</code> is returned.
|
||||
*
|
||||
* @param logging enable logging
|
||||
*/
|
||||
public void enableLogging(boolean logging)
|
||||
{
|
||||
this.logging = logging;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to broadcast a message.<br>
|
||||
* If message is of wrong type, <code>false</code> is returned.
|
||||
*
|
||||
* @param message a message to be sent
|
||||
* @param event a event to be sent
|
||||
* @param clients collection of clients
|
||||
* @return true if message was sent
|
||||
* @return true if event was sent
|
||||
*/
|
||||
public boolean broadcast(Event<?> message, Collection<Object> clients)
|
||||
public boolean broadcast(Event<?> event, Collection<Object> clients)
|
||||
{
|
||||
if (!canBroadcast(message)) return false;
|
||||
if (!canBroadcast(event)) return false;
|
||||
|
||||
final EVENT evt = messageClass.cast(message);
|
||||
|
||||
return doBroadcast(evt, clients, new HashSet<Object>());
|
||||
return doBroadcast(eventClass.cast(event), clients, new HashSet<Object>());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send the message
|
||||
* Send the event
|
||||
*
|
||||
* @param message sent message
|
||||
* @param event sent event
|
||||
* @param clients subscribing clients
|
||||
* @param processed clients already processed
|
||||
* @return success
|
||||
*/
|
||||
private boolean doBroadcast(final EVENT message, final Collection<Object> clients, final Collection<Object> processed)
|
||||
private boolean doBroadcast(final EVENT event, final Collection<Object> clients, final Collection<Object> processed)
|
||||
{
|
||||
boolean sent = false;
|
||||
final boolean singular = message.getClass().isAnnotationPresent(SingularEvent.class);
|
||||
final boolean singular = event.getClass().isAnnotationPresent(SingularEvent.class);
|
||||
|
||||
for (final Object client : clients) {
|
||||
|
||||
@@ -96,13 +86,10 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
|
||||
// opt-out
|
||||
if (client instanceof ToggleableClient) {
|
||||
if (!((ToggleableClient) client).isListening()) {
|
||||
if (logging) Log.f3("<bus> Client disabled: " + Log.str(client));
|
||||
continue;
|
||||
}
|
||||
if (!((ToggleableClient) client).isListening()) continue;
|
||||
}
|
||||
|
||||
sent |= sendTo(client, message);
|
||||
sent |= sendTo(client, event);
|
||||
|
||||
// singular event ain't no whore, handled once only.
|
||||
if (sent && singular) return true;
|
||||
@@ -114,11 +101,9 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
final Collection<Object> children = ((DelegatingClient) client).getChildClients();
|
||||
|
||||
if (children != null && children.size() > 0) {
|
||||
sent |= doBroadcast(message, children, processed);
|
||||
sent |= doBroadcast(event, children, processed);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (logging) Log.f3("<bus> Client not delegating: " + Log.str(client));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,18 +113,17 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
|
||||
|
||||
/**
|
||||
* Send a message to a client.
|
||||
* Send an event to a client.
|
||||
*
|
||||
* @param client target client
|
||||
* @param message message to send
|
||||
* @param event event to send
|
||||
* @return success
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean sendTo(Object client, EVENT message)
|
||||
private boolean sendTo(Object client, EVENT event)
|
||||
{
|
||||
if (isClientOfType(client)) {
|
||||
if (logging) Log.f3("<bus> Delivered " + Log.str(message) + " to " + Log.str(client));
|
||||
((Event<CLIENT>) message).handleBy((CLIENT) client);
|
||||
((Event<CLIENT>) event).handleBy((CLIENT) client);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -147,28 +131,28 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
|
||||
|
||||
/**
|
||||
* Check if the given message can be broadcasted by this
|
||||
* Check if the given event can be broadcasted by this
|
||||
* {@link EventChannel}
|
||||
*
|
||||
* @param message event object
|
||||
* @param event event object
|
||||
* @return can be broadcasted
|
||||
*/
|
||||
public boolean canBroadcast(Event<?> message)
|
||||
public boolean canBroadcast(Event<?> event)
|
||||
{
|
||||
return message != null && messageClass.isInstance(message);
|
||||
return event != null && eventClass.isInstance(event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance for given types
|
||||
*
|
||||
* @param messageClass event class
|
||||
* @param eventClass event class
|
||||
* @param clientClass client class
|
||||
* @return the broadcaster
|
||||
*/
|
||||
public static <F_EVENT extends Event<F_CLIENT>, F_CLIENT> EventChannel<F_EVENT, F_CLIENT> create(Class<F_EVENT> messageClass, Class<F_CLIENT> clientClass)
|
||||
public static <F_EVENT extends Event<F_CLIENT>, F_CLIENT> EventChannel<F_EVENT, F_CLIENT> create(Class<F_EVENT> eventClass, Class<F_CLIENT> clientClass)
|
||||
{
|
||||
return new EventChannel<F_EVENT, F_CLIENT>(messageClass, clientClass);
|
||||
return new EventChannel<F_EVENT, F_CLIENT>(eventClass, clientClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +186,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
final int prime = 13;
|
||||
int result = 1;
|
||||
result = prime * result + ((clientClass == null) ? 0 : clientClass.hashCode());
|
||||
result = prime * result + ((messageClass == null) ? 0 : messageClass.hashCode());
|
||||
result = prime * result + ((eventClass == null) ? 0 : eventClass.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -217,9 +201,9 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
if (clientClass == null) {
|
||||
if (other.clientClass != null) return false;
|
||||
} else if (!clientClass.equals(other.clientClass)) return false;
|
||||
if (messageClass == null) {
|
||||
if (other.messageClass != null) return false;
|
||||
} else if (!messageClass.equals(other.messageClass)) return false;
|
||||
if (eventClass == null) {
|
||||
if (other.eventClass != null) return false;
|
||||
} else if (!eventClass.equals(other.eventClass)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -227,6 +211,6 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "{ " + Log.str(messageClass) + " => " + Log.str(clientClass) + " }";
|
||||
return "{ " + Log.str(eventClass) + " => " + Log.str(clientClass) + " }";
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.utils.control.bus;
|
||||
package mightypork.utils.control.bus.events;
|
||||
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.utils.control.bus;
|
||||
package mightypork.utils.control.bus.events.types;
|
||||
|
||||
|
||||
import java.lang.annotation.*;
|
||||
@@ -8,7 +8,7 @@ import java.util.HashMap;
|
||||
public class Log {
|
||||
|
||||
/** enable static logging */
|
||||
private static boolean esl = true;
|
||||
private static boolean staticLogging = true;
|
||||
|
||||
|
||||
/**
|
||||
@@ -18,7 +18,7 @@ public class Log {
|
||||
*/
|
||||
public static void f1(String msg)
|
||||
{
|
||||
if (esl && ready()) main.f1(msg);
|
||||
if (staticLogging && ready()) main.f1(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public class Log {
|
||||
*/
|
||||
public static void f2(String msg)
|
||||
{
|
||||
if (esl && ready()) main.f2(msg);
|
||||
if (staticLogging && ready()) main.f2(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class Log {
|
||||
*/
|
||||
public static void f3(String msg)
|
||||
{
|
||||
if (esl && ready()) main.f3(msg);
|
||||
if (staticLogging && ready()) main.f3(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public class Log {
|
||||
*/
|
||||
public static void i(String msg)
|
||||
{
|
||||
if (esl && ready()) main.i(msg);
|
||||
if (staticLogging && ready()) main.i(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public class Log {
|
||||
*/
|
||||
public static void w(String msg)
|
||||
{
|
||||
if (esl && ready()) main.w(msg);
|
||||
if (staticLogging && ready()) main.w(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public class Log {
|
||||
*/
|
||||
public static void e(String msg)
|
||||
{
|
||||
if (esl && ready()) main.e(msg);
|
||||
if (staticLogging && ready()) main.e(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public class Log {
|
||||
*/
|
||||
public static void e(String msg, Throwable thrown)
|
||||
{
|
||||
if (esl && ready()) main.e(msg, thrown);
|
||||
if (staticLogging && ready()) main.e(msg, thrown);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,13 +96,13 @@ public class Log {
|
||||
*/
|
||||
public static void e(Throwable thrown)
|
||||
{
|
||||
if (esl && ready()) main.e(thrown);
|
||||
if (staticLogging && ready()) main.e(thrown);
|
||||
}
|
||||
|
||||
|
||||
public static void enable(boolean flag)
|
||||
{
|
||||
if (esl && ready()) main.enable(flag);
|
||||
if (staticLogging && ready()) main.enable(flag);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ public class Log {
|
||||
*/
|
||||
public static void enableStaticLogging(boolean flag)
|
||||
{
|
||||
esl = flag;
|
||||
staticLogging = flag;
|
||||
}
|
||||
|
||||
private static HashMap<String, LogInstance> logs = new HashMap<String, LogInstance>();
|
||||
|
||||
@@ -38,7 +38,7 @@ public class LogInstance {
|
||||
private final int logs_to_keep;
|
||||
|
||||
/** Logs dir */
|
||||
private final File dir;
|
||||
private final File log_dir;
|
||||
|
||||
/** Logger instance. */
|
||||
private Logger logger;
|
||||
@@ -54,10 +54,17 @@ public class LogInstance {
|
||||
private LogToSysoutMonitor sysoutMonitor;
|
||||
|
||||
|
||||
/**
|
||||
* Log
|
||||
*
|
||||
* @param name log name
|
||||
* @param dir log directory
|
||||
* @param oldLogCount number of old log files to keep: -1 all, 0 none.
|
||||
*/
|
||||
public LogInstance(String name, File dir, int oldLogCount) {
|
||||
this.name = name;
|
||||
this.file = new File(dir, name + getSuffix());
|
||||
this.dir = dir;
|
||||
this.log_dir = dir;
|
||||
this.logs_to_keep = oldLogCount;
|
||||
|
||||
init();
|
||||
@@ -71,7 +78,7 @@ public class LogInstance {
|
||||
{
|
||||
logger = Logger.getLogger(name);
|
||||
|
||||
cleanup();
|
||||
cleanLoggingDirectory();
|
||||
|
||||
FileHandler handler = null;
|
||||
|
||||
@@ -92,26 +99,27 @@ public class LogInstance {
|
||||
|
||||
logger.setUseParentHandlers(false);
|
||||
logger.setLevel(Level.ALL);
|
||||
logger.info("Main logger initialized.");
|
||||
logger.info("Logger \""+name+"\" initialized.");
|
||||
logger.info((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")).format(new Date()));
|
||||
}
|
||||
|
||||
|
||||
private void cleanup()
|
||||
private void cleanLoggingDirectory()
|
||||
{
|
||||
if (logs_to_keep == 0) return; // overwrite
|
||||
|
||||
// move old file
|
||||
for (final File f : FileUtils.listDirectory(file.getParentFile())) {
|
||||
if (!f.isFile()) continue;
|
||||
if (f.equals(file)) {
|
||||
final Date d = new Date(f.lastModified());
|
||||
|
||||
final Date d = new Date(f.lastModified());
|
||||
final String fbase = name + '_' + (new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss")).format(d);
|
||||
final String suff = getSuffix();
|
||||
String cntStr = "";
|
||||
File f2;
|
||||
|
||||
for (int cnt = 0; (f2 = new File(dir, fbase + cntStr + suff)).exists(); cntStr = "_" + (++cnt)) {}
|
||||
for (int cnt = 0; (f2 = new File(log_dir, fbase + cntStr + suff)).exists(); cntStr = "_" + (++cnt)) {}
|
||||
|
||||
f.renameTo(f2);
|
||||
}
|
||||
@@ -119,7 +127,7 @@ public class LogInstance {
|
||||
|
||||
if (logs_to_keep == -1) return; // keep all
|
||||
|
||||
final List<File> oldLogs = FileUtils.listDirectory(dir, new FileFilter() {
|
||||
final List<File> oldLogs = FileUtils.listDirectory(log_dir, new FileFilter() {
|
||||
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
@@ -174,6 +182,18 @@ public class LogInstance {
|
||||
}
|
||||
|
||||
|
||||
public void setSysoutLevel(Level level)
|
||||
{
|
||||
sysoutMonitor.setLevel(level);
|
||||
}
|
||||
|
||||
|
||||
public void setFileLevel(Level level)
|
||||
{
|
||||
logger.setLevel(level);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable logging.
|
||||
*
|
||||
@@ -197,6 +217,34 @@ public class LogInstance {
|
||||
}
|
||||
|
||||
|
||||
public void log(Level level, String msg)
|
||||
{
|
||||
if (enabled) {
|
||||
logger.log(level, msg);
|
||||
|
||||
String fmt = formatMessage(level, msg, null);
|
||||
|
||||
for (final LogMonitor mon : monitors.values()) {
|
||||
mon.onMessageLogged(level, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void log(Level level, String msg, Throwable t)
|
||||
{
|
||||
if (enabled) {
|
||||
logger.log(level, msg, t);
|
||||
|
||||
String fmt = formatMessage(level, msg, null);
|
||||
|
||||
for (final LogMonitor mon : monitors.values()) {
|
||||
mon.onMessageLogged(level, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log FINE message
|
||||
*
|
||||
@@ -204,7 +252,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void f1(String msg)
|
||||
{
|
||||
if (enabled) logger.log(Level.FINE, msg);
|
||||
log(Level.FINE, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +263,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void f2(String msg)
|
||||
{
|
||||
if (enabled) logger.log(Level.FINER, msg);
|
||||
log(Level.FINER, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +274,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void f3(String msg)
|
||||
{
|
||||
if (enabled) logger.log(Level.FINEST, msg);
|
||||
log(Level.FINEST, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +285,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void i(String msg)
|
||||
{
|
||||
if (enabled) logger.log(Level.INFO, msg);
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +296,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void w(String msg)
|
||||
{
|
||||
if (enabled) logger.log(Level.WARNING, msg);
|
||||
log(Level.WARNING, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +307,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void e(String msg)
|
||||
{
|
||||
if (enabled) logger.log(Level.SEVERE, msg);
|
||||
log(Level.SEVERE, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -271,7 +319,7 @@ public class LogInstance {
|
||||
*/
|
||||
public void e(String msg, Throwable thrown)
|
||||
{
|
||||
if (enabled) logger.log(Level.SEVERE, msg + "\n" + getStackTrace(thrown));
|
||||
log(Level.SEVERE, msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -282,7 +330,70 @@ public class LogInstance {
|
||||
*/
|
||||
public void e(Throwable thrown)
|
||||
{
|
||||
if (enabled) logger.log(Level.SEVERE, getStackTrace(thrown));
|
||||
log(Level.SEVERE, null, thrown);
|
||||
}
|
||||
|
||||
/**
|
||||
* PowerCraft Log file formatter.
|
||||
*
|
||||
* @author MightyPork
|
||||
* @copy (c) 2012
|
||||
*/
|
||||
private class LogFormatter extends Formatter {
|
||||
|
||||
@Override
|
||||
public String format(LogRecord record)
|
||||
{
|
||||
return LogInstance.formatMessage(record.getLevel(), record.getMessage(), record.getThrown());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return log filename suffix (incl. dot)
|
||||
*/
|
||||
protected String getSuffix()
|
||||
{
|
||||
return ".log";
|
||||
}
|
||||
|
||||
|
||||
private static String formatMessage(Level level, String message, Throwable throwable)
|
||||
{
|
||||
|
||||
final String nl = System.getProperty("line.separator");
|
||||
|
||||
if (message.equals("\n")) {
|
||||
return nl;
|
||||
}
|
||||
|
||||
if (message.charAt(0) == '\n') {
|
||||
message = nl + message.substring(1);
|
||||
}
|
||||
|
||||
String prefix = "[ ? ]";
|
||||
|
||||
if (level == Level.FINE) {
|
||||
prefix = "[ # ] ";
|
||||
} else if (level == Level.FINER) {
|
||||
prefix = "[ - ] ";
|
||||
} else if (level == Level.FINEST) {
|
||||
prefix = "[ ] ";
|
||||
} else if (level == Level.INFO) {
|
||||
prefix = "[ i ] ";
|
||||
} else if (level == Level.SEVERE) {
|
||||
prefix = "[!E!] ";
|
||||
} else if (level == Level.WARNING) {
|
||||
prefix = "[!W!] ";
|
||||
}
|
||||
|
||||
message = prefix + message.replaceAll("\n", nl + prefix) + nl;
|
||||
|
||||
if (throwable != null) {
|
||||
message += getStackTrace(throwable);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
@@ -301,92 +412,4 @@ public class LogInstance {
|
||||
sw.flush();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* PowerCraft Log file formatter.
|
||||
*
|
||||
* @author MightyPork
|
||||
* @copy (c) 2012
|
||||
*/
|
||||
private class LogFormatter extends Formatter {
|
||||
|
||||
/** Newline string constant */
|
||||
private final String nl = System.getProperty("line.separator");
|
||||
|
||||
|
||||
@Override
|
||||
public String format(LogRecord record)
|
||||
{
|
||||
final StringBuffer buf = new StringBuffer(180);
|
||||
|
||||
if (record.getMessage().equals("\n")) {
|
||||
return nl;
|
||||
}
|
||||
|
||||
if (record.getMessage().charAt(0) == '\n') {
|
||||
buf.append(nl);
|
||||
record.setMessage(record.getMessage().substring(1));
|
||||
}
|
||||
|
||||
final Level level = record.getLevel();
|
||||
String trail = "[ ? ]";
|
||||
if (level == Level.FINE) {
|
||||
trail = "[ # ] ";
|
||||
}
|
||||
if (level == Level.FINER) {
|
||||
trail = "[ - ] ";
|
||||
}
|
||||
if (level == Level.FINEST) {
|
||||
trail = "[ ] ";
|
||||
}
|
||||
if (level == Level.INFO) {
|
||||
trail = "[ i ] ";
|
||||
}
|
||||
if (level == Level.SEVERE) {
|
||||
trail = "[!E!] ";
|
||||
}
|
||||
if (level == Level.WARNING) {
|
||||
trail = "[!W!] ";
|
||||
}
|
||||
|
||||
record.setMessage(record.getMessage().replaceAll("\n", nl + trail));
|
||||
|
||||
buf.append(trail);
|
||||
buf.append(formatMessage(record));
|
||||
|
||||
buf.append(nl);
|
||||
|
||||
final Throwable throwable = record.getThrown();
|
||||
if (throwable != null) {
|
||||
buf.append("at ");
|
||||
buf.append(record.getSourceClassName());
|
||||
buf.append('.');
|
||||
buf.append(record.getSourceMethodName());
|
||||
buf.append(nl);
|
||||
|
||||
final StringWriter sink = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(sink, true));
|
||||
buf.append(sink.toString());
|
||||
|
||||
buf.append(nl);
|
||||
}
|
||||
|
||||
final String str = buf.toString();
|
||||
|
||||
for (final LogMonitor mon : monitors.values()) {
|
||||
mon.log(level, str);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return log filename suffix (incl. dot)
|
||||
*/
|
||||
protected String getSuffix()
|
||||
{
|
||||
return ".log";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,18 @@ package mightypork.utils.logging;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
/**
|
||||
* Log monitor, receives all logged messages
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface LogMonitor {
|
||||
|
||||
public void log(Level level, String message);
|
||||
|
||||
|
||||
public void enable(boolean enable);
|
||||
/**
|
||||
* Message logged;
|
||||
*
|
||||
* @param level message level
|
||||
* @param message message text, already formatted.
|
||||
*/
|
||||
void onMessageLogged(Level level, String message);
|
||||
}
|
||||
|
||||
@@ -7,22 +7,29 @@ import java.util.logging.Level;
|
||||
public class LogToSysoutMonitor implements LogMonitor {
|
||||
|
||||
private boolean enabled = true;
|
||||
private Level accepted = Level.ALL;
|
||||
|
||||
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.accepted = level;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void log(Level level, String message)
|
||||
public void onMessageLogged(Level level, String message)
|
||||
{
|
||||
if (!enabled) return;
|
||||
if (accepted.intValue() > level.intValue()) return;
|
||||
|
||||
if (level == Level.FINE || level == Level.FINER || level == Level.FINEST || level == Level.INFO) {
|
||||
System.out.print(message);
|
||||
} else if (level == Level.SEVERE || level == Level.WARNING) {
|
||||
if (level == Level.SEVERE || level == Level.WARNING) {
|
||||
System.err.print(message);
|
||||
} else {
|
||||
System.out.print(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void enable(boolean enable)
|
||||
{
|
||||
this.enabled = enable;
|
||||
|
||||
Reference in New Issue
Block a user