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