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