1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache license, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the license for the specific language governing permissions and 15 * limitations under the license. 16 */ 17 package org.apache.logging.log4j; 18 19 import java.net.URI; 20 import java.util.Map; 21 import java.util.SortedMap; 22 import java.util.TreeMap; 23 24 import org.apache.logging.log4j.message.MessageFactory; 25 import org.apache.logging.log4j.message.StringFormatterMessageFactory; 26 import org.apache.logging.log4j.simple.SimpleLoggerContextFactory; 27 import org.apache.logging.log4j.spi.LoggerContext; 28 import org.apache.logging.log4j.spi.LoggerContextFactory; 29 import org.apache.logging.log4j.spi.Provider; 30 import org.apache.logging.log4j.spi.Terminable; 31 import org.apache.logging.log4j.status.StatusLogger; 32 import org.apache.logging.log4j.util.LoaderUtil; 33 import org.apache.logging.log4j.util.PropertiesUtil; 34 import org.apache.logging.log4j.util.ProviderUtil; 35 import org.apache.logging.log4j.util.ReflectionUtil; 36 import org.apache.logging.log4j.util.Strings; 37 38 /** 39 * The anchor point for the logging system. The most common usage of this class is to obtain a named {@link Logger}. The 40 * method {@link #getLogger()} is provided as the most convenient way to obtain a named Logger based on the calling 41 * class name. This class also provides method for obtaining named Loggers that use 42 * {@link String#format(String, Object...)} style messages instead of the default type of parameterized messages. These 43 * are obtained through the {@link #getFormatterLogger(Class)} family of methods. Other service provider methods are 44 * given through the {@link #getContext()} and {@link #getFactory()} family of methods; these methods are not normally 45 * useful for typical usage of Log4j. 46 */ 47 public class LogManager { 48 49 /** 50 * Log4j property to set to the fully qualified class name of a custom implementation of 51 * {@link org.apache.logging.log4j.spi.LoggerContextFactory}. 52 */ 53 public static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory"; 54 55 /** 56 * The name of the root Logger. 57 */ 58 public static final String ROOT_LOGGER_NAME = Strings.EMPTY; 59 60 private static final Logger LOGGER = StatusLogger.getLogger(); 61 62 // for convenience 63 private static final String FQCN = LogManager.class.getName(); 64 65 private static volatile LoggerContextFactory factory; 66 67 /** 68 * Scans the classpath to find all logging implementation. Currently, only one will be used but this could be 69 * extended to allow multiple implementations to be used. 70 */ 71 static { 72 // Shortcut binding to force a specific logging implementation. 73 final PropertiesUtil managerProps = PropertiesUtil.getProperties(); 74 final String factoryClassName = managerProps.getStringProperty(FACTORY_PROPERTY_NAME); 75 if (factoryClassName != null) { 76 try { 77 factory = LoaderUtil.newCheckedInstanceOf(factoryClassName, LoggerContextFactory.class); 78 } catch (final ClassNotFoundException cnfe) { 79 LOGGER.error("Unable to locate configured LoggerContextFactory {}", factoryClassName); 80 } catch (final Exception ex) { 81 LOGGER.error("Unable to create configured LoggerContextFactory {}", factoryClassName, ex); 82 } 83 } 84 85 if (factory == null) { 86 final SortedMap<Integer, LoggerContextFactory> factories = new TreeMap<>(); 87 // note that the following initial call to ProviderUtil may block until a Provider has been installed when 88 // running in an OSGi environment 89 if (ProviderUtil.hasProviders()) { 90 for (final Provider provider : ProviderUtil.getProviders()) { 91 final Class<? extends LoggerContextFactory> factoryClass = provider.loadLoggerContextFactory(); 92 if (factoryClass != null) { 93 try { 94 factories.put(provider.getPriority(), factoryClass.newInstance()); 95 } catch (final Exception e) { 96 LOGGER.error("Unable to create class {} specified in {}", factoryClass.getName(), provider 97 .getUrl().toString(), e); 98 } 99 } 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 * Shutdown using the LoggerContext appropriate for the caller of this method. 338 * This is equivalent to calling {@code LogManager.shutdown(false)}. 339 * 340 * This call is synchronous and will block until shut down is complete. 341 * This may include flushing pending log events over network connections. 342 * 343 * @since 2.6 344 */ 345 public static void shutdown() { 346 shutdown(false); 347 } 348 349 /** 350 * Shutdown the logging system if the logging system supports it. 351 * This is equivalent to calling {@code LogManager.shutdown(LogManager.getContext(currentContext))}. 352 * 353 * This call is synchronous and will block until shut down is complete. 354 * This may include flushing pending log events over network connections. 355 * 356 * @param currentContext if true a default LoggerContext (may not be the LoggerContext used to create a Logger 357 * for the calling class) will be used. 358 * If false the LoggerContext appropriate for the caller of this method is used. For 359 * example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be 360 * used and if the caller is a class in the container's classpath then a different LoggerContext may 361 * be used. 362 * @since 2.6 363 */ 364 public static void shutdown(final boolean currentContext) { 365 shutdown(getContext(currentContext)); 366 } 367 368 /** 369 * Shutdown the logging system if the logging system supports it. 370 * 371 * This call is synchronous and will block until shut down is complete. 372 * This may include flushing pending log events over network connections. 373 * 374 * @param context the LoggerContext. 375 * @since 2.6 376 */ 377 public static void shutdown(final LoggerContext context) { 378 if (context != null && context instanceof Terminable) { 379 ((Terminable) context).terminate(); 380 } 381 } 382 383 /** 384 * Returns the current LoggerContextFactory. 385 * 386 * @return The LoggerContextFactory. 387 */ 388 public static LoggerContextFactory getFactory() { 389 return factory; 390 } 391 392 /** 393 * Sets the current LoggerContextFactory to use. Normally, the appropriate LoggerContextFactory is created at 394 * startup, but in certain environments, a LoggerContextFactory implementation may not be available at this point. 395 * Thus, an alternative LoggerContextFactory can be set at runtime. 396 * 397 * <p> 398 * Note that any Logger or LoggerContext objects already created will still be valid, but they will no longer be 399 * accessible through LogManager. Thus, <strong>it is a bad idea to use this method without a good reason</strong>! 400 * Generally, this method should be used only during startup before any code starts caching Logger objects. 401 * </p> 402 * 403 * @param factory the LoggerContextFactory to use. 404 */ 405 // FIXME: should we allow only one update of the factory? 406 public static void setFactory(final LoggerContextFactory factory) { 407 LogManager.factory = factory; 408 } 409 410 /** 411 * Returns a formatter Logger using the fully qualified name of the calling Class as the Logger name. 412 * <p> 413 * This logger lets you use a {@link java.util.Formatter} string in the message to format parameters. 414 * </p> 415 * 416 * @return The Logger for the calling class. 417 * @throws UnsupportedOperationException if the calling class cannot be determined. 418 * @since 2.4 419 */ 420 public static Logger getFormatterLogger() { 421 return getFormatterLogger(ReflectionUtil.getCallerClass(2)); 422 } 423 424 /** 425 * Returns a formatter Logger using the fully qualified name of the Class as the Logger name. 426 * <p> 427 * This logger let you use a {@link java.util.Formatter} string in the message to format parameters. 428 * </p> 429 * <p> 430 * Short-hand for {@code getLogger(clazz, StringFormatterMessageFactory.INSTANCE)} 431 * </p> 432 * 433 * @param clazz The Class whose name should be used as the Logger name. 434 * @return The Logger, created with a {@link StringFormatterMessageFactory} 435 * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be 436 * determined. 437 * @see Logger#fatal(Marker, String, Object...) 438 * @see Logger#fatal(String, Object...) 439 * @see Logger#error(Marker, String, Object...) 440 * @see Logger#error(String, Object...) 441 * @see Logger#warn(Marker, String, Object...) 442 * @see Logger#warn(String, Object...) 443 * @see Logger#info(Marker, String, Object...) 444 * @see Logger#info(String, Object...) 445 * @see Logger#debug(Marker, String, Object...) 446 * @see Logger#debug(String, Object...) 447 * @see Logger#trace(Marker, String, Object...) 448 * @see Logger#trace(String, Object...) 449 * @see StringFormatterMessageFactory 450 */ 451 public static Logger getFormatterLogger(final Class<?> clazz) { 452 return getLogger(clazz != null ? clazz : ReflectionUtil.getCallerClass(2), 453 StringFormatterMessageFactory.INSTANCE); 454 } 455 456 /** 457 * Returns a formatter Logger using the fully qualified name of the value's Class as the Logger name. 458 * <p> 459 * This logger let you use a {@link java.util.Formatter} string in the message to format parameters. 460 * </p> 461 * <p> 462 * Short-hand for {@code getLogger(value, StringFormatterMessageFactory.INSTANCE)} 463 * </p> 464 * 465 * @param value The value's whose class name should be used as the Logger name. 466 * @return The Logger, created with a {@link StringFormatterMessageFactory} 467 * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be 468 * determined. 469 * @see Logger#fatal(Marker, String, Object...) 470 * @see Logger#fatal(String, Object...) 471 * @see Logger#error(Marker, String, Object...) 472 * @see Logger#error(String, Object...) 473 * @see Logger#warn(Marker, String, Object...) 474 * @see Logger#warn(String, Object...) 475 * @see Logger#info(Marker, String, Object...) 476 * @see Logger#info(String, Object...) 477 * @see Logger#debug(Marker, String, Object...) 478 * @see Logger#debug(String, Object...) 479 * @see Logger#trace(Marker, String, Object...) 480 * @see Logger#trace(String, Object...) 481 * @see StringFormatterMessageFactory 482 */ 483 public static Logger getFormatterLogger(final Object value) { 484 return getLogger(value != null ? value.getClass() : ReflectionUtil.getCallerClass(2), 485 StringFormatterMessageFactory.INSTANCE); 486 } 487 488 /** 489 * Returns a formatter Logger with the specified name. 490 * <p> 491 * This logger let you use a {@link java.util.Formatter} string in the message to format parameters. 492 * </p> 493 * <p> 494 * Short-hand for {@code getLogger(name, StringFormatterMessageFactory.INSTANCE)} 495 * </p> 496 * 497 * @param name The logger name. If null it will default to the name of the calling class. 498 * @return The Logger, created with a {@link StringFormatterMessageFactory} 499 * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined. 500 * @see Logger#fatal(Marker, String, Object...) 501 * @see Logger#fatal(String, Object...) 502 * @see Logger#error(Marker, String, Object...) 503 * @see Logger#error(String, Object...) 504 * @see Logger#warn(Marker, String, Object...) 505 * @see Logger#warn(String, Object...) 506 * @see Logger#info(Marker, String, Object...) 507 * @see Logger#info(String, Object...) 508 * @see Logger#debug(Marker, String, Object...) 509 * @see Logger#debug(String, Object...) 510 * @see Logger#trace(Marker, String, Object...) 511 * @see Logger#trace(String, Object...) 512 * @see StringFormatterMessageFactory 513 */ 514 public static Logger getFormatterLogger(final String name) { 515 return name == null ? getFormatterLogger(ReflectionUtil.getCallerClass(2)) : getLogger(name, 516 StringFormatterMessageFactory.INSTANCE); 517 } 518 519 private static Class<?> callerClass(final Class<?> clazz) { 520 if (clazz != null) { 521 return clazz; 522 } 523 final Class<?> candidate = ReflectionUtil.getCallerClass(3); 524 if (candidate == null) { 525 throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found."); 526 } 527 return candidate; 528 } 529 530 /** 531 * Returns a Logger with the name of the calling class. 532 * 533 * @return The Logger for the calling class. 534 * @throws UnsupportedOperationException if the calling class cannot be determined. 535 */ 536 public static Logger getLogger() { 537 return getLogger(ReflectionUtil.getCallerClass(2)); 538 } 539 540 /** 541 * Returns a Logger using the fully qualified name of the Class as the Logger name. 542 * 543 * @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling 544 * class. 545 * @return The Logger. 546 * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be 547 * determined. 548 */ 549 public static Logger getLogger(final Class<?> clazz) { 550 final Class<?> cls = callerClass(clazz); 551 return getContext(cls.getClassLoader(), false).getLogger(cls.getName()); 552 } 553 554 /** 555 * Returns a Logger using the fully qualified name of the Class as the Logger name. 556 * 557 * @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling 558 * class. 559 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 560 * logger but will log a warning if mismatched. 561 * @return The Logger. 562 * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be 563 * determined. 564 */ 565 public static Logger getLogger(final Class<?> clazz, final MessageFactory messageFactory) { 566 final Class<?> cls = callerClass(clazz); 567 return getContext(cls.getClassLoader(), false).getLogger(cls.getName(), messageFactory); 568 } 569 570 /** 571 * Returns a Logger with the name of the calling class. 572 * 573 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 574 * logger but will log a warning if mismatched. 575 * @return The Logger for the calling class. 576 * @throws UnsupportedOperationException if the calling class cannot be determined. 577 */ 578 public static Logger getLogger(final MessageFactory messageFactory) { 579 return getLogger(ReflectionUtil.getCallerClass(2), messageFactory); 580 } 581 582 /** 583 * Returns a Logger using the fully qualified class name of the value as the Logger name. 584 * 585 * @param value The value whose class name should be used as the Logger name. If null the name of the calling class 586 * will be used as the logger name. 587 * @return The Logger. 588 * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be 589 * determined. 590 */ 591 public static Logger getLogger(final Object value) { 592 return getLogger(value != null ? value.getClass() : ReflectionUtil.getCallerClass(2)); 593 } 594 595 /** 596 * Returns a Logger using the fully qualified class name of the value as the Logger name. 597 * 598 * @param value The value whose class name should be used as the Logger name. If null the name of the calling class 599 * will be used as the logger name. 600 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 601 * logger but will log a warning if mismatched. 602 * @return The Logger. 603 * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be 604 * determined. 605 */ 606 public static Logger getLogger(final Object value, final MessageFactory messageFactory) { 607 return getLogger(value != null ? value.getClass() : ReflectionUtil.getCallerClass(2), messageFactory); 608 } 609 610 /** 611 * Returns a Logger with the specified name. 612 * 613 * @param name The logger name. If null the name of the calling class will be used. 614 * @return The Logger. 615 * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined. 616 */ 617 public static Logger getLogger(final String name) { 618 return name != null ? getContext(false).getLogger(name) : getLogger(ReflectionUtil.getCallerClass(2)); 619 } 620 621 /** 622 * Returns a Logger with the specified name. 623 * 624 * @param name The logger name. If null the name of the calling class will be used. 625 * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the 626 * logger but will log a warning if mismatched. 627 * @return The Logger. 628 * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined. 629 */ 630 public static Logger getLogger(final String name, final MessageFactory messageFactory) { 631 return name != null ? getContext(false).getLogger(name, messageFactory) : getLogger( 632 ReflectionUtil.getCallerClass(2), messageFactory); 633 } 634 635 /** 636 * Returns a Logger with the specified name. 637 * 638 * @param fqcn The fully qualified class name of the class that this method is a member of. 639 * @param name The logger name. 640 * @return The Logger. 641 */ 642 protected static Logger getLogger(final String fqcn, final String name) { 643 return factory.getContext(fqcn, null, null, false).getLogger(name); 644 } 645 646 /** 647 * Returns the root logger. 648 * 649 * @return the root logger, named {@link #ROOT_LOGGER_NAME}. 650 */ 651 public static Logger getRootLogger() { 652 return getLogger(ROOT_LOGGER_NAME); 653 } 654 }