View Javadoc
1   package uk.org.lidalia.slf4jtest;
2   
3   import java.io.IOException;
4   import java.util.List;
5   import java.util.Map;
6   import java.util.concurrent.Callable;
7   import java.util.concurrent.ConcurrentHashMap;
8   import java.util.concurrent.ConcurrentMap;
9   import java.util.concurrent.CopyOnWriteArrayList;
10  
11  import org.slf4j.ILoggerFactory;
12  
13  import com.google.common.collect.ImmutableList;
14  import com.google.common.collect.ImmutableMap;
15  
16  import uk.org.lidalia.lang.LazyValue;
17  import uk.org.lidalia.lang.ThreadLocal;
18  import uk.org.lidalia.slf4jext.Level;
19  
20  import static com.google.common.base.Optional.fromNullable;
21  import static com.google.common.base.Preconditions.checkNotNull;
22  
23  public final class TestLoggerFactory implements ILoggerFactory {
24  
25      private static final LazyValue<TestLoggerFactory> INSTANCE = new LazyValue<>(new TestLoggerFactoryMaker());
26  
27      public static TestLoggerFactory getInstance() {
28          return INSTANCE.call();
29      }
30  
31      public static TestLogger getTestLogger(final Class<?> aClass) {
32          return getInstance().getLogger(aClass);
33      }
34  
35      public static TestLogger getTestLogger(final String name) {
36          return getInstance().getLogger(name);
37      }
38  
39      public static Map<String, TestLogger> getAllTestLoggers() {
40          return getInstance().getAllLoggers();
41      }
42  
43      public static void clear() {
44          getInstance().clearLoggers();
45      }
46  
47      public static void clearAll() {
48          getInstance().clearAllLoggers();
49      }
50  
51      static void reset() {
52          getInstance().doReset();
53      }
54  
55      public static List<LoggingEvent> getLoggingEvents() {
56          return getInstance().getLoggingEventsFromLoggers();
57      }
58  
59      public static List<LoggingEvent> getAllLoggingEvents() {
60          return getInstance().getAllLoggingEventsFromLoggers();
61      }
62  
63      private final ConcurrentMap<String, TestLogger> loggers = new ConcurrentHashMap<>();
64      private final List<LoggingEvent> allLoggingEvents = new CopyOnWriteArrayList<>();
65      private final ThreadLocal<List<LoggingEvent>> loggingEvents =
66              new ThreadLocal<>(Suppliers.<LoggingEvent>makeEmptyMutableList());
67      private volatile Level printLevel;
68  
69      private TestLoggerFactory(final Level printLevel) {
70          this.printLevel = checkNotNull(printLevel);
71      }
72  
73      public Level getPrintLevel() {
74          return printLevel;
75      }
76  
77      public ImmutableMap<String, TestLogger> getAllLoggers() {
78          return ImmutableMap.copyOf(loggers);
79      }
80  
81      public TestLogger getLogger(final Class<?> aClass) {
82          return getLogger(aClass.getName());
83      }
84  
85      public TestLogger getLogger(final String name) {
86          final TestLogger newLogger = new TestLogger(name, this);
87          return fromNullable(loggers.putIfAbsent(name, newLogger)).or(newLogger);
88      }
89  
90      public void clearLoggers() {
91          for (final TestLogger testLogger: loggers.values()) {
92              testLogger.clear();
93          }
94          loggingEvents.get().clear();
95      }
96  
97      public void clearAllLoggers() {
98          for (final TestLogger testLogger: loggers.values()) {
99              testLogger.clearAll();
100         }
101         loggingEvents.reset();
102         allLoggingEvents.clear();
103     }
104 
105     void doReset() {
106         clearAllLoggers();
107         loggers.clear();
108     }
109 
110     public ImmutableList<LoggingEvent> getLoggingEventsFromLoggers() {
111         return ImmutableList.copyOf(loggingEvents.get());
112     }
113 
114     public List<LoggingEvent> getAllLoggingEventsFromLoggers() {
115         return allLoggingEvents;
116     }
117 
118     void addLoggingEvent(final LoggingEvent event) {
119         loggingEvents.get().add(event);
120         allLoggingEvents.add(event);
121     }
122 
123     public void setPrintLevel(final Level printLevel) {
124         this.printLevel = checkNotNull(printLevel);
125     }
126 
127     @SuppressWarnings("PMD.AccessorClassGeneration")
128     private static class TestLoggerFactoryMaker implements Callable<TestLoggerFactory> {
129         @Override
130         public TestLoggerFactory call() throws IOException {
131             try {
132                 final String level = new OverridableProperties("slf4jtest").getProperty("print.level", "OFF");
133                 final Level printLevel = Level.valueOf(level);
134                 return new TestLoggerFactory(printLevel);
135             } catch (IllegalArgumentException e) {
136                 throw new IllegalStateException("Invalid level name in property print.level of file slf4jtest.properties " +
137                         "or System property slf4jtest.print.level", e);
138             }
139         }
140     }
141 }