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