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.StackLocatorUtil;
36 import org.apache.logging.log4j.util.Strings;
37
38 /**
39 * The anchor point for the Log4j logging system. The most common usage of this class is to obtain a named
40 * {@link Logger}. The method {@link #getLogger()} is provided as the most convenient way to obtain a named Logger based
41 * on the calling 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 provider URL {}", factoryClass.getName(), provider
97 .getUrl(), 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 /**
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 }