View Javadoc
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.commons.logging.impl;
18  
19  import static org.slf4j.spi.LocationAwareLogger.DEBUG_INT;
20  import static org.slf4j.spi.LocationAwareLogger.ERROR_INT;
21  import static org.slf4j.spi.LocationAwareLogger.INFO_INT;
22  import static org.slf4j.spi.LocationAwareLogger.TRACE_INT;
23  import static org.slf4j.spi.LocationAwareLogger.WARN_INT;
24  
25  import java.util.concurrent.ConcurrentHashMap;
26  import java.util.concurrent.ConcurrentMap;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogConfigurationException;
30  import org.apache.commons.logging.LogFactory;
31  import org.slf4j.ILoggerFactory;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  import org.slf4j.Marker;
35  import org.slf4j.MarkerFactory;
36  import org.slf4j.spi.LocationAwareLogger;
37  
38  /**
39   * Logger factory hardcoded to send everything to SLF4J.
40   *
41   * @since 1.3.0
42   */
43  public final class Slf4jLogFactory extends LogFactory {
44  
45      private static final class Slf4jLocationAwareLog implements Log {
46  
47          private static final String FQCN = Slf4jLocationAwareLog.class.getName();
48  
49          private final LocationAwareLogger logger;
50  
51          public Slf4jLocationAwareLog(final LocationAwareLogger logger) {
52              this.logger = logger;
53          }
54  
55          @Override
56          public void debug(final Object message) {
57              log(DEBUG_INT, message, null);
58          }
59  
60          @Override
61          public void debug(final Object message, final Throwable t) {
62              log(DEBUG_INT, message, t);
63          }
64  
65          @Override
66          public void error(final Object message) {
67              log(ERROR_INT, message, null);
68          }
69  
70          @Override
71          public void error(final Object message, final Throwable t) {
72              log(ERROR_INT, message, t);
73          }
74  
75          @Override
76          public void fatal(final Object message) {
77              error(message);
78          }
79  
80          @Override
81          public void fatal(final Object message, final Throwable t) {
82              error(message, t);
83          }
84  
85          @Override
86          public void info(final Object message) {
87              log(INFO_INT, message, null);
88          }
89  
90          @Override
91          public void info(final Object message, final Throwable t) {
92              log(INFO_INT, message, t);
93          }
94  
95          @Override
96          public boolean isDebugEnabled() {
97              return logger.isDebugEnabled(MARKER);
98          }
99  
100         @Override
101         public boolean isErrorEnabled() {
102             return logger.isErrorEnabled(MARKER);
103         }
104 
105         @Override
106         public boolean isFatalEnabled() {
107             return isErrorEnabled();
108         }
109 
110         @Override
111         public boolean isInfoEnabled() {
112             return logger.isInfoEnabled(MARKER);
113         }
114 
115         @Override
116         public boolean isTraceEnabled() {
117             return logger.isTraceEnabled(MARKER);
118         }
119 
120         @Override
121         public boolean isWarnEnabled() {
122             return logger.isWarnEnabled(MARKER);
123         }
124 
125         private void log(final int level, final Object message, final Throwable t) {
126             logger.log(MARKER, FQCN, level, String.valueOf(message), EMPTY_OBJECT_ARRAY, t);
127         }
128 
129         @Override
130         public void trace(final Object message) {
131             log(TRACE_INT, message, null);
132         }
133 
134         @Override
135         public void trace(final Object message, final Throwable t) {
136             log(TRACE_INT, message, t);
137         }
138 
139         @Override
140         public void warn(final Object message) {
141             log(WARN_INT, message, null);
142         }
143 
144         @Override
145         public void warn(final Object message, final Throwable t) {
146             log(WARN_INT, message, t);
147         }
148     }
149     private static class Slf4jLog implements Log {
150 
151         private final Logger logger;
152 
153         public Slf4jLog(final Logger logger) {
154             this.logger = logger;
155         }
156 
157         @Override
158         public void debug(final Object message) {
159             logger.debug(MARKER, String.valueOf(message));
160         }
161 
162         @Override
163         public void debug(final Object message, final Throwable t) {
164             logger.debug(MARKER, String.valueOf(message), t);
165         }
166 
167         @Override
168         public void error(final Object message) {
169             logger.error(MARKER, String.valueOf(message));
170         }
171 
172         @Override
173         public void error(final Object message, final Throwable t) {
174             logger.debug(MARKER, String.valueOf(message), t);
175         }
176 
177         @Override
178         public void fatal(final Object message) {
179             error(message);
180         }
181 
182         @Override
183         public void fatal(final Object message, final Throwable t) {
184             error(message, t);
185         }
186 
187         @Override
188         public void info(final Object message) {
189             logger.info(MARKER, String.valueOf(message));
190         }
191 
192         @Override
193         public void info(final Object message, final Throwable t) {
194             logger.info(MARKER, String.valueOf(message), t);
195         }
196 
197         @Override
198         public boolean isDebugEnabled() {
199             return logger.isDebugEnabled(MARKER);
200         }
201 
202         @Override
203         public boolean isErrorEnabled() {
204             return logger.isErrorEnabled(MARKER);
205         }
206 
207         @Override
208         public boolean isFatalEnabled() {
209             return isErrorEnabled();
210         }
211 
212         @Override
213         public boolean isInfoEnabled() {
214             return logger.isInfoEnabled(MARKER);
215         }
216 
217         @Override
218         public boolean isTraceEnabled() {
219             return logger.isTraceEnabled(MARKER);
220         }
221 
222         @Override
223         public boolean isWarnEnabled() {
224             return logger.isWarnEnabled(MARKER);
225         }
226 
227         @Override
228         public void trace(final Object message) {
229             logger.trace(MARKER, String.valueOf(message));
230         }
231 
232         @Override
233         public void trace(final Object message, final Throwable t) {
234             logger.trace(MARKER, String.valueOf(message), t);
235         }
236 
237         @Override
238         public void warn(final Object message) {
239             logger.warn(MARKER, String.valueOf(message));
240         }
241 
242         @Override
243         public void warn(final Object message, final Throwable t) {
244             logger.warn(MARKER, String.valueOf(message), t);
245         }
246     }
247 
248     private static final Object[] EMPTY_OBJECT_ARRAY = {};
249 
250     private static final String[] EMPTY_STRING_ARRAY = {};
251 
252     /**
253      * Marker used by all messages coming from Apache Commons Logging.
254      */
255     private static final Marker MARKER = MarkerFactory.getMarker("COMMONS-LOGGING");
256 
257     /**
258      * Caches Log instances.
259      * <p>
260      * The SLF4J reference implementation (Logback) has a single logger context, so each call to
261      * {@link #getInstance(String)}
262      * should give the same result.
263      * </p>
264      */
265     private final ConcurrentMap<String, Log> loggers = new ConcurrentHashMap<>();
266 
267     private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
268 
269     /**
270      * Constructs a new instance.
271      */
272     public Slf4jLogFactory() {
273         // empty
274     }
275 
276     @Override
277     public Object getAttribute(final String name) {
278         return attributes.get(name);
279     }
280 
281     @Override
282     public String[] getAttributeNames() {
283         return attributes.keySet().toArray(EMPTY_STRING_ARRAY);
284     }
285 
286     @Override
287     public Log getInstance(final Class<?> clazz) throws LogConfigurationException {
288         return getInstance(clazz.getName());
289     }
290 
291     @Override
292     public Log getInstance(final String name) {
293         return loggers.computeIfAbsent(name, n -> {
294             final Logger logger = LoggerFactory.getLogger(n);
295             return logger instanceof LocationAwareLogger ? new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog(
296                     logger);
297         });
298     }
299 
300     /**
301      * This method is supposed to clear all loggers.
302      * <p>
303      * In this implementation it calls a "stop" method if the logger factory supports it. This is the case of
304      * Logback.
305      * </p>
306      */
307     @Override
308     public void release() {
309         final ILoggerFactory factory = LoggerFactory.getILoggerFactory();
310         try {
311             factory.getClass().getMethod("stop").invoke(factory);
312         } catch (final ReflectiveOperationException ignored) {
313             // empty
314         }
315     }
316 
317     @Override
318     public void removeAttribute(final String name) {
319         attributes.remove(name);
320     }
321 
322     @Override
323     public void setAttribute(final String name, final Object value) {
324         if (value != null) {
325             attributes.put(name, value);
326         } else {
327             removeAttribute(name);
328         }
329     }
330 }