1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic;
15
16 import ch.qos.logback.classic.spi.LoggerComparator;
17 import ch.qos.logback.classic.spi.LoggerContextListener;
18 import ch.qos.logback.classic.spi.LoggerContextVO;
19 import ch.qos.logback.classic.spi.TurboFilterList;
20 import ch.qos.logback.classic.turbo.TurboFilter;
21 import ch.qos.logback.classic.util.LoggerNameUtil;
22 import ch.qos.logback.core.ContextBase;
23 import ch.qos.logback.core.boolex.EventEvaluator;
24 import ch.qos.logback.core.spi.FilterReply;
25 import ch.qos.logback.core.spi.LifeCycle;
26 import ch.qos.logback.core.spi.SequenceNumberGenerator;
27 import ch.qos.logback.core.status.StatusListener;
28 import ch.qos.logback.core.status.StatusManager;
29 import ch.qos.logback.core.status.WarnStatus;
30 import org.slf4j.ILoggerFactory;
31 import org.slf4j.Marker;
32 import org.slf4j.spi.MDCAdapter;
33
34 import java.util.*;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ScheduledFuture;
37
38 import static ch.qos.logback.core.CoreConstants.EVALUATOR_MAP;
39
40
41
42
43
44
45
46
47
48
49 public class LoggerContext extends ContextBase implements ILoggerFactory, LifeCycle {
50
51
52
53
54 public static final boolean DEFAULT_PACKAGING_DATA = false;
55
56 final Logger root;
57 private int size;
58 private int noAppenderWarning = 0;
59 final private List<LoggerContextListener> loggerContextListenerList = new ArrayList<LoggerContextListener>();
60
61 private Map<String, Logger> loggerCache;
62
63 private LoggerContextVO loggerContextRemoteView;
64 private final TurboFilterList turboFilterList = new TurboFilterList();
65 private boolean packagingDataEnabled = DEFAULT_PACKAGING_DATA;
66 SequenceNumberGenerator sequenceNumberGenerator = null;
67
68 MDCAdapter mdcAdapter;
69
70 private int maxCallerDataDepth = ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH;
71
72 int resetCount = 0;
73 private List<String> frameworkPackages;
74
75 public LoggerContext() {
76 super();
77 this.loggerCache = new ConcurrentHashMap<String, Logger>();
78
79 this.loggerContextRemoteView = new LoggerContextVO(this);
80 this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
81 this.root.setLevel(Level.DEBUG);
82 loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
83 initEvaluatorMap();
84 size = 1;
85 this.frameworkPackages = new ArrayList<String>();
86
87
88
89 this.start();
90 }
91
92 void initEvaluatorMap() {
93 putObject(EVALUATOR_MAP, new HashMap<String, EventEvaluator<?>>());
94 }
95
96
97
98
99
100 private void updateLoggerContextVO() {
101 loggerContextRemoteView = new LoggerContextVO(this);
102 }
103
104 @Override
105 public void putProperty(String key, String val) {
106 super.putProperty(key, val);
107 updateLoggerContextVO();
108 }
109
110 @Override
111 public void setName(String name) {
112 super.setName(name);
113 updateLoggerContextVO();
114 }
115
116 public final Logger getLogger(final Class<?> clazz) {
117 return getLogger(clazz.getName());
118 }
119
120 @Override
121 public Logger getLogger(final String name) {
122
123 if (name == null) {
124 throw new IllegalArgumentException("name argument cannot be null");
125 }
126
127
128
129 if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
130 return root;
131 }
132
133 int i = 0;
134 Logger logger = root;
135
136
137
138 Logger childLogger = (Logger) loggerCache.get(name);
139
140 if (childLogger != null) {
141 return childLogger;
142 }
143
144
145
146 String childName;
147 while (true) {
148 int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
149 if (h == -1) {
150 childName = name;
151 } else {
152 childName = name.substring(0, h);
153 }
154
155 i = h + 1;
156 synchronized (logger) {
157 childLogger = logger.getChildByName(childName);
158 if (childLogger == null) {
159 childLogger = logger.createChildByName(childName);
160 loggerCache.put(childName, childLogger);
161 incSize();
162 }
163 }
164 logger = childLogger;
165 if (h == -1) {
166 return childLogger;
167 }
168 }
169 }
170
171 private void incSize() {
172 size++;
173 }
174
175 int size() {
176 return size;
177 }
178
179
180
181
182
183
184
185 public Logger exists(String name) {
186 return (Logger) loggerCache.get(name);
187 }
188
189 final void noAppenderDefinedWarning(final Logger logger) {
190 if (noAppenderWarning++ == 0) {
191 getStatusManager().add(new WarnStatus("No appenders present in context [" + getName() + "] for logger [" + logger.getName() + "].", logger));
192 }
193 }
194
195 public List<Logger> getLoggerList() {
196 Collection<Logger> collection = loggerCache.values();
197 List<Logger> loggerList = new ArrayList<Logger>(collection);
198 Collections.sort(loggerList, new LoggerComparator());
199 return loggerList;
200 }
201
202 public LoggerContextVO getLoggerContextRemoteView() {
203 return loggerContextRemoteView;
204 }
205
206 public void setPackagingDataEnabled(boolean packagingDataEnabled) {
207 this.packagingDataEnabled = packagingDataEnabled;
208 }
209
210 public boolean isPackagingDataEnabled() {
211 return packagingDataEnabled;
212 }
213
214 void cancelScheduledTasks() {
215
216 try {
217 configurationLock.lock();
218
219 for (ScheduledFuture<?> sf : scheduledFutures) {
220 sf.cancel(false);
221 }
222 scheduledFutures.clear();
223 } finally {
224 configurationLock.unlock();
225 }
226 }
227
228 private void resetStatusListenersExceptResetResistant() {
229 StatusManager sm = getStatusManager();
230 for (StatusListener sl : sm.getCopyOfStatusListenerList()) {
231 if (!sl.isResetResistant()) {
232 sm.remove(sl);
233 }
234 }
235 }
236
237 public TurboFilterList getTurboFilterList() {
238 return turboFilterList;
239 }
240
241 public void addTurboFilter(TurboFilter newFilter) {
242 turboFilterList.add(newFilter);
243 }
244
245
246
247
248
249 public void resetTurboFilterList() {
250 for (TurboFilter tf : turboFilterList) {
251 tf.stop();
252 }
253 turboFilterList.clear();
254 }
255
256 final FilterReply getTurboFilterChainDecision_0_3OrMore(final Marker marker, final Logger logger, final Level level, final String format,
257 final Object[] params, final Throwable t) {
258 if (turboFilterList.size() == 0) {
259 return FilterReply.NEUTRAL;
260 }
261 return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, params, t);
262 }
263
264 final FilterReply getTurboFilterChainDecision_1(final Marker marker, final Logger logger, final Level level, final String format, final Object param,
265 final Throwable t) {
266 if (turboFilterList.size() == 0) {
267 return FilterReply.NEUTRAL;
268 }
269 return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param }, t);
270 }
271
272 final FilterReply getTurboFilterChainDecision_2(final Marker marker, final Logger logger, final Level level, final String format, final Object param1,
273 final Object param2, final Throwable t) {
274 if (turboFilterList.isEmpty()) {
275 return FilterReply.NEUTRAL;
276 }
277 return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param1, param2 }, t);
278 }
279
280 final FilterReply getTurboFilterChainDecision(final Logger logger, final org.slf4j.event.LoggingEvent slf4jEvent) {
281 if (turboFilterList.isEmpty()) {
282 return FilterReply.NEUTRAL;
283 }
284 return turboFilterList.getTurboFilterChainDecision(logger, slf4jEvent);
285 }
286
287
288
289 public void addListener(LoggerContextListener listener) {
290 loggerContextListenerList.add(listener);
291 }
292
293 public void removeListener(LoggerContextListener listener) {
294 loggerContextListenerList.remove(listener);
295 }
296
297 private void resetListenersExceptResetResistant() {
298 List<LoggerContextListener> toRetain = new ArrayList<LoggerContextListener>();
299
300 for (LoggerContextListener lcl : loggerContextListenerList) {
301 if (lcl.isResetResistant()) {
302 toRetain.add(lcl);
303 }
304 }
305 loggerContextListenerList.retainAll(toRetain);
306 }
307
308 private void resetAllListeners() {
309 loggerContextListenerList.clear();
310 }
311
312 public List<LoggerContextListener> getCopyOfListenerList() {
313 return new ArrayList<LoggerContextListener>(loggerContextListenerList);
314 }
315
316 void fireOnLevelChange(Logger logger, Level level) {
317 for (LoggerContextListener listener : loggerContextListenerList) {
318 listener.onLevelChange(logger, level);
319 }
320 }
321
322 private void fireOnReset() {
323 for (LoggerContextListener listener : loggerContextListenerList) {
324 listener.onReset(this);
325 }
326 }
327
328 private void fireOnStart() {
329 for (LoggerContextListener listener : loggerContextListenerList) {
330 listener.onStart(this);
331 }
332 }
333
334 private void fireOnStop() {
335 for (LoggerContextListener listener : loggerContextListenerList) {
336 listener.onStop(this);
337 }
338 }
339
340
341
342 @Override
343 public void start() {
344 super.start();
345 fireOnStart();
346 }
347
348 public void stop() {
349 if (!isStarted())
350 return;
351
352 try {
353 configurationLock.lock();
354 if (!isStarted())
355 return;
356
357 reset();
358 fireOnStop();
359 resetAllListeners();
360 super.stop();
361 } finally {
362 configurationLock.unlock();
363 }
364 }
365
366
367
368
369
370
371
372
373
374 @Override
375 public void reset() {
376 resetCount++;
377 super.reset();
378 initEvaluatorMap();
379 root.recursiveReset();
380 resetTurboFilterList();
381 cancelScheduledTasks();
382 fireOnReset();
383 resetListenersExceptResetResistant();
384 resetStatusListenersExceptResetResistant();
385 }
386
387 @Override
388 public String toString() {
389 return this.getClass().getName() + "[" + getName() + "]";
390 }
391
392 public int getMaxCallerDataDepth() {
393 return maxCallerDataDepth;
394 }
395
396 public void setMaxCallerDataDepth(int maxCallerDataDepth) {
397 this.maxCallerDataDepth = maxCallerDataDepth;
398 }
399
400
401
402
403
404
405
406
407
408
409
410 public List<String> getFrameworkPackages() {
411 return frameworkPackages;
412 }
413
414 @Override
415 public void setSequenceNumberGenerator(SequenceNumberGenerator sng) {
416 this.sequenceNumberGenerator = sng;
417 }
418
419 @Override
420 public SequenceNumberGenerator getSequenceNumberGenerator() {
421 return sequenceNumberGenerator;
422 }
423
424 public MDCAdapter getMDCAdapter() {
425 return mdcAdapter;
426 }
427
428 public void setMDCAdapter(MDCAdapter anAdapter) {
429 if (this.mdcAdapter != null) {
430 StatusManager sm = getStatusManager();
431 sm.add(new WarnStatus("mdcAdapter being reset a second time", this));
432 }
433 this.mdcAdapter = anAdapter;
434 }
435 }