1 /*
2 * #%L
3 * Slf4jLogFactory.java - mongodb-async-driver - Allanbank Consulting, Inc.
4 * %%
5 * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6 * %%
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * #L%
19 */
20 package com.allanbank.mongodb.util.log;
21
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26
27 /**
28 * Slf4jLogFactory provides factory to create {@link Slf4jLog} instances.
29 *
30 * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
31 * mutated in incompatible ways between any two releases of the driver.
32 * @copyright 2014, Allanbank Consulting, Inc., All Rights Reserved
33 */
34 public class Slf4jLogFactory extends LogFactory {
35 /** The <code>LocationAwareLogger</code> class. */
36 private final Class<?> myLocationAwareLoggerClass;
37
38 /**
39 * The <code>getLogger(Class)</code> method from the
40 * <code>LoggerFactory</code> interface.
41 */
42 private final Method myLogFactoryMethod;
43
44 /**
45 * The <code>log(Marker, String, int, String, Object[])</code> method from
46 * the <code>LocationAwareLogger</code> interface.
47 */
48 private final Method myLogMethod;
49
50 /**
51 * Creates a new Slf4jLogFactory.
52 *
53 * @throws RuntimeException
54 * On a failure to find the SLF4J Logger.
55 */
56 public Slf4jLogFactory() throws RuntimeException {
57 Class<?> logFactoryClass;
58 try {
59 logFactoryClass = Class.forName("org.slf4j.LoggerFactory");
60 }
61 catch (final ClassNotFoundException e) {
62 // Don't log. SLF4J is not on the classpath to use.
63 throw new RuntimeException(e);
64 }
65
66 try {
67 myLogFactoryMethod = logFactoryClass.getMethod("getLogger",
68 Class.class);
69
70 myLocationAwareLoggerClass = Class
71 .forName("org.slf4j.spi.LocationAwareLogger");
72 final Class<?> markerClass = Class.forName("org.slf4j.Marker");
73 myLogMethod = myLocationAwareLoggerClass.getMethod("log",
74 markerClass, String.class, int.class, String.class,
75 Object[].class, Throwable.class);
76 }
77 catch (final ClassNotFoundException e) {
78 Logger.getLogger(Slf4jLogFactory.class.getName()).log(
79 Level.WARNING,
80 "Failed bootstrap the SLF4J logger: " + e.getMessage(), e);
81 throw new RuntimeException(e);
82 }
83 catch (final NoSuchMethodException e) {
84 Logger.getLogger(Slf4jLogFactory.class.getName()).log(
85 Level.WARNING,
86 "Failed bootstrap the SLF4J logger: " + e.getMessage(), e);
87 throw new RuntimeException(e);
88 }
89 }
90
91 /**
92 * {@inheritDoc}
93 * <p>
94 * Overridden to return a {@link Slf4jLog} instance if SLF4J LoggerFactory
95 * returns a LocationAwareLogger instance. Otherwise a {@link JulLog} is
96 * returned.
97 * </p>
98 */
99 @Override
100 protected Log doGetLog(final Class<?> clazz) {
101 Log log = null;
102 try {
103 final Object logger = myLogFactoryMethod.invoke(null, clazz);
104 if (myLocationAwareLoggerClass.isInstance(logger)) {
105 log = new Slf4jLog(myLogMethod, logger);
106 }
107 }
108 catch (final IllegalAccessException e) {
109 // Fall through.
110 }
111 catch (final InvocationTargetException e) {
112 // Fall through.
113 }
114 catch (final RuntimeException e) {
115 // Fall through.
116 }
117
118 // Fall back to JUL logging.
119 if (log == null) {
120 Logger.getLogger(Slf4jLogFactory.class.getName()).warning(
121 "Falling back to the JUL logger.");
122 log = new JulLog(clazz);
123 }
124
125 return log;
126 }
127 }