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 }