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