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