diff options
author | Jiri Vanek <[email protected]> | 2013-12-20 11:20:39 +0100 |
---|---|---|
committer | Jiri Vanek <[email protected]> | 2013-12-20 11:20:39 +0100 |
commit | 99428f6f586269f4b5856f93adb71385f6c64c97 (patch) | |
tree | f13560c1d4d7200583dc858b1ad8c387023f5013 /netx/net/sourceforge/jnlp/util/logging/OutputController.java | |
parent | c3b3c491051c08e035593a25850e537168bb1db9 (diff) |
singletons logic, logs and test cleanup/fixes
Diffstat (limited to 'netx/net/sourceforge/jnlp/util/logging/OutputController.java')
-rw-r--r-- | netx/net/sourceforge/jnlp/util/logging/OutputController.java | 136 |
1 files changed, 77 insertions, 59 deletions
diff --git a/netx/net/sourceforge/jnlp/util/logging/OutputController.java b/netx/net/sourceforge/jnlp/util/logging/OutputController.java index d84950a..996eebb 100644 --- a/netx/net/sourceforge/jnlp/util/logging/OutputController.java +++ b/netx/net/sourceforge/jnlp/util/logging/OutputController.java @@ -38,11 +38,19 @@ package net.sourceforge.jnlp.util.logging; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.util.Date; import java.util.LinkedList; import java.util.List; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.util.logging.headers.Header; +import net.sourceforge.jnlp.util.logging.headers.JavaMessage; +import net.sourceforge.jnlp.util.logging.headers.MessageWithHeader; + +/** + * + * OutputController class (thread) must NOT call JNLPRuntime.getConfiguraion() + * + */ public class OutputController { public static enum Level { @@ -88,30 +96,15 @@ public class OutputController { } } - private static final class MessageWithLevel { - - public final String message; - public final Level level; - public final StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - public final Thread thread = Thread.currentThread(); - public final Date loggedAt = new Date(); - - public MessageWithLevel(String message, Level level) { - this.message = message; - this.level = level; - } - } /* * singleton instance */ - private static OutputController logger; private static final String NULL_OBJECT = "Trying to log null object"; - private FileLog fileLog; private PrintStreamLogger outLog; private PrintStreamLogger errLog; - private SingleStreamLogger sysLog; - private List<MessageWithLevel> messageQue = new LinkedList<MessageWithLevel>(); + private List<MessageWithHeader> messageQue = new LinkedList<MessageWithHeader>(); private MessageQueConsumer messageQueConsumer = new MessageQueConsumer(); + Thread consumerThread; //bounded to instance private class MessageQueConsumer implements Runnable { @@ -149,33 +142,32 @@ public class OutputController { } private void consume() { - MessageWithLevel s = messageQue.get(0); + MessageWithHeader s = messageQue.get(0); messageQue.remove(0); - net.sourceforge.jnlp.util.logging.headers.Header header = new net.sourceforge.jnlp.util.logging.headers.Header(s.level, s.stack, s.thread, s.loggedAt, false); //filtering is done in console during runtime if (LogConfig.getLogConfig().isLogToConsole()) { - JavaConsole.getConsole().addMessage(header, s.message); + JavaConsole.getConsole().addMessage(s.getHeader(), s.getMessage()); } - if (!JNLPRuntime.isDebug() && (s.level == Level.MESSAGE_DEBUG - || s.level == Level.WARNING_DEBUG - || s.level == Level.ERROR_DEBUG)) { + if (!JNLPRuntime.isDebug() && (s.getHeader().level == Level.MESSAGE_DEBUG + || s.getHeader().level == Level.WARNING_DEBUG + || s.getHeader().level == Level.ERROR_DEBUG)) { //filter out debug messages //must be here to prevent deadlock, casued by exception form jnlpruntime, loggers or configs themselves return; } - String message = s.message; + String message = s.getMessage(); if (LogConfig.getLogConfig().isEnableHeaders()) { if (message.contains("\n")) { - message = header.toString() + "\n" + message; + message = s.getHeader().toString() + "\n" + message; } else { - message = header.toString() + " " + message; + message = s.getHeader().toString() + " " + message; } } if (LogConfig.getLogConfig().isLogToStreams()) { - if (s.level.isOutput()) { + if (s.getHeader().level.isOutput()) { outLog.log(message); } - if (s.level.isError()) { + if (s.getHeader().level.isError()) { errLog.log(message); } } @@ -191,17 +183,22 @@ public class OutputController { private OutputController() { this(System.out, System.err); } + + + private static class OutputControllerHolder { + + //https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom + //https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java + private static final OutputController INSTANCE = new OutputController(); + } /** * This should be the only legal way to get logger for ITW * * @return logging singleton */ - synchronized public static OutputController getLogger() { - if (logger == null) { - logger = new OutputController(); - } - return logger; + public static OutputController getLogger() { + return OutputControllerHolder.INSTANCE; } /** @@ -215,22 +212,24 @@ public class OutputController { outLog = new PrintStreamLogger(out); errLog = new PrintStreamLogger(err); //itw logger have to be fully initialised before start - Thread t = new Thread(messageQueConsumer, "Output controller consumer daemon"); - t.setDaemon(true); - t.start(); - //some messages were probably posted before start of consumer - synchronized (this){ - this.notifyAll(); - } + consumerThread = new Thread(messageQueConsumer, "Output controller consumer daemon"); + consumerThread.setDaemon(true); + //is started in JNLPRuntime.getConfig() after config is laoded Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { - while (!messageQue.isEmpty()) { - consume(); - } + flush(); } })); } + + public void startConsumer() { + consumerThread.start(); + //some messages were probably posted before start of consumer + synchronized (this) { + this.notifyAll(); + } + } /** * @@ -302,33 +301,52 @@ public class OutputController { log(Level.ERROR_DEBUG, (Object) s); } - private synchronized void log(Level level, Object o) { + private void log(Level level, Object o) { + String s =""; if (o == null) { - messageQue.add(new MessageWithLevel(NULL_OBJECT, level)); + s = NULL_OBJECT; } else if (o instanceof Throwable) { - messageQue.add(new MessageWithLevel(exceptionToString((Throwable) o), level)); + s = exceptionToString((Throwable) o); } else { - messageQue.add(new MessageWithLevel(o.toString(), level)); + s=o.toString(); } + log(new JavaMessage(new Header(level, false), s)); + } + + synchronized void log(MessageWithHeader l){ + messageQue.add(l); this.notifyAll(); } + + + private static class FileLogHolder { + + //https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java + //https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom + private static volatile FileLog INSTANCE = new FileLog(); + } private FileLog getFileLog() { - if (fileLog == null) { - fileLog = new FileLog(); - } - return fileLog; + return FileLogHolder.INSTANCE; } - private SingleStreamLogger getSystemLog() { - if (sysLog == null) { + private static class SystemLogHolder { + + //https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java + //https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom + private static volatile SingleStreamLogger INSTANCE = initSystemLogger(); + + private static SingleStreamLogger initSystemLogger() { if (JNLPRuntime.isWindows()) { - sysLog = new WinSystemLog(); + return new WinSystemLog(); } else { - sysLog = new UnixSystemLog(); + return new UnixSystemLog(); } } - return sysLog; + } + + private SingleStreamLogger getSystemLog() { + return SystemLogHolder.INSTANCE; } public void printErrorLn(String e) { @@ -368,7 +386,7 @@ public class OutputController { } void setFileLog(FileLog fileLog) { - this.fileLog = fileLog; + FileLogHolder.INSTANCE = fileLog; } void setOutLog(PrintStreamLogger outLog) { @@ -376,7 +394,7 @@ public class OutputController { } void setSysLog(SingleStreamLogger sysLog) { - this.sysLog = sysLog; + SystemLogHolder.INSTANCE = sysLog; } |