1 package com.github.valfirst.slf4jtest; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 import java.util.concurrent.ConcurrentHashMap; 9 import java.util.concurrent.ConcurrentMap; 10 import org.slf4j.ILoggerFactory; 11 import org.slf4j.event.Level; 12 import uk.org.lidalia.lang.ThreadLocal; 13 14 public final class TestLoggerFactory implements ILoggerFactory { 15 16 private static volatile TestLoggerFactory INSTANCE = null; 17 18 private static Level getLevelProperty( 19 OverridableProperties properties, String propertyKey, String defaultValue) { 20 try { 21 final String printLevelProperty = properties.getProperty(propertyKey, defaultValue); 22 if ("OFF".equals(printLevelProperty)) { 23 return null; 24 } 25 return Level.valueOf(printLevelProperty); 26 } catch (IllegalArgumentException e) { 27 throw new IllegalStateException( 28 "Invalid level name in property " 29 + propertyKey 30 + " of file slf4jtest.properties " 31 + "or System property slf4jtest." 32 + propertyKey, 33 e); 34 } 35 } 36 37 private final ConcurrentMap<String, TestLogger> loggers = new ConcurrentHashMap<>(); 38 private final List<LoggingEvent> allLoggingEvents = 39 Collections.synchronizedList(new ArrayList<>()); 40 private final ThreadLocal<List<LoggingEvent>> loggingEvents = new ThreadLocal<>(ArrayList::new); 41 private volatile Level printLevel; 42 private volatile Level captureLevel; 43 44 public static TestLoggerFactory getInstance() { 45 if (INSTANCE == null) { 46 synchronized (TestLoggerFactory.class) { 47 if (INSTANCE == null) { 48 INSTANCE = createInstance(OverridableProperties.createUnchecked("slf4jtest")); 49 } 50 } 51 } 52 return INSTANCE; 53 } 54 55 static TestLoggerFactory createInstance(OverridableProperties properties) { 56 Level printLevel = getLevelProperty(properties, "print.level", "OFF"); 57 Level captureLevel = getLevelProperty(properties, "capture.level", "TRACE"); 58 return new TestLoggerFactory(printLevel, captureLevel); 59 } 60 61 public static TestLogger getTestLogger(final Class<?> aClass) { 62 return getInstance().getLogger(aClass); 63 } 64 65 public static TestLogger getTestLogger(final String name) { 66 return getInstance().getLogger(name); 67 } 68 69 public static Map<String, TestLogger> getAllTestLoggers() { 70 return getInstance().getAllLoggers(); 71 } 72 73 public static void clear() { 74 getInstance().clearLoggers(); 75 } 76 77 public static void clearAll() { 78 getInstance().clearAllLoggers(); 79 } 80 81 static void reset() { 82 getInstance().doReset(); 83 } 84 85 public static List<LoggingEvent> getLoggingEvents() { 86 return getInstance().getLoggingEventsFromLoggers(); 87 } 88 89 public static List<LoggingEvent> getAllLoggingEvents() { 90 return getInstance().getAllLoggingEventsFromLoggers(); 91 } 92 93 public TestLoggerFactory() { 94 this(null, Level.TRACE); 95 } 96 97 public TestLoggerFactory(final Level printLevel) { 98 this(printLevel, Level.TRACE); 99 } 100 101 public TestLoggerFactory(final Level printLevel, final Level captureLevel) { 102 this.printLevel = printLevel; 103 this.captureLevel = captureLevel; 104 } 105 106 public Level getPrintLevel() { 107 return printLevel; 108 } 109 110 public Level getCaptureLevel() { 111 return captureLevel; 112 } 113 114 public Map<String, TestLogger> getAllLoggers() { 115 return Collections.unmodifiableMap(new HashMap<>(loggers)); 116 } 117 118 public TestLogger getLogger(final Class<?> aClass) { 119 return getLogger(aClass.getName()); 120 } 121 122 public TestLogger getLogger(final String name) { 123 return loggers.computeIfAbsent(name, nm -> new TestLogger(nm, this)); 124 } 125 126 public void clearLoggers() { 127 for (final TestLogger testLogger : loggers.values()) { 128 testLogger.clear(); 129 } 130 loggingEvents.get().clear(); 131 } 132 133 public void clearAllLoggers() { 134 for (final TestLogger testLogger : loggers.values()) { 135 testLogger.clearAll(); 136 } 137 loggingEvents.reset(); 138 allLoggingEvents.clear(); 139 } 140 141 void doReset() { 142 clearAllLoggers(); 143 loggers.clear(); 144 } 145 146 public List<LoggingEvent> getLoggingEventsFromLoggers() { 147 return Collections.unmodifiableList(new ArrayList<>(loggingEvents.get())); 148 } 149 150 public List<LoggingEvent> getAllLoggingEventsFromLoggers() { 151 return allLoggingEvents; 152 } 153 154 void addLoggingEvent(final LoggingEvent event) { 155 loggingEvents.get().add(event); 156 allLoggingEvents.add(event); 157 } 158 159 public void setPrintLevel(final Level printLevel) { 160 this.printLevel = printLevel; 161 } 162 163 public void setCaptureLevel(Level captureLevel) { 164 this.captureLevel = captureLevel; 165 } 166 }