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.logging.log4j; 018 019import java.net.URI; 020import java.util.Map; 021import java.util.SortedMap; 022import java.util.TreeMap; 023 024import org.apache.logging.log4j.message.MessageFactory; 025import org.apache.logging.log4j.message.StringFormatterMessageFactory; 026import org.apache.logging.log4j.simple.SimpleLoggerContextFactory; 027import org.apache.logging.log4j.spi.LoggerContext; 028import org.apache.logging.log4j.spi.LoggerContextFactory; 029import org.apache.logging.log4j.spi.Provider; 030import org.apache.logging.log4j.spi.Terminable; 031import org.apache.logging.log4j.status.StatusLogger; 032import org.apache.logging.log4j.util.LoaderUtil; 033import org.apache.logging.log4j.util.PropertiesUtil; 034import org.apache.logging.log4j.util.ProviderUtil; 035import org.apache.logging.log4j.util.StackLocatorUtil; 036import org.apache.logging.log4j.util.Strings; 037 038/** 039 * The anchor point for the Log4j logging system. The most common usage of this class is to obtain a named 040 * {@link Logger}. The method {@link #getLogger()} is provided as the most convenient way to obtain a named Logger based 041 * on the calling class name. This class also provides method for obtaining named Loggers that use 042 * {@link String#format(String, Object...)} style messages instead of the default type of parameterized messages. These 043 * are obtained through the {@link #getFormatterLogger(Class)} family of methods. Other service provider methods are 044 * given through the {@link #getContext()} and {@link #getFactory()} family of methods; these methods are not normally 045 * useful for typical usage of Log4j. 046 */ 047public class LogManager { 048 049 /** 050 * Log4j property to set to the fully qualified class name of a custom implementation of 051 * {@link org.apache.logging.log4j.spi.LoggerContextFactory}. 052 */ 053 public static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory"; 054 055 /** 056 * The name of the root Logger. 057 */ 058 public static final String ROOT_LOGGER_NAME = Strings.EMPTY; 059 060 private static final Logger LOGGER = StatusLogger.getLogger(); 061 062 // for convenience 063 private static final String FQCN = LogManager.class.getName(); 064 065 private static volatile LoggerContextFactory factory; 066 067 /** 068 * Scans the classpath to find all logging implementation. Currently, only one will be used but this could be 069 * extended to allow multiple implementations to be used. 070 */ 071 static { 072 // Shortcut binding to force a specific logging implementation. 073 final PropertiesUtil managerProps = PropertiesUtil.getProperties(); 074 final String factoryClassName = managerProps.getStringProperty(FACTORY_PROPERTY_NAME); 075 if (factoryClassName != null) { 076 try { 077 factory = LoaderUtil.newCheckedInstanceOf(factoryClassName, LoggerContextFactory.class); 078 } catch (final ClassNotFoundException cnfe) { 079 LOGGER.error("Unable to locate configured LoggerContextFactory {}", factoryClassName); 080 } catch (final Exception ex) { 081 LOGGER.error("Unable to create configured LoggerContextFactory {}", factoryClassName, ex); 082 } 083 } 084 085 if (factory == null) { 086 final SortedMap<Integer, LoggerContextFactory> factories = new TreeMap<>(); 087 // note that the following initial call to ProviderUtil may block until a Provider has been installed when 088 // running in an OSGi environment 089 if (ProviderUtil.hasProviders()) { 090 for (final Provider provider : ProviderUtil.getProviders()) { 091 final Class<? extends LoggerContextFactory> factoryClass = provider.loadLoggerContextFactory(); 092 if (factoryClass != null) { 093 try { 094 factories.put(provider.getPriority(), factoryClass.newInstance()); 095 } catch (final Exception e) { 096 LOGGER.error("Unable to create class {} specified in provider URL {}", factoryClass.getName(), provider 097 .getUrl(), e); 098 } 099 } 100 } 101 102 if (factories.isEmpty()) { 103 LOGGER.error("Log4j2 could not find a logging implementation. " 104 + "Please add log4j-core to the classpath. Using SimpleLogger to log to the console..."); 105 factory = new SimpleLoggerContextFactory(); 106 } else if (factories.size() == 1) { 107 factory = factories.get(factories.lastKey()); 108 } else { 109 final StringBuilder sb = new StringBuilder("Multiple logging implementations found: \n"); 110 for (final Map.Entry<Integer, LoggerContextFactory> entry : factories.entrySet()) { 111 sb.append("Factory: ").append(entry.getValue().getClass().getName()); 112 sb.append(", Weighting: ").append(entry.getKey()).append('\n'); 113 } 114 factory = factories.get(factories.lastKey()); 115 sb.append("Using factory: ").append(factory.getClass().getName()); 116 LOGGER.warn(sb.toString()); 117 118 } 119 } else { 120 LOGGER.error("Log4j2 could not find a logging implementation. " 121 + "Please add log4j-core to the classpath. Using SimpleLogger to log to the console..."); 122 factory = new SimpleLoggerContextFactory(); 123 } 124 } 125 } 126 127 /** 128 * Prevents instantiation 129 */ 130 protected LogManager() { 131 } 132 133 /** 134 * Detects if a Logger with the specified name exists. This is a convenience method for porting from version 1. 135 * 136 * @param name The Logger name to search for. 137 * @return true if the Logger exists, false otherwise. 138 * @see LoggerContext#hasLogger(String) 139 */ 140 public static boolean exists(final String name) { 141 return getContext().hasLogger(name); 142 } 143 144 /** 145 * Returns the current LoggerContext. 146 * <p> 147 * WARNING - The LoggerContext returned by this method may not be the LoggerContext used to create a Logger for the 148 * calling class. 149 * </p> 150 * 151 * @return The current LoggerContext. 152 */ 153 public static LoggerContext getContext() { 154 try { 155 return factory.getContext(FQCN, null, null, true); 156 } catch (final IllegalStateException ex) { 157 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 158 return new SimpleLoggerContextFactory().getContext(FQCN, null, null, true); 159 } 160 } 161 162 /** 163 * Returns a LoggerContext. 164 * 165 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 166 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 167 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 168 * be returned. If true then only a single LoggerContext will be returned. 169 * @return a LoggerContext. 170 */ 171 public static LoggerContext getContext(final boolean currentContext) { 172 // TODO: would it be a terrible idea to try and find the caller ClassLoader here? 173 try { 174 return factory.getContext(FQCN, null, null, currentContext, null, null); 175 } catch (final IllegalStateException ex) { 176 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 177 return new SimpleLoggerContextFactory().getContext(FQCN, null, null, currentContext, null, null); 178 } 179 } 180 181 /** 182 * Returns a LoggerContext. 183 * 184 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 185 * ClassLoader. 186 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 187 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 188 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 189 * be returned. If true then only a single LoggerContext will be returned. 190 * @return a LoggerContext. 191 */ 192 public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext) { 193 try { 194 return factory.getContext(FQCN, loader, null, currentContext); 195 } catch (final IllegalStateException ex) { 196 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 197 return new SimpleLoggerContextFactory().getContext(FQCN, loader, null, currentContext); 198 } 199 } 200 201 /** 202 * Returns a LoggerContext. 203 * 204 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 205 * ClassLoader. 206 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 207 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 208 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 209 * be returned. If true then only a single LoggerContext will be returned. 210 * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext. 211 * @return a LoggerContext. 212 */ 213 public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext, 214 final Object externalContext) { 215 try { 216 return factory.getContext(FQCN, loader, externalContext, currentContext); 217 } catch (final IllegalStateException ex) { 218 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 219 return new SimpleLoggerContextFactory().getContext(FQCN, loader, externalContext, currentContext); 220 } 221 } 222 223 /** 224 * Returns a LoggerContext. 225 * 226 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 227 * ClassLoader. 228 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 229 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 230 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 231 * be returned. If true then only a single LoggerContext will be returned. 232 * @param configLocation The URI for the configuration to use. 233 * @return a LoggerContext. 234 */ 235 public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext, 236 final URI configLocation) { 237 try { 238 return factory.getContext(FQCN, loader, null, currentContext, configLocation, null); 239 } catch (final IllegalStateException ex) { 240 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 241 return new SimpleLoggerContextFactory().getContext(FQCN, loader, null, currentContext, configLocation, 242 null); 243 } 244 } 245 246 /** 247 * Returns a LoggerContext. 248 * 249 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 250 * ClassLoader. 251 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 252 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 253 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 254 * be returned. If true then only a single LoggerContext will be returned. 255 * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext. 256 * @param configLocation The URI for the configuration to use. 257 * @return a LoggerContext. 258 */ 259 public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext, 260 final Object externalContext, final URI configLocation) { 261 try { 262 return factory.getContext(FQCN, loader, externalContext, currentContext, configLocation, null); 263 } catch (final IllegalStateException ex) { 264 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 265 return new SimpleLoggerContextFactory().getContext(FQCN, loader, externalContext, currentContext, 266 configLocation, null); 267 } 268 } 269 270 /** 271 * Returns a LoggerContext. 272 * 273 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 274 * ClassLoader. 275 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 276 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 277 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 278 * be returned. If true then only a single LoggerContext will be returned. 279 * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext. 280 * @param configLocation The URI for the configuration to use. 281 * @param name The LoggerContext name. 282 * @return a LoggerContext. 283 */ 284 public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext, 285 final Object externalContext, final URI configLocation, final String name) { 286 try { 287 return factory.getContext(FQCN, loader, externalContext, currentContext, configLocation, name); 288 } catch (final IllegalStateException ex) { 289 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 290 return new SimpleLoggerContextFactory().getContext(FQCN, loader, externalContext, currentContext, 291 configLocation, name); 292 } 293 } 294 295 /** 296 * Returns a LoggerContext 297 * 298 * @param fqcn The fully qualified class name of the Class that this method is a member of. 299 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 300 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 301 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 302 * be returned. If true then only a single LoggerContext will be returned. 303 * @return a LoggerContext. 304 */ 305 protected static LoggerContext getContext(final String fqcn, final boolean currentContext) { 306 try { 307 return factory.getContext(fqcn, null, null, currentContext); 308 } catch (final IllegalStateException ex) { 309 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 310 return new SimpleLoggerContextFactory().getContext(fqcn, null, null, currentContext); 311 } 312 } 313 314 /** 315 * Returns a LoggerContext 316 * 317 * @param fqcn The fully qualified class name of the Class that this method is a member of. 318 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 319 * ClassLoader. 320 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 321 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 322 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 323 * be returned. If true then only a single LoggerContext will be returned. 324 * @return a LoggerContext. 325 */ 326 protected static LoggerContext getContext(final String fqcn, final ClassLoader loader, 327 final boolean currentContext) { 328 try { 329 return factory.getContext(fqcn, loader, null, currentContext); 330 } catch (final IllegalStateException ex) { 331 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 332 return new SimpleLoggerContextFactory().getContext(fqcn, loader, null, currentContext); 333 } 334 } 335 336 337 /** 338 * Returns a LoggerContext 339 * 340 * @param fqcn The fully qualified class name of the Class that this method is a member of. 341 * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate 342 * ClassLoader. 343 * @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For 344 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 345 * returned and if the caller is a class in the container's classpath then a different LoggerContext may 346 * be returned. If true then only a single LoggerContext will be returned. 347 * @param configLocation The URI for the configuration to use. 348 * @param name The LoggerContext name. 349 * @return a LoggerContext. 350 */ 351 protected static LoggerContext getContext(final String fqcn, final ClassLoader loader, 352 final boolean currentContext, final URI configLocation, final String name) { 353 try { 354 return factory.getContext(fqcn, loader, null, currentContext, configLocation, name); 355 } catch (final IllegalStateException ex) { 356 LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); 357 return new SimpleLoggerContextFactory().getContext(fqcn, loader, null, currentContext); 358 } 359 } 360 361 /** 362 * Shutdown using the LoggerContext appropriate for the caller of this method. 363 * This is equivalent to calling {@code LogManager.shutdown(false)}. 364 * 365 * This call is synchronous and will block until shut down is complete. 366 * This may include flushing pending log events over network connections. 367 * 368 * @since 2.6 369 */ 370 public static void shutdown() { 371 shutdown(false); 372 } 373 374 /** 375 * Shutdown the logging system if the logging system supports it. 376 * This is equivalent to calling {@code LogManager.shutdown(LogManager.getContext(currentContext))}. 377 * 378 * This call is synchronous and will block until shut down is complete. 379 * This may include flushing pending log events over network connections. 380 * 381 * @param currentContext if true a default LoggerContext (may not be the LoggerContext used to create a Logger 382 * for the calling class) will be used. 383 * If false the LoggerContext appropriate for the caller of this method is used. For 384 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 385 * used and if the caller is a class in the container's classpath then a different LoggerContext may 386 * be used. 387 * @since 2.6 388 */ 389 public static void shutdown(final boolean currentContext) { 390 shutdown(getContext(currentContext)); 391 } 392 393 /** 394 * Shutdown the logging system if the logging system supports it. 395 * 396 * This call is synchronous and will block until shut down is complete. 397 * This may include flushing pending log events over network connections. 398 * 399 * @param context the LoggerContext. 400 * @since 2.6 401 */ 402 public static void shutdown(final LoggerContext context) { 403 if (context != null && context instanceof Terminable) { 404 ((Terminable) context).terminate(); 405 } 406 } 407 408 private static String toLoggerName(final Class<?> cls) { 409 final String canonicalName = cls.getCanonicalName(); 410 return canonicalName != null ? canonicalName : cls.getName(); 411 } 412 413 /** 414 * Returns the current LoggerContextFactory. 415 * 416 * @return The LoggerContextFactory. 417 */ 418 public static LoggerContextFactory getFactory() { 419 return factory; 420 } 421 422 /** 423 * Sets the current LoggerContextFactory to use. Normally, the appropriate LoggerContextFactory is created at 424 * startup, but in certain environments, a LoggerContextFactory implementation may not be available at this point. 425 * Thus, an alternative LoggerContextFactory can be set at runtime. 426 * 427 * <p> 428 * Note that any Logger or LoggerContext objects already created will still be valid, but they will no longer be 429 * accessible through LogManager. Thus, <strong>it is a bad idea to use this method without a good reason</strong>! 430 * Generally, this method should be used only during startup before any code starts caching Logger objects. 431 * </p> 432 * 433 * @param factory the LoggerContextFactory to use. 434 */ 435 // FIXME: should we allow only one update of the factory? 436 public static void setFactory(final LoggerContextFactory factory) { 437 LogManager.factory = factory; 438 } 439 440 /** 441 * Returns a formatter Logger using the fully qualified name of the calling Class as the Logger name. 442 * <p> 443 * This logger lets you use a {@link java.util.Formatter} string in the message to format parameters. 444 * </p> 445 * 446 * @return The Logger for the calling class. 447 * @throws UnsupportedOperationException if the calling class cannot be determined. 448 * @since 2.4 449 */ 450 public static Logger getFormatterLogger() { 451 return getFormatterLogger(StackLocatorUtil.getCallerClass(2)); 452 } 453 454 /** 455 * Returns a formatter Logger using the fully qualified name of the Class as the Logger name. 456 * <p> 457 * This logger let you use a {@link java.util.Formatter} string in the message to format parameters. 458 * </p> 459 * <p> 460 * Short-hand for {@code getLogger(clazz, StringFormatterMessageFactory.INSTANCE)} 461 * </p> 462 * 463 * @param clazz The Class whose name should be used as the Logger name. 464 * @return The Logger, created with a {@link StringFormatterMessageFactory} 465 * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be 466 * determined. 467 * @see Logger#fatal(Marker, String, Object...) 468 * @see Logger#fatal(String, Object...) 469 * @see Logger#error(Marker, String, Object...) 470 * @see Logger#error(String, Object...) 471 * @see Logger#warn(Marker, String, Object...) 472 * @see Logger#warn(String, Object...) 473 * @see Logger#info(Marker, String, Object...) 474 * @see Logger#info(String, Object...) 475 * @see Logger#debug(Marker, String, Object...) 476 * @see Logger#debug(String, Object...) 477 * @see Logger#trace(Marker, String, Object...) 478 * @see Logger#trace(String, Object...) 479 * @see StringFormatterMessageFactory 480 */ 481 public static Logger getFormatterLogger(final Class<?> clazz) { 482 return getLogger(clazz != null ? clazz : StackLocatorUtil.getCallerClass(2), 483 StringFormatterMessageFactory.INSTANCE); 484 } 485 486 /** 487 * Returns a formatter Logger using the fully qualified name of the value's Class as the Logger name. 488 * <p> 489 * This logger let you use a {@link java.util.Formatter} string in the message to format parameters. 490 * </p> 491 * <p> 492 * Short-hand for {@code getLogger(value, StringFormatterMessageFactory.INSTANCE)} 493 * </p> 494 * 495 * @param value The value's whose class name should be used as the Logger name. 496 * @return The Logger, created with a {@link StringFormatterMessageFactory} 497 * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be 498 * determined. 499 * @see Logger#fatal(Marker, String, Object...) 500 * @see Logger#fatal(String, Object...) 501 * @see Logger#error(Marker, String, Object...) 502 * @see Logger#error(String, Object...) 503 * @see Logger#warn(Marker, String, Object...) 504 * @see Logger#warn(String, Object...) 505 * @see Logger#info(Marker, String, Object...) 506 * @see Logger#info(String, Object...) 507 * @see Logger#debug(Marker, String, Object...) 508 * @see Logger#debug(String, Object...) 509 * @see Logger#trace(Marker, String, Object...) 510 * @see Logger#trace(String, Object...) 511 * @see StringFormatterMessageFactory 512 */ 513 public static Logger getFormatterLogger(final Object value) { 514 return getLogger(value != null ? value.getClass() : StackLocatorUtil.getCallerClass(2), 515 StringFormatterMessageFactory.INSTANCE); 516 } 517 518 /** 519 * Returns a formatter Logger with the specified name. 520 * <p> 521 * This logger let you use a {@link java.util.Formatter} string in the message to format parameters. 522 * </p> 523 * <p> 524 * Short-hand for {@code getLogger(name, StringFormatterMessageFactory.INSTANCE)} 525 * </p> 526 * 527 * @param name The logger name. If null it will default to the name of the calling class. 528 * @return The Logger, created with a {@link StringFormatterMessageFactory} 529 * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined. 530 * @see Logger#fatal(Marker, String, Object...) 531 * @see Logger#fatal(String, Object...) 532 * @see Logger#error(Marker, String, Object...) 533 * @see Logger#error(String, Object...) 534 * @see Logger#warn(Marker, String, Object...) 535 * @see Logger#warn(String, Object...) 536 * @see Logger#info(Marker, String, Object...) 537 * @see Logger#info(String, Object...) 538 * @see Logger#debug(Marker, String, Object...) 539 * @see Logger#debug(String, Object...) 540 * @see Logger#trace(Marker, String, Object...) 541 * @see Logger#trace(String, Object...) 542 * @see StringFormatterMessageFactory 543 */ 544 public static Logger getFormatterLogger(final String name) { 545 return name == null ? getFormatterLogger(StackLocatorUtil.getCallerClass(2)) : getLogger(name, 546 StringFormatterMessageFactory.INSTANCE); 547 } 548 549 private static Class<?> callerClass(final Class<?> clazz) { 550 if (clazz != null) { 551 return clazz; 552 } 553 final Class<?> candidate = StackLocatorUtil.getCallerClass(3); 554 if (candidate == null) { 555 throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found."); 556 } 557 return candidate; 558 } 559 560 /** 561 * Returns a Logger with the name of the calling class. 562 * 563 * @return The Logger for the calling class. 564 * @throws UnsupportedOperationException if the calling class cannot be determined. 565 */ 566 public static Logger getLogger() { 567 return getLogger(StackLocatorUtil.getCallerClass(2)); 568 } 569 570 /** 571 * Returns a Logger using the fully qualified name of the Class as the Logger name. 572 * 573 * @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling 574 * class. 575 * @return The Logger. 576 * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be 577 * determined. 578 */ 579 public static Logger getLogger(final Class<?> clazz) { 580 final Class<?> cls = callerClass(clazz); 581 return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls)); 582 } 583 584 /** 585 * Returns a Logger using the fully qualified name of the Class as the Logger name. 586 * 587 * @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling 588 * class. 589 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 590 * logger but will log a warning if mismatched. 591 * @return The Logger. 592 * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be 593 * determined. 594 */ 595 public static Logger getLogger(final Class<?> clazz, final MessageFactory messageFactory) { 596 final Class<?> cls = callerClass(clazz); 597 return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls), messageFactory); 598 } 599 600 /** 601 * Returns a Logger with the name of the calling class. 602 * 603 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 604 * logger but will log a warning if mismatched. 605 * @return The Logger for the calling class. 606 * @throws UnsupportedOperationException if the calling class cannot be determined. 607 */ 608 public static Logger getLogger(final MessageFactory messageFactory) { 609 return getLogger(StackLocatorUtil.getCallerClass(2), messageFactory); 610 } 611 612 /** 613 * Returns a Logger using the fully qualified class name of the value as the Logger name. 614 * 615 * @param value The value whose class name should be used as the Logger name. If null the name of the calling class 616 * will be used as the logger name. 617 * @return The Logger. 618 * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be 619 * determined. 620 */ 621 public static Logger getLogger(final Object value) { 622 return getLogger(value != null ? value.getClass() : StackLocatorUtil.getCallerClass(2)); 623 } 624 625 /** 626 * Returns a Logger using the fully qualified class name of the value as the Logger name. 627 * 628 * @param value The value whose class name should be used as the Logger name. If null the name of the calling class 629 * will be used as the logger name. 630 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 631 * logger but will log a warning if mismatched. 632 * @return The Logger. 633 * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be 634 * determined. 635 */ 636 public static Logger getLogger(final Object value, final MessageFactory messageFactory) { 637 return getLogger(value != null ? value.getClass() : StackLocatorUtil.getCallerClass(2), messageFactory); 638 } 639 640 /** 641 * Returns a Logger with the specified name. 642 * 643 * @param name The logger name. If null the name of the calling class will be used. 644 * @return The Logger. 645 * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined. 646 */ 647 public static Logger getLogger(final String name) { 648 return name != null ? getContext(false).getLogger(name) : getLogger(StackLocatorUtil.getCallerClass(2)); 649 } 650 651 /** 652 * Returns a Logger with the specified name. 653 * 654 * @param name The logger name. If null the name of the calling class will be used. 655 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 656 * logger but will log a warning if mismatched. 657 * @return The Logger. 658 * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined. 659 */ 660 public static Logger getLogger(final String name, final MessageFactory messageFactory) { 661 return name != null ? getContext(false).getLogger(name, messageFactory) : getLogger( 662 StackLocatorUtil.getCallerClass(2), messageFactory); 663 } 664 665 /** 666 * Returns a Logger with the specified name. 667 * 668 * @param fqcn The fully qualified class name of the class that this method is a member of. 669 * @param name The logger name. 670 * @return The Logger. 671 */ 672 protected static Logger getLogger(final String fqcn, final String name) { 673 return factory.getContext(fqcn, null, null, false).getLogger(name); 674 } 675 676 /** 677 * Returns the root logger. 678 * 679 * @return the root logger, named {@link #ROOT_LOGGER_NAME}. 680 */ 681 public static Logger getRootLogger() { 682 return getLogger(ROOT_LOGGER_NAME); 683 } 684}