package ilarkesto.logging; import ilarkesto.base.Str; import ilarkesto.base.Sys; import ilarkesto.core.logging.Log; import ilarkesto.core.logging.LogRecord; import ilarkesto.core.logging.LogRecordHandler; import ilarkesto.io.IO; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; public class DefaultLogDataHandler implements LogRecordHandler { private static final Log LOG = Log.get(DefaultLogDataHandler.class); public static final DateFormat LOG_TIME_FORMAT = new SimpleDateFormat("EEE, dd. MMMM yyyy, HH:mm"); public static final DefaultLogDataHandler INSTANCE = new DefaultLogDataHandler(); private BlockingQueue<LogRecord> queue = new LinkedBlockingQueue<LogRecord>(); private File logFile; private Thread sysoutThread; private boolean shutdown = false; public static void activate() {} private DefaultLogDataHandler() { System.err.println("Initializing logging system"); sysoutThread = new Thread(new Runnable() { public void run() { while (true) { try { synchronized (Log.class) { if (shutdown && queue.isEmpty()) { System.err.println("Shutting down logging system"); break; } } LogRecord record = queue.poll(Long.MAX_VALUE, TimeUnit.SECONDS); System.err.println(record.toString()); } catch (InterruptedException ignored) { // retry } finally { // no clean up to do } } } }); sysoutThread.setName(Log.class.getName()); sysoutThread.setPriority(Thread.MIN_PRIORITY); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { stopLogging(); } }); sysoutThread.start(); Log.setLogRecordHandler(this); } public static void stopLogging() { INSTANCE.flush(); synchronized (Log.class) { INSTANCE.shutdown = true; } if (INSTANCE.sysoutThread != null) INSTANCE.sysoutThread.interrupt(); } @Override public void log(LogRecord record) { record.context = Thread.currentThread().getName(); try { queue.put(record); } catch (InterruptedException e) { return; } if (record.level.isWarnOrWorse()) appendToFile(record.toString()); } public void flush() { while (!queue.isEmpty()) { try { Thread.sleep(100); } catch (InterruptedException ex) { throw new RuntimeException(ex); } } } public static boolean setLogFile(File file) { if (!IO.isFileWritable(file)) return false; INSTANCE.logFile = file; LOG.info("Log-file:", file); return true; } public static File getLogFile() { return INSTANCE.logFile; } public static boolean setLogFileToHomeOrWorkdir(String name) { if (setLogFileToWorkdir(name)) return true; return setLogFileToHome(name); } public static boolean setLogFileToHome(String name) { boolean ok = setLogFile(new File(Sys.getUsersHomePath() + "/" + name + ".log")); if (ok) return true; return setLogFile(new File(Sys.getUsersHomePath() + "/webapps/" + name + ".log")); } public static boolean setLogFileToWorkdir(String name) { boolean ok = setLogFile(new File(Sys.getWorkDir() + "/" + name + ".log")); if (ok) return true; return setLogFile(new File(Sys.getWorkDir() + "/webapps/" + name + ".log")); } private void appendToFile(String record) { if (logFile == null) { File runtimedataDir = new File("runtimedata"); if (runtimedataDir.exists() && runtimedataDir.isDirectory()) { setLogFile(new File("runtimedata/warn+error.log")); } else { setLogFile(new File("warn+error.log")); } } if (logFile == null) return; synchronized (logFile) { try { BufferedWriter out = new BufferedWriter(new FileWriter(logFile, true)); out.write("--------------------------------------------------------------------------------\n"); out.write(LOG_TIME_FORMAT.format(new Date())); out.write(" -> "); out.write(record); out.write('\n'); out.close(); } catch (Exception e) { System.err.println("Failed to write to logFile: " + logFile.getAbsolutePath() + ": " + Str.format(e)); } } } }