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