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 java.io.IOException;
20  import java.util.concurrent.ConcurrentHashMap;
21  import java.util.concurrent.ConcurrentMap;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.logging.log4j.Level;
26  import org.apache.logging.log4j.LogManager;
27  import org.apache.logging.log4j.Marker;
28  import org.apache.logging.log4j.MarkerManager;
29  import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
30  import org.apache.logging.log4j.spi.ExtendedLogger;
31  import org.apache.logging.log4j.spi.LoggerAdapter;
32  import org.apache.logging.log4j.spi.LoggerContext;
33  import org.apache.logging.log4j.util.StackLocatorUtil;
34  
35  /**
36   * Logger factory hardcoded to send everything to Log4j API.
37   * <p>
38   * Based on the `log4j-jcl` artifact from Apache Logging Services.
39   * </p>
40   *
41   * @since 1.3.0
42   */
43  public final class Log4jApiLogFactory extends LogFactory {
44  
45      private static final class Log4j2Log implements Log {
46  
47          private static final String FQCN = Log4j2Log.class.getName();
48  
49          private final ExtendedLogger logger;
50  
51          public Log4j2Log(final ExtendedLogger logger) {
52              this.logger = logger;
53          }
54  
55          @Override
56          public void debug(final Object message) {
57              logIfEnabled(Level.DEBUG, message, null);
58          }
59  
60          @Override
61          public void debug(final Object message, final Throwable t) {
62              logIfEnabled(Level.DEBUG, message, t);
63          }
64  
65          @Override
66          public void error(final Object message) {
67              logIfEnabled(Level.ERROR, message, null);
68          }
69  
70          @Override
71          public void error(final Object message, final Throwable t) {
72              logIfEnabled(Level.ERROR, message, t);
73          }
74  
75          @Override
76          public void fatal(final Object message) {
77              logIfEnabled(Level.FATAL, message, null);
78          }
79  
80          @Override
81          public void fatal(final Object message, final Throwable t) {
82              logIfEnabled(Level.FATAL, message, t);
83          }
84  
85          @Override
86          public void info(final Object message) {
87              logIfEnabled(Level.INFO, message, null);
88          }
89  
90          @Override
91          public void info(final Object message, final Throwable t) {
92              logIfEnabled(Level.INFO, message, t);
93          }
94  
95          @Override
96          public boolean isDebugEnabled() {
97              return isEnabled(Level.DEBUG);
98          }
99  
100         private boolean isEnabled(final Level level) {
101             return logger.isEnabled(level, MARKER, null);
102         }
103 
104         @Override
105         public boolean isErrorEnabled() {
106             return isEnabled(Level.ERROR);
107         }
108 
109         @Override
110         public boolean isFatalEnabled() {
111             return isEnabled(Level.FATAL);
112         }
113 
114         @Override
115         public boolean isInfoEnabled() {
116             return isEnabled(Level.INFO);
117         }
118 
119         @Override
120         public boolean isTraceEnabled() {
121             return isEnabled(Level.TRACE);
122         }
123 
124         @Override
125         public boolean isWarnEnabled() {
126             return isEnabled(Level.WARN);
127         }
128 
129         private void logIfEnabled(final Level level, final Object message, final Throwable t) {
130             if (message instanceof CharSequence) {
131                 logger.logIfEnabled(FQCN, level, MARKER, (CharSequence) message, t);
132             } else {
133                 logger.logIfEnabled(FQCN, level, MARKER, message, t);
134             }
135         }
136 
137         @Override
138         public void trace(final Object message) {
139             logIfEnabled(Level.TRACE, message, null);
140         }
141 
142         @Override
143         public void trace(final Object message, final Throwable t) {
144             logIfEnabled(Level.TRACE, message, t);
145         }
146 
147         @Override
148         public void warn(final Object message) {
149             logIfEnabled(Level.WARN, message, null);
150         }
151 
152         @Override
153         public void warn(final Object message, final Throwable t) {
154             logIfEnabled(Level.WARN, message, t);
155         }
156     }
157     private static final class LogAdapter extends AbstractLoggerAdapter<Log> {
158 
159         @Override
160         protected LoggerContext getContext() {
161             return getContext(LogManager.getFactory().isClassLoaderDependent() ? StackLocatorUtil.getCallerClass(
162                     LogFactory.class) : null);
163         }
164 
165         @Override
166         protected Log newLogger(final String name, final LoggerContext context) {
167             return new Log4j2Log(context.getLogger(name));
168         }
169 
170     }
171 
172     private static final String[] EMPTY_ARRAY = {};
173 
174     /**
175      * Marker used by all messages coming from Apache Commons Logging.
176      */
177     private static final Marker MARKER = MarkerManager.getMarker("COMMONS-LOGGING");
178 
179     /**
180      * Caches Log instances
181      */
182     private final LoggerAdapter<Log> adapter = new LogAdapter();
183 
184     private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
185 
186     /**
187      * Constructs a new instance.
188      */
189     public Log4jApiLogFactory() {
190         // empty
191     }
192 
193     @Override
194     public Object getAttribute(final String name) {
195         return attributes.get(name);
196     }
197 
198     @Override
199     public String[] getAttributeNames() {
200         return attributes.keySet().toArray(EMPTY_ARRAY);
201     }
202 
203     @Override
204     public Log getInstance(final Class<?> clazz) {
205         return getInstance(clazz.getName());
206     }
207 
208     @Override
209     public Log getInstance(final String name) {
210         return adapter.getLogger(name);
211     }
212 
213     /**
214      * This method is supposed to clear all loggers. In this implementation it will clear all the logger
215      * wrappers but the loggers managed by the underlying logger context will not be.
216      */
217     @Override
218     public void release() {
219         try {
220             adapter.close();
221         } catch (final IOException ignored) {
222             // Ignore
223         }
224     }
225 
226     @Override
227     public void removeAttribute(final String name) {
228         attributes.remove(name);
229     }
230 
231     @Override
232     public void setAttribute(final String name, final Object value) {
233         if (value != null) {
234             attributes.put(name, value);
235         } else {
236             removeAttribute(name);
237         }
238     }
239 }