1
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.status.StatusListener;
41 import ch.qos.logback.core.status.StatusManager;
42 import ch.qos.logback.core.status.WarnStatus;
43
44
53 public class LoggerContext extends ContextBase implements ILoggerFactory, LifeCycle {
54
55
56 public static final boolean DEFAULT_PACKAGING_DATA = false;
57
58 final Logger root;
59 private int size;
60 private int noAppenderWarning = 0;
61 final private List<LoggerContextListener> loggerContextListenerList = new ArrayList<LoggerContextListener>();
62
63 private Map<String, Logger> loggerCache;
64
65 private LoggerContextVO loggerContextRemoteView;
66 private final TurboFilterList turboFilterList = new TurboFilterList();
67 private boolean packagingDataEnabled = DEFAULT_PACKAGING_DATA;
68
69 private int maxCallerDataDepth = ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH;
70
71 int resetCount = 0;
72 private List<String> frameworkPackages;
73
74 public LoggerContext() {
75 super();
76 this.loggerCache = new ConcurrentHashMap<String, Logger>();
77
78 this.loggerContextRemoteView = new LoggerContextVO(this);
79 this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
80 this.root.setLevel(Level.DEBUG);
81 loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
82 initEvaluatorMap();
83 size = 1;
84 this.frameworkPackages = new ArrayList<String>();
85 }
86
87 void initEvaluatorMap() {
88 putObject(EVALUATOR_MAP, new HashMap<String, EventEvaluator<?>>());
89 }
90
91
95 private void updateLoggerContextVO() {
96 loggerContextRemoteView = new LoggerContextVO(this);
97 }
98
99 @Override
100 public void putProperty(String key, String val) {
101 super.putProperty(key, val);
102 updateLoggerContextVO();
103 }
104
105 @Override
106 public void setName(String name) {
107 super.setName(name);
108 updateLoggerContextVO();
109 }
110
111 public final Logger getLogger(final Class<?> clazz) {
112 return getLogger(clazz.getName());
113 }
114
115 @Override
116 public final Logger getLogger(final String name) {
117
118 if (name == null) {
119 throw new IllegalArgumentException("name argument cannot be null");
120 }
121
122
123
124 if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
125 return root;
126 }
127
128 int i = 0;
129 Logger logger = root;
130
131
132
133 Logger childLogger = (Logger) loggerCache.get(name);
134
135 if (childLogger != null) {
136 return childLogger;
137 }
138
139
140
141 String childName;
142 while (true) {
143 int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
144 if (h == -1) {
145 childName = name;
146 } else {
147 childName = name.substring(0, h);
148 }
149
150 i = h + 1;
151 synchronized (logger) {
152 childLogger = logger.getChildByName(childName);
153 if (childLogger == null) {
154 childLogger = logger.createChildByName(childName);
155 loggerCache.put(childName, childLogger);
156 incSize();
157 }
158 }
159 logger = childLogger;
160 if (h == -1) {
161 return childLogger;
162 }
163 }
164 }
165
166 private void incSize() {
167 size++;
168 }
169
170 int size() {
171 return size;
172 }
173
174
180 public Logger exists(String name) {
181 return (Logger) loggerCache.get(name);
182 }
183
184 final void noAppenderDefinedWarning(final Logger logger) {
185 if (noAppenderWarning++ == 0) {
186 getStatusManager().add(new WarnStatus("No appenders present in context [" + getName() + "] for logger [" + logger.getName() + "].", logger));
187 }
188 }
189
190 public List<Logger> getLoggerList() {
191 Collection<Logger> collection = loggerCache.values();
192 List<Logger> loggerList = new ArrayList<Logger>(collection);
193 Collections.sort(loggerList, new LoggerComparator());
194 return loggerList;
195 }
196
197 public LoggerContextVO getLoggerContextRemoteView() {
198 return loggerContextRemoteView;
199 }
200
201 public void setPackagingDataEnabled(boolean packagingDataEnabled) {
202 this.packagingDataEnabled = packagingDataEnabled;
203 }
204
205 public boolean isPackagingDataEnabled() {
206 return packagingDataEnabled;
207 }
208
209
217 @Override
218 public void reset() {
219 resetCount++;
220 super.reset();
221 initEvaluatorMap();
222 initCollisionMaps();
223 root.recursiveReset();
224 resetTurboFilterList();
225 cancelScheduledTasks();
226 fireOnReset();
227 resetListenersExceptResetResistant();
228 resetStatusListeners();
229 }
230
231 private void cancelScheduledTasks() {
232 for(ScheduledFuture<?> sf: scheduledFutures) {
233 sf.cancel(false);
234 }
235 scheduledFutures.clear();
236 }
237
238 private void resetStatusListeners() {
239 StatusManager sm = getStatusManager();
240 for (StatusListener sl : sm.getCopyOfStatusListenerList()) {
241 sm.remove(sl);
242 }
243 }
244
245 public TurboFilterList getTurboFilterList() {
246 return turboFilterList;
247 }
248
249 public void addTurboFilter(TurboFilter newFilter) {
250 turboFilterList.add(newFilter);
251 }
252
253
257 public void resetTurboFilterList() {
258 for (TurboFilter tf : turboFilterList) {
259 tf.stop();
260 }
261 turboFilterList.clear();
262 }
263
264 final FilterReply getTurboFilterChainDecision_0_3OrMore(final Marker marker, final Logger logger, final Level level, final String format,
265 final Object[] params, final Throwable t) {
266 if (turboFilterList.size() == 0) {
267 return FilterReply.NEUTRAL;
268 }
269 return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, params, t);
270 }
271
272 final FilterReply getTurboFilterChainDecision_1(final Marker marker, final Logger logger, final Level level, final String format, final Object param,
273 final Throwable t) {
274 if (turboFilterList.size() == 0) {
275 return FilterReply.NEUTRAL;
276 }
277 return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param }, t);
278 }
279
280 final FilterReply getTurboFilterChainDecision_2(final Marker marker, final Logger logger, final Level level, final String format, final Object param1,
281 final Object param2, final Throwable t) {
282 if (turboFilterList.size() == 0) {
283 return FilterReply.NEUTRAL;
284 }
285 return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param1, param2 }, t);
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 public void start() {
343 super.start();
344 fireOnStart();
345 }
346
347 public void stop() {
348 reset();
349 fireOnStop();
350 resetAllListeners();
351 super.stop();
352 }
353
354 @Override
355 public String toString() {
356 return this.getClass().getName() + "[" + getName() + "]";
357 }
358
359 public int getMaxCallerDataDepth() {
360 return maxCallerDataDepth;
361 }
362
363 public void setMaxCallerDataDepth(int maxCallerDataDepth) {
364 this.maxCallerDataDepth = maxCallerDataDepth;
365 }
366
367
376 public List<String> getFrameworkPackages() {
377 return frameworkPackages;
378 }
379 }
380