TestLoggerFactory.java
package com.github.valfirst.slf4jtest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.ILoggerFactory;
import org.slf4j.event.Level;
import uk.org.lidalia.lang.ThreadLocal;
public final class TestLoggerFactory implements ILoggerFactory {
private static volatile TestLoggerFactory INSTANCE = null;
private static Level getLevelProperty(
OverridableProperties properties, String propertyKey, String defaultValue) {
try {
final String printLevelProperty = properties.getProperty(propertyKey, defaultValue);
if ("OFF".equals(printLevelProperty)) {
return null;
}
return Level.valueOf(printLevelProperty);
} catch (IllegalArgumentException e) {
throw new IllegalStateException(
"Invalid level name in property "
+ propertyKey
+ " of file slf4jtest.properties "
+ "or System property slf4jtest."
+ propertyKey,
e);
}
}
private final ConcurrentMap<String, TestLogger> loggers = new ConcurrentHashMap<>();
private final List<LoggingEvent> allLoggingEvents =
Collections.synchronizedList(new ArrayList<>());
private final ThreadLocal<List<LoggingEvent>> loggingEvents = new ThreadLocal<>(ArrayList::new);
private volatile Level printLevel;
private volatile Level captureLevel;
public static TestLoggerFactory getInstance() {
if (INSTANCE == null) {
synchronized (TestLoggerFactory.class) {
if (INSTANCE == null) {
INSTANCE = createInstance(OverridableProperties.createUnchecked("slf4jtest"));
}
}
}
return INSTANCE;
}
static TestLoggerFactory createInstance(OverridableProperties properties) {
Level printLevel = getLevelProperty(properties, "print.level", "OFF");
Level captureLevel = getLevelProperty(properties, "capture.level", "TRACE");
return new TestLoggerFactory(printLevel, captureLevel);
}
public static TestLogger getTestLogger(final Class<?> aClass) {
return getInstance().getLogger(aClass);
}
public static TestLogger getTestLogger(final String name) {
return getInstance().getLogger(name);
}
public static Map<String, TestLogger> getAllTestLoggers() {
return getInstance().getAllLoggers();
}
public static void clear() {
getInstance().clearLoggers();
}
public static void clearAll() {
getInstance().clearAllLoggers();
}
static void reset() {
getInstance().doReset();
}
public static List<LoggingEvent> getLoggingEvents() {
return getInstance().getLoggingEventsFromLoggers();
}
public static List<LoggingEvent> getAllLoggingEvents() {
return getInstance().getAllLoggingEventsFromLoggers();
}
public TestLoggerFactory() {
this(null, Level.TRACE);
}
public TestLoggerFactory(final Level printLevel) {
this(printLevel, Level.TRACE);
}
public TestLoggerFactory(final Level printLevel, final Level captureLevel) {
this.printLevel = printLevel;
this.captureLevel = captureLevel;
}
public Level getPrintLevel() {
return printLevel;
}
public Level getCaptureLevel() {
return captureLevel;
}
public Map<String, TestLogger> getAllLoggers() {
return Collections.unmodifiableMap(new HashMap<>(loggers));
}
public TestLogger getLogger(final Class<?> aClass) {
return getLogger(aClass.getName());
}
public TestLogger getLogger(final String name) {
return loggers.computeIfAbsent(name, nm -> new TestLogger(nm, this));
}
public void clearLoggers() {
for (final TestLogger testLogger : loggers.values()) {
testLogger.clear();
}
loggingEvents.get().clear();
}
public void clearAllLoggers() {
for (final TestLogger testLogger : loggers.values()) {
testLogger.clearAll();
}
loggingEvents.reset();
allLoggingEvents.clear();
}
void doReset() {
clearAllLoggers();
loggers.clear();
}
public List<LoggingEvent> getLoggingEventsFromLoggers() {
return Collections.unmodifiableList(new ArrayList<>(loggingEvents.get()));
}
public List<LoggingEvent> getAllLoggingEventsFromLoggers() {
return allLoggingEvents;
}
void addLoggingEvent(final LoggingEvent event) {
loggingEvents.get().add(event);
allLoggingEvents.add(event);
}
public void setPrintLevel(final Level printLevel) {
this.printLevel = printLevel;
}
public void setCaptureLevel(Level captureLevel) {
this.captureLevel = captureLevel;
}
}