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 }