View Javadoc
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 }