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