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