1 package uk.org.lidalia.slf4jtest;
2
3 import java.util.Collections;
4 import java.util.List;
5 import java.util.Map;
6 import java.util.concurrent.CopyOnWriteArrayList;
7
8 import org.slf4j.Logger;
9 import org.slf4j.MDC;
10 import org.slf4j.Marker;
11 import org.slf4j.helpers.FormattingTuple;
12 import org.slf4j.helpers.MessageFormatter;
13
14 import com.google.common.base.Optional;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.ImmutableSet;
17
18 import uk.org.lidalia.lang.ThreadLocal;
19 import uk.org.lidalia.slf4jext.Level;
20 import static com.google.common.base.Optional.fromNullable;
21 import static com.google.common.base.Optional.of;
22 import static com.google.common.collect.ImmutableList.copyOf;
23 import static com.google.common.collect.Sets.immutableEnumSet;
24 import static java.util.Arrays.asList;
25 import static uk.org.lidalia.slf4jext.Level.DEBUG;
26 import static uk.org.lidalia.slf4jext.Level.ERROR;
27 import static uk.org.lidalia.slf4jext.Level.INFO;
28 import static uk.org.lidalia.slf4jext.Level.TRACE;
29 import static uk.org.lidalia.slf4jext.Level.WARN;
30 import static uk.org.lidalia.slf4jext.Level.enablableValueSet;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 @SuppressWarnings({ "PMD.ExcessivePublicCount", "PMD.TooManyMethods" })
50 public class TestLogger implements Logger {
51
52 private final String name;
53 private final TestLoggerFactory testLoggerFactory;
54 private final ThreadLocal<List<LoggingEvent>> loggingEvents = new ThreadLocal<>(
55 Suppliers.<LoggingEvent>makeEmptyMutableList());
56
57 private final List<LoggingEvent> allLoggingEvents = new CopyOnWriteArrayList<>();
58 private volatile ThreadLocal<ImmutableSet<Level>> enabledLevels = new ThreadLocal<>(enablableValueSet());
59
60 TestLogger(final String name, final TestLoggerFactory testLoggerFactory) {
61 this.name = name;
62 this.testLoggerFactory = testLoggerFactory;
63 }
64
65 public String getName() {
66 return name;
67 }
68
69
70
71
72
73 public void clear() {
74 loggingEvents.get().clear();
75 enabledLevels.remove();
76 }
77
78
79
80
81
82
83 public void clearAll() {
84 allLoggingEvents.clear();
85 loggingEvents.reset();
86 enabledLevels.reset();
87 }
88
89
90
91
92 public ImmutableList<LoggingEvent> getLoggingEvents() {
93 return copyOf(loggingEvents.get());
94 }
95
96
97
98
99 public ImmutableList<LoggingEvent> getAllLoggingEvents() {
100 return copyOf(allLoggingEvents);
101 }
102
103
104
105
106 @Override
107 public boolean isTraceEnabled() {
108 return enabledLevels.get().contains(TRACE);
109 }
110
111 @Override
112 public void trace(final String message) {
113 log(TRACE, message);
114 }
115
116 @Override
117 public void trace(final String format, final Object arg) {
118 log(TRACE, format, arg);
119 }
120
121 @Override
122 public void trace(final String format, final Object arg1, final Object arg2) {
123 log(TRACE, format, arg1, arg2);
124 }
125
126 @Override
127 public void trace(final String format, final Object... args) {
128 log(TRACE, format, args);
129 }
130
131 @Override
132 public void trace(final String msg, final Throwable throwable) {
133 log(TRACE, msg, throwable);
134 }
135
136 @Override
137 public boolean isTraceEnabled(final Marker marker) {
138 return enabledLevels.get().contains(TRACE);
139 }
140
141 @Override
142 public void trace(final Marker marker, final String msg) {
143 log(TRACE, marker, msg);
144 }
145
146 @Override
147 public void trace(final Marker marker, final String format, final Object arg) {
148 log(TRACE, marker, format, arg);
149 }
150
151 @Override
152 public void trace(final Marker marker, final String format, final Object arg1, final Object arg2) {
153 log(TRACE, marker, format, arg1, arg2);
154 }
155
156 @Override
157 public void trace(final Marker marker, final String format, final Object... args) {
158 log(TRACE, marker, format, args);
159 }
160
161 @Override
162 public void trace(final Marker marker, final String msg, final Throwable throwable) {
163 log(TRACE, marker, msg, throwable);
164 }
165
166
167
168
169 @Override
170 public boolean isDebugEnabled() {
171 return enabledLevels.get().contains(DEBUG);
172 }
173
174 @Override
175 public void debug(final String message) {
176 log(DEBUG, message);
177 }
178
179 @Override
180 public void debug(final String format, final Object arg) {
181 log(DEBUG, format, arg);
182 }
183
184 @Override
185 public void debug(final String format, final Object arg1, final Object arg2) {
186 log(DEBUG, format, arg1, arg2);
187 }
188
189 @Override
190 public void debug(final String format, final Object... args) {
191 log(DEBUG, format, args);
192 }
193
194 @Override
195 public void debug(final String msg, final Throwable throwable) {
196 log(DEBUG, msg, throwable);
197 }
198
199 @Override
200 public boolean isDebugEnabled(final Marker marker) {
201 return enabledLevels.get().contains(DEBUG);
202 }
203
204 @Override
205 public void debug(final Marker marker, final String msg) {
206 log(DEBUG, marker, msg);
207 }
208
209 @Override
210 public void debug(final Marker marker, final String format, final Object arg) {
211 log(DEBUG, marker, format, arg);
212 }
213
214 @Override
215 public void debug(final Marker marker, final String format, final Object arg1, final Object arg2) {
216 log(DEBUG, marker, format, arg1, arg2);
217 }
218
219 @Override
220 public void debug(final Marker marker, final String format, final Object... args) {
221 log(DEBUG, marker, format, args);
222 }
223
224 @Override
225 public void debug(final Marker marker, final String msg, final Throwable throwable) {
226 log(DEBUG, marker, msg, throwable);
227 }
228
229
230
231
232 @Override
233 public boolean isInfoEnabled() {
234 return enabledLevels.get().contains(INFO);
235 }
236
237 @Override
238 public void info(final String message) {
239 log(INFO, message);
240 }
241
242 @Override
243 public void info(final String format, final Object arg) {
244 log(INFO, format, arg);
245 }
246
247 @Override
248 public void info(final String format, final Object arg1, final Object arg2) {
249 log(INFO, format, arg1, arg2);
250 }
251
252 @Override
253 public void info(final String format, final Object... args) {
254 log(INFO, format, args);
255 }
256
257 @Override
258 public void info(final String msg, final Throwable throwable) {
259 log(INFO, msg, throwable);
260 }
261
262 @Override
263 public boolean isInfoEnabled(final Marker marker) {
264 return enabledLevels.get().contains(INFO);
265 }
266
267 @Override
268 public void info(final Marker marker, final String msg) {
269 log(INFO, marker, msg);
270 }
271
272 @Override
273 public void info(final Marker marker, final String format, final Object arg) {
274 log(INFO, marker, format, arg);
275 }
276
277 @Override
278 public void info(final Marker marker, final String format, final Object arg1, final Object arg2) {
279 log(INFO, marker, format, arg1, arg2);
280 }
281
282 @Override
283 public void info(final Marker marker, final String format, final Object... args) {
284 log(INFO, marker, format, args);
285 }
286
287 @Override
288 public void info(final Marker marker, final String msg, final Throwable throwable) {
289 log(INFO, marker, msg, throwable);
290 }
291
292
293
294
295 @Override
296 public boolean isWarnEnabled() {
297 return enabledLevels.get().contains(WARN);
298 }
299
300 @Override
301 public void warn(final String message) {
302 log(WARN, message);
303 }
304
305 @Override
306 public void warn(final String format, final Object arg) {
307 log(WARN, format, arg);
308 }
309
310 @Override
311 public void warn(final String format, final Object arg1, final Object arg2) {
312 log(WARN, format, arg1, arg2);
313 }
314
315 @Override
316 public void warn(final String format, final Object... args) {
317 log(WARN, format, args);
318 }
319
320 @Override
321 public void warn(final String msg, final Throwable throwable) {
322 log(WARN, msg, throwable);
323 }
324
325 @Override
326 public boolean isWarnEnabled(final Marker marker) {
327 return enabledLevels.get().contains(WARN);
328 }
329
330 @Override
331 public void warn(final Marker marker, final String msg) {
332 log(WARN, marker, msg);
333 }
334
335 @Override
336 public void warn(final Marker marker, final String format, final Object arg) {
337 log(WARN, marker, format, arg);
338 }
339
340 @Override
341 public void warn(final Marker marker, final String format, final Object arg1, final Object arg2) {
342 log(WARN, marker, format, arg1, arg2);
343 }
344
345 @Override
346 public void warn(final Marker marker, final String format, final Object... args) {
347 log(WARN, marker, format, args);
348 }
349
350 @Override
351 public void warn(final Marker marker, final String msg, final Throwable throwable) {
352 log(WARN, marker, msg, throwable);
353 }
354
355
356
357
358 @Override
359 public boolean isErrorEnabled() {
360 return enabledLevels.get().contains(ERROR);
361 }
362
363 @Override
364 public void error(final String message) {
365 log(ERROR, message);
366 }
367
368 @Override
369 public void error(final String format, final Object arg) {
370 log(ERROR, format, arg);
371 }
372
373 @Override
374 public void error(final String format, final Object arg1, final Object arg2) {
375 log(ERROR, format, arg1, arg2);
376 }
377
378 @Override
379 public void error(final String format, final Object... args) {
380 log(ERROR, format, args);
381 }
382
383 @Override
384 public void error(final String msg, final Throwable throwable) {
385 log(ERROR, msg, throwable);
386 }
387
388 @Override
389 public boolean isErrorEnabled(final Marker marker) {
390 return enabledLevels.get().contains(ERROR);
391 }
392
393 @Override
394 public void error(final Marker marker, final String msg) {
395 log(ERROR, marker, msg);
396 }
397
398 @Override
399 public void error(final Marker marker, final String format, final Object arg) {
400 log(ERROR, marker, format, arg);
401 }
402
403 @Override
404 public void error(final Marker marker, final String format, final Object arg1, final Object arg2) {
405 log(ERROR, marker, format, arg1, arg2);
406 }
407
408 @Override
409 public void error(final Marker marker, final String format, final Object... args) {
410 log(ERROR, marker, format, args);
411 }
412
413 @Override
414 public void error(final Marker marker, final String msg, final Throwable throwable) {
415 log(ERROR, marker, msg, throwable);
416 }
417
418 private void log(final Level level, final String format, final Object... args) {
419 log(level, format, Optional.<Marker>absent(), args);
420 }
421
422 private void log(final Level level, final String msg, final Throwable throwable) {
423 addLoggingEvent(level, Optional.<Marker>absent(), fromNullable(throwable), msg);
424 }
425
426 private void log(final Level level, final Marker marker, final String format, final Object... args) {
427 log(level, format, fromNullable(marker), args);
428 }
429
430 private void log(final Level level, final Marker marker, final String msg, final Throwable throwable) {
431 addLoggingEvent(level, fromNullable(marker), fromNullable(throwable), msg);
432 }
433
434 private void log(final Level level, final String format, final Optional<Marker> marker, final Object[] args) {
435 final FormattingTuple formattedArgs = MessageFormatter.arrayFormat(format, args);
436 addLoggingEvent(level, marker, fromNullable(formattedArgs.getThrowable()), format, formattedArgs.getArgArray());
437 }
438
439 private void addLoggingEvent(
440 final Level level,
441 final Optional<Marker> marker,
442 final Optional<Throwable> throwable,
443 final String format,
444 final Object... args) {
445 if (enabledLevels.get().contains(level)) {
446 final LoggingEvent event = new LoggingEvent(of(this), level, mdc(), marker, throwable, format, args);
447 allLoggingEvents.add(event);
448 loggingEvents.get().add(event);
449 testLoggerFactory.addLoggingEvent(event);
450 optionallyPrint(event);
451 }
452 }
453
454 @SuppressWarnings("unchecked")
455 private Map<String, String> mdc() {
456 return fromNullable(MDC.getCopyOfContextMap()).or(Collections.emptyMap());
457 }
458
459 private void optionallyPrint(final LoggingEvent event) {
460 if (testLoggerFactory.getPrintLevel().compareTo(event.getLevel()) <= 0) {
461 event.print();
462 }
463 }
464
465
466
467
468 public ImmutableSet<Level> getEnabledLevels() {
469 return enabledLevels.get();
470 }
471
472
473
474
475
476
477
478
479
480
481 public void setEnabledLevels(final ImmutableSet<Level> enabledLevels) {
482 this.enabledLevels.set(enabledLevels);
483 }
484
485
486
487
488
489
490
491
492
493
494 public void setEnabledLevels(final Level... enabledLevels) {
495 setEnabledLevels(immutableEnumSet(asList(enabledLevels)));
496 }
497
498
499
500
501
502
503
504
505
506 public void setEnabledLevelsForAllThreads(final ImmutableSet<Level> enabledLevelsForAllThreads) {
507 this.enabledLevels = new ThreadLocal<>(enabledLevelsForAllThreads);
508 }
509
510
511
512
513
514
515
516
517
518 public void setEnabledLevelsForAllThreads(final Level... enabledLevelsForAllThreads) {
519 setEnabledLevelsForAllThreads(ImmutableSet.copyOf(enabledLevelsForAllThreads));
520 }
521 }