001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.log4j; 018 019import java.util.Enumeration; 020import java.util.Map; 021import java.util.ResourceBundle; 022import java.util.WeakHashMap; 023import java.util.concurrent.ConcurrentHashMap; 024import java.util.concurrent.ConcurrentMap; 025 026import org.apache.log4j.helpers.NullEnumeration; 027import org.apache.log4j.spi.LoggerFactory; 028import org.apache.log4j.spi.LoggingEvent; 029import org.apache.logging.log4j.core.LoggerContext; 030import org.apache.logging.log4j.core.util.NameUtil; 031import org.apache.logging.log4j.message.LocalizedMessage; 032import org.apache.logging.log4j.message.Message; 033import org.apache.logging.log4j.message.ObjectMessage; 034import org.apache.logging.log4j.spi.AbstractLoggerAdapter; 035import org.apache.logging.log4j.util.Strings; 036 037 038/** 039 * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago. 040 */ 041public class Category { 042 043 private static PrivateAdapter adapter = new PrivateAdapter(); 044 045 private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP = 046 new WeakHashMap<>(); 047 048 private static final String FQCN = Category.class.getName(); 049 050 /** 051 * Resource bundle for localized messages. 052 */ 053 protected ResourceBundle bundle = null; 054 055 private final org.apache.logging.log4j.core.Logger logger; 056 057 /** 058 * Constructor used by Logger to specify a LoggerContext. 059 * @param context The LoggerContext. 060 * @param name The name of the Logger. 061 */ 062 protected Category(final LoggerContext context, final String name) { 063 this.logger = context.getLogger(name); 064 } 065 066 /** 067 * Constructor exposed by Log4j 1.2. 068 * @param name The name of the Logger. 069 */ 070 protected Category(final String name) { 071 this(PrivateManager.getContext(), name); 072 } 073 074 private Category(final org.apache.logging.log4j.core.Logger logger) { 075 this.logger = logger; 076 } 077 078 public static Category getInstance(final String name) { 079 return getInstance(PrivateManager.getContext(), name, adapter); 080 } 081 082 static Logger getInstance(final LoggerContext context, final String name) { 083 return getInstance(context, name, adapter); 084 } 085 086 static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) { 087 final ConcurrentMap<String, Logger> loggers = getLoggersMap(context); 088 Logger logger = loggers.get(name); 089 if (logger != null) { 090 return logger; 091 } 092 logger = factory.makeNewLoggerInstance(name); 093 final Logger prev = loggers.putIfAbsent(name, logger); 094 return prev == null ? logger : prev; 095 } 096 097 static Logger getInstance(final LoggerContext context, final String name, final PrivateAdapter factory) { 098 final ConcurrentMap<String, Logger> loggers = getLoggersMap(context); 099 Logger logger = loggers.get(name); 100 if (logger != null) { 101 return logger; 102 } 103 logger = factory.newLogger(name, context); 104 final Logger prev = loggers.putIfAbsent(name, logger); 105 return prev == null ? logger : prev; 106 } 107 108 public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) { 109 return getInstance(clazz.getName()); 110 } 111 112 static Logger getInstance(final LoggerContext context, @SuppressWarnings("rawtypes") final Class clazz) { 113 return getInstance(context, clazz.getName()); 114 } 115 116 public final String getName() { 117 return logger.getName(); 118 } 119 120 org.apache.logging.log4j.core.Logger getLogger() { 121 return logger; 122 } 123 124 public final Category getParent() { 125 final org.apache.logging.log4j.core.Logger parent = logger.getParent(); 126 if (parent == null) { 127 return null; 128 } 129 final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext()); 130 final Logger l = loggers.get(parent.getName()); 131 return l == null ? new Category(parent) : l; 132 } 133 134 public static Category getRoot() { 135 return getInstance(Strings.EMPTY); 136 } 137 138 static Logger getRoot(final LoggerContext context) { 139 return getInstance(context, Strings.EMPTY); 140 } 141 142 private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) { 143 synchronized (CONTEXT_MAP) { 144 ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context); 145 if (map == null) { 146 map = new ConcurrentHashMap<>(); 147 CONTEXT_MAP.put(context, map); 148 } 149 return map; 150 } 151 } 152 153 /** 154 Returns all the currently defined categories in the default 155 hierarchy as an {@link java.util.Enumeration Enumeration}. 156 157 <p>The root category is <em>not</em> included in the returned 158 {@link Enumeration}. 159 @return and Enumeration of the Categories. 160 161 @deprecated Please use {@link LogManager#getCurrentLoggers()} instead. 162 */ 163 @SuppressWarnings("rawtypes") 164 @Deprecated 165 public static Enumeration getCurrentCategories() { 166 return LogManager.getCurrentLoggers(); 167 } 168 169 public final Level getEffectiveLevel() { 170 switch (logger.getLevel().getStandardLevel()) { 171 case ALL: 172 return Level.ALL; 173 case TRACE: 174 return Level.TRACE; 175 case DEBUG: 176 return Level.DEBUG; 177 case INFO: 178 return Level.INFO; 179 case WARN: 180 return Level.WARN; 181 case ERROR: 182 return Level.ERROR; 183 case FATAL: 184 return Level.FATAL; 185 case OFF: 186 return Level.OFF; 187 default: 188 // TODO Should this be an IllegalStateException? 189 return Level.OFF; 190 } 191 } 192 193 public final Priority getChainedPriority() { 194 return getEffectiveLevel(); 195 } 196 197 public final Level getLevel() { 198 return getEffectiveLevel(); 199 } 200 201 public void setLevel(final Level level) { 202 logger.setLevel(org.apache.logging.log4j.Level.toLevel(level.levelStr)); 203 } 204 205 public final Level getPriority() { 206 return getEffectiveLevel(); 207 } 208 209 public void setPriority(final Priority priority) { 210 logger.setLevel(org.apache.logging.log4j.Level.toLevel(priority.levelStr)); 211 } 212 213 public void debug(final Object message) { 214 maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null); 215 } 216 217 public void debug(final Object message, final Throwable t) { 218 maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t); 219 } 220 221 public boolean isDebugEnabled() { 222 return logger.isDebugEnabled(); 223 } 224 225 public void error(final Object message) { 226 maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null); 227 } 228 229 public void error(final Object message, final Throwable t) { 230 maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t); 231 } 232 233 public boolean isErrorEnabled() { 234 return logger.isErrorEnabled(); 235 } 236 237 public void warn(final Object message) { 238 maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null); 239 } 240 241 public void warn(final Object message, final Throwable t) { 242 maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t); 243 } 244 245 public boolean isWarnEnabled() { 246 return logger.isWarnEnabled(); 247 } 248 249 public void fatal(final Object message) { 250 maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null); 251 } 252 253 public void fatal(final Object message, final Throwable t) { 254 maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t); 255 } 256 257 public boolean isFatalEnabled() { 258 return logger.isFatalEnabled(); 259 } 260 261 public void info(final Object message) { 262 maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null); 263 } 264 265 public void info(final Object message, final Throwable t) { 266 maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t); 267 } 268 269 public boolean isInfoEnabled() { 270 return logger.isInfoEnabled(); 271 } 272 273 public void trace(final Object message) { 274 maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null); 275 } 276 277 public void trace(final Object message, final Throwable t) { 278 maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t); 279 } 280 281 public boolean isTraceEnabled() { 282 return logger.isTraceEnabled(); 283 } 284 285 public boolean isEnabledFor(final Priority level) { 286 final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString()); 287 return isEnabledFor(lvl); 288 } 289 290 /** 291 * No-op implementation. 292 * @param appender The Appender to add. 293 */ 294 public void addAppender(final Appender appender) { 295 } 296 297 /** 298 * No-op implementation. 299 * @param event The logging event. 300 */ 301 public void callAppenders(final LoggingEvent event) { 302 } 303 304 @SuppressWarnings("rawtypes") 305 public Enumeration getAllAppenders() { 306 return NullEnumeration.getInstance(); 307 } 308 309 /** 310 * No-op implementation. 311 * @param name The name of the Appender. 312 * @return null. 313 */ 314 public Appender getAppender(final String name) { 315 return null; 316 } 317 318 /** 319 Is the appender passed as parameter attached to this category? 320 * @param appender The Appender to add. 321 * @return true if the appender is attached. 322 */ 323 public boolean isAttached(final Appender appender) { 324 return false; 325 } 326 327 /** 328 * No-op implementation. 329 */ 330 public void removeAllAppenders() { 331 } 332 333 /** 334 * No-op implementation. 335 * @param appender The Appender to remove. 336 */ 337 public void removeAppender(final Appender appender) { 338 } 339 340 /** 341 * No-op implementation. 342 * @param name The Appender to remove. 343 */ 344 public void removeAppender(final String name) { 345 } 346 347 /** 348 * No-op implementation. 349 */ 350 public static void shutdown() { 351 } 352 353 354 public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) { 355 final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString()); 356 final Message msg = message instanceof Message ? (Message) message : new ObjectMessage(message); 357 logger.logMessage(fqcn, lvl, null, msg, t); 358 } 359 360 public boolean exists(final String name) { 361 return PrivateManager.getContext().hasLogger(name); 362 } 363 364 public boolean getAdditivity() { 365 return logger.isAdditive(); 366 } 367 368 public void setAdditivity(final boolean additivity) { 369 logger.setAdditive(additivity); 370 } 371 372 public void setResourceBundle(final ResourceBundle bundle) { 373 this.bundle = bundle; 374 } 375 376 public ResourceBundle getResourceBundle() { 377 if (bundle != null) { 378 return bundle; 379 } 380 String name = logger.getName(); 381 final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext()); 382 while ((name = NameUtil.getSubName(name)) != null) { 383 final Logger subLogger = loggers.get(name); 384 if (subLogger != null) { 385 final ResourceBundle rb = subLogger.bundle; 386 if (rb != null) { 387 return rb; 388 } 389 } 390 } 391 return null; 392 } 393 394 /** 395 If <code>assertion</code> parameter is {@code false}, then 396 logs <code>msg</code> as an {@link #error(Object) error} statement. 397 398 <p>The <code>assert</code> method has been renamed to 399 <code>assertLog</code> because <code>assert</code> is a language 400 reserved word in JDK 1.4. 401 402 @param assertion The assertion. 403 @param msg The message to print if <code>assertion</code> is 404 false. 405 406 @since 1.2 407 */ 408 public void assertLog(final boolean assertion, final String msg) { 409 if (!assertion) { 410 this.error(msg); 411 } 412 } 413 414 public void l7dlog(final Priority priority, final String key, final Throwable t) { 415 if (isEnabledFor(priority)) { 416 final Message msg = new LocalizedMessage(bundle, key, null); 417 forcedLog(FQCN, priority, msg, t); 418 } 419 } 420 421 public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) { 422 if (isEnabledFor(priority)) { 423 final Message msg = new LocalizedMessage(bundle, key, params); 424 forcedLog(FQCN, priority, msg, t); 425 } 426 } 427 428 public void log(final Priority priority, final Object message, final Throwable t) { 429 if (isEnabledFor(priority)) { 430 final Message msg = new ObjectMessage(message); 431 forcedLog(FQCN, priority, msg, t); 432 } 433 } 434 435 public void log(final Priority priority, final Object message) { 436 if (isEnabledFor(priority)) { 437 final Message msg = new ObjectMessage(message); 438 forcedLog(FQCN, priority, msg, null); 439 } 440 } 441 442 public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) { 443 if (isEnabledFor(priority)) { 444 final Message msg = new ObjectMessage(message); 445 forcedLog(fqcn, priority, msg, t); 446 } 447 } 448 449 private void maybeLog(final String fqcn, final org.apache.logging.log4j.Level level, 450 final Object message, final Throwable throwable) { 451 if (logger.isEnabled(level, null, message, throwable)) { 452 logger.logMessage(FQCN, level, null, new ObjectMessage(message), throwable); 453 } 454 } 455 456 private static class PrivateAdapter extends AbstractLoggerAdapter<Logger> { 457 458 @Override 459 protected Logger newLogger(final String name, final org.apache.logging.log4j.spi.LoggerContext context) { 460 return new Logger((LoggerContext) context, name); 461 } 462 463 @Override 464 protected org.apache.logging.log4j.spi.LoggerContext getContext() { 465 return PrivateManager.getContext(); 466 } 467 } 468 469 /** 470 * Private LogManager. 471 */ 472 private static class PrivateManager extends org.apache.logging.log4j.LogManager { 473 private static final String FQCN = Category.class.getName(); 474 475 public static LoggerContext getContext() { 476 return (LoggerContext) getContext(FQCN, false); 477 } 478 479 public static org.apache.logging.log4j.Logger getLogger(final String name) { 480 return getLogger(FQCN, name); 481 } 482 } 483 484 private boolean isEnabledFor(final org.apache.logging.log4j.Level level) { 485 return logger.isEnabled(level, null, null); 486 } 487 488}