1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j;
18
19 import java.util.Enumeration;
20 import java.util.Map;
21 import java.util.ResourceBundle;
22 import java.util.WeakHashMap;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.concurrent.ConcurrentMap;
25
26 import org.apache.log4j.helpers.NullEnumeration;
27 import org.apache.log4j.legacy.core.CategoryUtil;
28 import org.apache.log4j.or.ObjectRenderer;
29 import org.apache.log4j.or.RendererSupport;
30 import org.apache.log4j.spi.LoggerFactory;
31 import org.apache.log4j.spi.LoggingEvent;
32 import org.apache.logging.log4j.message.MapMessage;
33 import org.apache.logging.log4j.message.SimpleMessage;
34 import org.apache.logging.log4j.spi.ExtendedLogger;
35 import org.apache.logging.log4j.spi.LoggerContext;
36 import org.apache.logging.log4j.message.LocalizedMessage;
37 import org.apache.logging.log4j.message.Message;
38 import org.apache.logging.log4j.message.ObjectMessage;
39 import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
40 import org.apache.logging.log4j.util.Strings;
41
42
43
44
45
46 public class Category {
47
48 private static PrivateAdapter adapter = new PrivateAdapter();
49
50 private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP =
51 new WeakHashMap<>();
52
53 private static final String FQCN = Category.class.getName();
54
55 private static final boolean isCoreAvailable;
56
57 private final Map<Class<?>, ObjectRenderer> rendererMap;
58
59 static {
60 boolean available;
61
62 try {
63 available = Class.forName("org.apache.logging.log4j.core.Logger") != null;
64 } catch (Exception ex) {
65 available = false;
66 }
67 isCoreAvailable = available;
68 }
69
70
71
72
73 protected ResourceBundle bundle = null;
74
75 private final org.apache.logging.log4j.Logger logger;
76
77
78
79
80
81
82 protected Category(final LoggerContext context, final String name) {
83 this.logger = context.getLogger(name);
84 rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
85 }
86
87
88
89
90
91 protected Category(final String name) {
92 this(PrivateManager.getContext(), name);
93 }
94
95 private Category(final org.apache.logging.log4j.Logger logger) {
96 this.logger = logger;
97 rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
98 }
99
100 public static Category getInstance(final String name) {
101 return getInstance(PrivateManager.getContext(), name, adapter);
102 }
103
104 static Logger getInstance(final LoggerContext context, final String name) {
105 return getInstance(context, name, adapter);
106 }
107
108 static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
109 final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
110 Logger logger = loggers.get(name);
111 if (logger != null) {
112 return logger;
113 }
114 logger = factory.makeNewLoggerInstance(name);
115 final Logger prev = loggers.putIfAbsent(name, logger);
116 return prev == null ? logger : prev;
117 }
118
119 static Logger getInstance(final LoggerContext context, final String name, final PrivateAdapter factory) {
120 final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
121 Logger logger = loggers.get(name);
122 if (logger != null) {
123 return logger;
124 }
125 logger = factory.newLogger(name, context);
126 final Logger prev = loggers.putIfAbsent(name, logger);
127 return prev == null ? logger : prev;
128 }
129
130 public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) {
131 return getInstance(clazz.getName());
132 }
133
134 static Logger getInstance(final LoggerContext context, @SuppressWarnings("rawtypes") final Class clazz) {
135 return getInstance(context, clazz.getName());
136 }
137
138 public final String getName() {
139 return logger.getName();
140 }
141
142 org.apache.logging.log4j.Logger getLogger() {
143 return logger;
144 }
145
146 public final Category getParent() {
147 if (!isCoreAvailable) {
148 return null;
149 }
150 org.apache.logging.log4j.Logger parent = CategoryUtil.getParent(logger);
151 LoggerContext loggerContext = CategoryUtil.getLoggerContext(logger);
152 if (parent == null || loggerContext == null) {
153 return null;
154 }
155 final ConcurrentMap<String, Logger> loggers = getLoggersMap(loggerContext);
156 final Logger l = loggers.get(parent.getName());
157 return l == null ? new Category(parent) : l;
158 }
159
160 public static Category getRoot() {
161 return getInstance(Strings.EMPTY);
162 }
163
164 static Logger getRoot(final LoggerContext context) {
165 return getInstance(context, Strings.EMPTY);
166 }
167
168 private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
169 synchronized (CONTEXT_MAP) {
170 ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context);
171 if (map == null) {
172 map = new ConcurrentHashMap<>();
173 CONTEXT_MAP.put(context, map);
174 }
175 return map;
176 }
177 }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192 @SuppressWarnings("rawtypes")
193 @Deprecated
194 public static Enumeration getCurrentCategories() {
195 return LogManager.getCurrentLoggers();
196 }
197
198 public final Level getEffectiveLevel() {
199 switch (logger.getLevel().getStandardLevel()) {
200 case ALL:
201 return Level.ALL;
202 case TRACE:
203 return Level.TRACE;
204 case DEBUG:
205 return Level.DEBUG;
206 case INFO:
207 return Level.INFO;
208 case WARN:
209 return Level.WARN;
210 case ERROR:
211 return Level.ERROR;
212 case FATAL:
213 return Level.FATAL;
214 default:
215
216 return Level.OFF;
217 }
218 }
219
220 public final Priority getChainedPriority() {
221 return getEffectiveLevel();
222 }
223
224 public final Level getLevel() {
225 return getEffectiveLevel();
226 }
227
228 private String getLevelStr(final Priority priority) {
229 return priority == null ? null : priority.levelStr;
230 }
231
232 public void setLevel(final Level level) {
233 setLevel(getLevelStr(level));
234 }
235
236 public final Level getPriority() {
237 return getEffectiveLevel();
238 }
239
240 public void setPriority(final Priority priority) {
241 setLevel(getLevelStr(priority));
242 }
243
244 private void setLevel(final String levelStr) {
245 if (isCoreAvailable) {
246 CategoryUtil.setLevel(logger, org.apache.logging.log4j.Level.toLevel(levelStr));
247 }
248 }
249
250 public void debug(final Object message) {
251 maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null);
252 }
253
254 public void debug(final Object message, final Throwable t) {
255 maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t);
256 }
257
258 public boolean isDebugEnabled() {
259 return logger.isDebugEnabled();
260 }
261
262 public void error(final Object message) {
263 maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null);
264 }
265
266 public void error(final Object message, final Throwable t) {
267 maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t);
268 }
269
270 public boolean isErrorEnabled() {
271 return logger.isErrorEnabled();
272 }
273
274 public void warn(final Object message) {
275 maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null);
276 }
277
278 public void warn(final Object message, final Throwable t) {
279 maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t);
280 }
281
282 public boolean isWarnEnabled() {
283 return logger.isWarnEnabled();
284 }
285
286 public void fatal(final Object message) {
287 maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null);
288 }
289
290 public void fatal(final Object message, final Throwable t) {
291 maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t);
292 }
293
294 public boolean isFatalEnabled() {
295 return logger.isFatalEnabled();
296 }
297
298 public void info(final Object message) {
299 maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null);
300 }
301
302 public void info(final Object message, final Throwable t) {
303 maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t);
304 }
305
306 public boolean isInfoEnabled() {
307 return logger.isInfoEnabled();
308 }
309
310 public void trace(final Object message) {
311 maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null);
312 }
313
314 public void trace(final Object message, final Throwable t) {
315 maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t);
316 }
317
318 public boolean isTraceEnabled() {
319 return logger.isTraceEnabled();
320 }
321
322 public boolean isEnabledFor(final Priority level) {
323 final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
324 return isEnabledFor(lvl);
325 }
326
327
328
329
330
331 public void addAppender(final Appender appender) {
332 }
333
334
335
336
337
338 public void callAppenders(final LoggingEvent event) {
339 }
340
341 @SuppressWarnings("rawtypes")
342 public Enumeration getAllAppenders() {
343 return NullEnumeration.getInstance();
344 }
345
346
347
348
349
350
351 public Appender getAppender(final String name) {
352 return null;
353 }
354
355
356
357
358
359
360 public boolean isAttached(final Appender appender) {
361 return false;
362 }
363
364
365
366
367 public void removeAllAppenders() {
368 }
369
370
371
372
373
374 public void removeAppender(final Appender appender) {
375 }
376
377
378
379
380
381 public void removeAppender(final String name) {
382 }
383
384
385
386
387 public static void shutdown() {
388 }
389
390 public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
391 final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
392 if (logger instanceof ExtendedLogger) {
393 @SuppressWarnings("unchecked")
394 Message msg = message instanceof Message ? (Message) message : message instanceof Map ?
395 new MapMessage((Map) message) : new ObjectMessage(message);
396 ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, msg, t);
397 } else {
398 ObjectRenderer renderer = get(message.getClass());
399 final Message msg = message instanceof Message ? (Message) message : renderer != null ?
400 new RenderedMessage(renderer, message) : new ObjectMessage(message);
401 logger.log(lvl, msg, t);
402 }
403 }
404
405 public boolean exists(final String name) {
406 return PrivateManager.getContext().hasLogger(name);
407 }
408
409 public boolean getAdditivity() {
410 return isCoreAvailable ? CategoryUtil.isAdditive(logger) : false;
411 }
412
413 public void setAdditivity(final boolean additivity) {
414 if (isCoreAvailable) {
415 CategoryUtil.setAdditivity(logger, additivity);
416 }
417 }
418
419 public void setResourceBundle(final ResourceBundle bundle) {
420 this.bundle = bundle;
421 }
422
423 public ResourceBundle getResourceBundle() {
424 if (bundle != null) {
425 return bundle;
426 }
427 String name = logger.getName();
428 if (isCoreAvailable) {
429 LoggerContext ctx = CategoryUtil.getLoggerContext(logger);
430 if (ctx != null) {
431 final ConcurrentMap<String, Logger> loggers = getLoggersMap(ctx);
432 while ((name = getSubName(name)) != null) {
433 final Logger subLogger = loggers.get(name);
434 if (subLogger != null) {
435 final ResourceBundle rb = subLogger.bundle;
436 if (rb != null) {
437 return rb;
438 }
439 }
440 }
441 }
442 }
443 return null;
444 }
445
446 private static String getSubName(final String name) {
447 if (Strings.isEmpty(name)) {
448 return null;
449 }
450 final int i = name.lastIndexOf('.');
451 return i > 0 ? name.substring(0, i) : Strings.EMPTY;
452 }
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 public void assertLog(final boolean assertion, final String msg) {
469 if (!assertion) {
470 this.error(msg);
471 }
472 }
473
474 public void l7dlog(final Priority priority, final String key, final Throwable t) {
475 if (isEnabledFor(priority)) {
476 final Message msg = new LocalizedMessage(bundle, key, null);
477 forcedLog(FQCN, priority, msg, t);
478 }
479 }
480
481 public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) {
482 if (isEnabledFor(priority)) {
483 final Message msg = new LocalizedMessage(bundle, key, params);
484 forcedLog(FQCN, priority, msg, t);
485 }
486 }
487
488 public void log(final Priority priority, final Object message, final Throwable t) {
489 if (isEnabledFor(priority)) {
490 @SuppressWarnings("unchecked")
491 final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
492 forcedLog(FQCN, priority, msg, t);
493 }
494 }
495
496 public void log(final Priority priority, final Object message) {
497 if (isEnabledFor(priority)) {
498 @SuppressWarnings("unchecked")
499 final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message);
500 forcedLog(FQCN, priority, msg, null);
501 }
502 }
503
504 public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) {
505 if (isEnabledFor(priority)) {
506 final Message msg = new ObjectMessage(message);
507 forcedLog(fqcn, priority, msg, t);
508 }
509 }
510
511 private void maybeLog(
512 final String fqcn,
513 final org.apache.logging.log4j.Level level,
514 final Object message,
515 final Throwable throwable) {
516 if (logger.isEnabled(level)) {
517 final Message msg;
518 if (message instanceof String) {
519 msg = new SimpleMessage((String) message);
520 }
521
522
523 else if (message instanceof CharSequence) {
524 msg = new SimpleMessage((CharSequence) message);
525 } else if (message instanceof Map) {
526 @SuppressWarnings("unchecked")
527 final Map<String, ?> map = (Map<String, ?>) message;
528 msg = new MapMessage<>(map);
529 } else {
530 msg = new ObjectMessage(message);
531 }
532 if (logger instanceof ExtendedLogger) {
533 ((ExtendedLogger) logger).logMessage(fqcn, level, null, msg, throwable);
534 } else {
535 logger.log(level, msg, throwable);
536 }
537 }
538 }
539
540 private static class PrivateAdapter extends AbstractLoggerAdapter<Logger> {
541
542 @Override
543 protected Logger newLogger(final String name, final org.apache.logging.log4j.spi.LoggerContext context) {
544 return new Logger(context, name);
545 }
546
547 @Override
548 protected org.apache.logging.log4j.spi.LoggerContext getContext() {
549 return PrivateManager.getContext();
550 }
551 }
552
553
554
555
556 private static class PrivateManager extends org.apache.logging.log4j.LogManager {
557 private static final String FQCN = Category.class.getName();
558
559 public static LoggerContext getContext() {
560 return getContext(FQCN, false);
561 }
562
563 public static org.apache.logging.log4j.Logger getLogger(final String name) {
564 return getLogger(FQCN, name);
565 }
566 }
567
568 private boolean isEnabledFor(final org.apache.logging.log4j.Level level) {
569 return logger.isEnabled(level);
570 }
571
572 private <T> ObjectRenderer get(Class<T> clazz) {
573 ObjectRenderer renderer = null;
574 for (Class<? super T> c = clazz; c != null; c = c.getSuperclass()) {
575 renderer = rendererMap.get(c);
576 if (renderer != null) {
577 return renderer;
578 }
579 renderer = searchInterfaces(c);
580 if (renderer != null) {
581 return renderer;
582 }
583 }
584 return null;
585 }
586
587 ObjectRenderer searchInterfaces(Class<?> c) {
588 ObjectRenderer renderer = rendererMap.get(c);
589 if (renderer != null) {
590 return renderer;
591 }
592 Class<?>[] ia = c.getInterfaces();
593 for (Class<?> clazz : ia) {
594 renderer = searchInterfaces(clazz);
595 if (renderer != null) {
596 return renderer;
597 }
598 }
599 return null;
600 }
601
602 }