package org.ripple.power.txns.btc; import java.util.ArrayList; import java.util.List; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; public class MemoryLogHandler extends Handler { /** Default ring buffer size */ private static final int DEFAULT_SIZE = 100; /** Level OFF value */ private static final int OFF_VALUE = Level.OFF.intValue(); /** Ring buffer */ private final LogRecord[] buffer; /** Buffer start */ private int start = 0; /** Number of buffer entries */ private int count = 0; /** Publish level */ private Level level; /** * Create a MemoryLogHandler and configure it based on LogManager properties */ public MemoryLogHandler() { LogManager manager = LogManager.getLogManager(); String cname = getClass().getName(); String value; // // Allocate the ring buffer // int bufferSize; try { value = manager.getProperty(cname+".size"); if (value != null) bufferSize = Math.max(Integer.valueOf(value.trim()), 10); else bufferSize = DEFAULT_SIZE; } catch (NumberFormatException exc) { bufferSize = DEFAULT_SIZE; } buffer = new LogRecord[bufferSize]; // // Get publish level // try { value = manager.getProperty(cname+".level"); if (value != null) { level = Level.parse(value.trim()); } else { level = Level.ALL; } } catch (IllegalArgumentException exc) { level = Level.ALL; } } /** * Store a LogRecord in the ring buffer * * @param record Description of the log event. A null record is * silently ignored and is not published */ @Override public void publish(LogRecord record) { if (record != null && record.getLevel().intValue() >= level.intValue() && level.intValue() != OFF_VALUE) { synchronized(buffer) { int ix = (start+count)%buffer.length; buffer[ix] = record; if (count < buffer.length) { count++; } else { start++; start %= buffer.length; } } } } /** * Return the log messages from the ring buffer * * @return List of log messages */ public List<String> getMessages() { List<String> rtnList = new ArrayList<>(buffer.length); synchronized(buffer) { int pos = start; Formatter formatter = getFormatter(); for (int i=0; i<count; i++) { rtnList.add(formatter.format(buffer[pos++])); if (pos == buffer.length) pos = 0; } } return rtnList; } /** * Flush the ring buffer */ @Override public void flush() { synchronized(buffer) { start = 0; count = 0; } } /** * Close the handler */ @Override public void close() { level = Level.OFF; } }