001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    package org.apache.logging.slf4j;
018    
019    import java.io.IOException;
020    import java.io.ObjectInputStream;
021    import java.io.ObjectOutputStream;
022    import java.io.Serializable;
023    
024    import org.apache.logging.log4j.Level;
025    import org.apache.logging.log4j.LogManager;
026    import org.apache.logging.log4j.message.Message;
027    import org.apache.logging.log4j.message.ParameterizedMessage;
028    import org.apache.logging.log4j.message.SimpleMessage;
029    import org.apache.logging.log4j.spi.ExtendedLogger;
030    import org.slf4j.Marker;
031    import org.slf4j.MarkerFactory;
032    import org.slf4j.spi.LocationAwareLogger;
033    
034    /**
035     * SLF4J logger implementation that uses Log4j.
036     */
037    public class Log4jLogger implements LocationAwareLogger, Serializable {
038    
039        public static final String FQCN = Log4jLogger.class.getName();
040    
041        private static final long serialVersionUID = 7869000638091304316L;
042        private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
043        private final boolean eventLogger;
044        private transient ExtendedLogger logger;
045        private final String name;
046        private transient EventDataConverter converter;
047    
048        public Log4jLogger(final ExtendedLogger logger, final String name) {
049            this.logger = logger;
050            this.eventLogger = "EventLogger".equals(name);
051            this.name = name;
052            this.converter = createConverter();
053        }
054    
055        @Override
056        public void trace(final String format) {
057            logger.logIfEnabled(FQCN, Level.TRACE, null, format);
058        }
059    
060        @Override
061        public void trace(final String format, final Object o) {
062            logger.logIfEnabled(FQCN, Level.TRACE, null, format, o);
063        }
064    
065        @Override
066        public void trace(final String format, final Object arg1, final Object arg2) {
067            logger.logIfEnabled(FQCN, Level.TRACE, null, format, arg1, arg2);
068        }
069    
070        @Override
071        public void trace(final String format, final Object... args) {
072            logger.logIfEnabled(FQCN, Level.TRACE, null, format, args);
073        }
074    
075        @Override
076        public void trace(final String format, final Throwable t) {
077            logger.logIfEnabled(FQCN, Level.TRACE, null, format, t);
078        }
079    
080        @Override
081        public boolean isTraceEnabled() {
082            return logger.isEnabled(Level.TRACE, null, null);
083        }
084    
085        @Override
086        public boolean isTraceEnabled(final Marker marker) {
087            return logger.isEnabled(Level.TRACE, getMarker(marker), null);
088        }
089    
090        @Override
091        public void trace(final Marker marker, final String s) {
092            logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s);
093        }
094    
095        @Override
096        public void trace(final Marker marker, final String s, final Object o) {
097            logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o);
098        }
099    
100        @Override
101        public void trace(final Marker marker, final String s, final Object o, final Object o1) {
102            logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o, o1);
103        }
104    
105        @Override
106        public void trace(final Marker marker, final String s, final Object... objects) {
107            logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, objects);
108        }
109    
110        @Override
111        public void trace(final Marker marker, final String s, final Throwable throwable) {
112            logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, throwable);
113        }
114    
115        @Override
116        public void debug(final String format) {
117            logger.logIfEnabled(FQCN, Level.DEBUG, null, format);
118        }
119    
120        @Override
121        public void debug(final String format, final Object o) {
122            logger.logIfEnabled(FQCN, Level.DEBUG, null, format, o);
123        }
124    
125        @Override
126        public void debug(final String format, final Object arg1, final Object arg2) {
127            logger.logIfEnabled(FQCN, Level.DEBUG, null, format, arg1, arg2);
128        }
129    
130        @Override
131        public void debug(final String format, final Object... args) {
132            logger.logIfEnabled(FQCN, Level.DEBUG, null, format, args);
133        }
134    
135        @Override
136        public void debug(final String format, final Throwable t) {
137            logger.logIfEnabled(FQCN, Level.DEBUG, null, format, t);
138        }
139    
140        @Override
141        public boolean isDebugEnabled() {
142            return logger.isEnabled(Level.DEBUG, null, null);
143        }
144    
145        @Override
146        public boolean isDebugEnabled(final Marker marker) {
147            return logger.isEnabled(Level.DEBUG, getMarker(marker), null);
148        }
149    
150        @Override
151        public void debug(final Marker marker, final String s) {
152            logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s);
153        }
154    
155        @Override
156        public void debug(final Marker marker, final String s, final Object o) {
157            logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o);
158        }
159    
160        @Override
161        public void debug(final Marker marker, final String s, final Object o, final Object o1) {
162            logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o, o1);
163        }
164    
165        @Override
166        public void debug(final Marker marker, final String s, final Object... objects) {
167            logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, objects);
168        }
169    
170        @Override
171        public void debug(final Marker marker, final String s, final Throwable throwable) {
172            logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, throwable);
173        }
174    
175        @Override
176        public void info(final String format) {
177            logger.logIfEnabled(FQCN, Level.INFO, null, format);
178        }
179    
180        @Override
181        public void info(final String format, final Object o) {
182            logger.logIfEnabled(FQCN, Level.INFO, null, format, o);
183        }
184    
185        @Override
186        public void info(final String format, final Object arg1, final Object arg2) {
187            logger.logIfEnabled(FQCN, Level.INFO, null, format, arg1, arg2);
188        }
189    
190        @Override
191        public void info(final String format, final Object... args) {
192            logger.logIfEnabled(FQCN, Level.INFO, null, format, args);
193        }
194    
195        @Override
196        public void info(final String format, final Throwable t) {
197            logger.logIfEnabled(FQCN, Level.INFO, null, format, t);
198        }
199    
200        @Override
201        public boolean isInfoEnabled() {
202            return logger.isEnabled(Level.INFO, null, null);
203        }
204    
205        @Override
206        public boolean isInfoEnabled(final Marker marker) {
207            return logger.isEnabled(Level.INFO, getMarker(marker), null);
208        }
209    
210        @Override
211        public void info(final Marker marker, final String s) {
212            logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s);
213        }
214    
215        @Override
216        public void info(final Marker marker, final String s, final Object o) {
217            logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o);
218        }
219    
220        @Override
221        public void info(final Marker marker, final String s, final Object o, final Object o1) {
222            logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o, o1);
223        }
224    
225        @Override
226        public void info(final Marker marker, final String s, final Object... objects) {
227            logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, objects);
228        }
229    
230        @Override
231        public void info(final Marker marker, final String s, final Throwable throwable) {
232            logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, throwable);
233        }
234    
235        @Override
236        public void warn(final String format) {
237            logger.logIfEnabled(FQCN, Level.WARN, null, format);
238        }
239    
240        @Override
241        public void warn(final String format, final Object o) {
242            logger.logIfEnabled(FQCN, Level.WARN, null, format, o);
243        }
244    
245        @Override
246        public void warn(final String format, final Object arg1, final Object arg2) {
247            logger.logIfEnabled(FQCN, Level.WARN, null, format, arg1, arg2);
248        }
249    
250        @Override
251        public void warn(final String format, final Object... args) {
252            logger.logIfEnabled(FQCN, Level.WARN, null, format, args);
253        }
254    
255        @Override
256        public void warn(final String format, final Throwable t) {
257            logger.logIfEnabled(FQCN, Level.WARN, null, format, t);
258        }
259    
260        @Override
261        public boolean isWarnEnabled() {
262            return logger.isEnabled(Level.WARN, null, null);
263        }
264    
265        @Override
266        public boolean isWarnEnabled(final Marker marker) {
267            return logger.isEnabled(Level.WARN, getMarker(marker), null);
268        }
269    
270        @Override
271        public void warn(final Marker marker, final String s) {
272            logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s);
273        }
274    
275        @Override
276        public void warn(final Marker marker, final String s, final Object o) {
277            logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o);
278        }
279    
280        @Override
281        public void warn(final Marker marker, final String s, final Object o, final Object o1) {
282            logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o, o1);
283        }
284    
285        @Override
286        public void warn(final Marker marker, final String s, final Object... objects) {
287            logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, objects);
288        }
289    
290        @Override
291        public void warn(final Marker marker, final String s, final Throwable throwable) {
292            logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, throwable);
293        }
294    
295        @Override
296        public void error(final String format) {
297            logger.logIfEnabled(FQCN, Level.ERROR, null, format);
298        }
299    
300        @Override
301        public void error(final String format, final Object o) {
302            logger.logIfEnabled(FQCN, Level.ERROR, null, format, o);
303        }
304    
305        @Override
306        public void error(final String format, final Object arg1, final Object arg2) {
307            logger.logIfEnabled(FQCN, Level.ERROR, null, format, arg1, arg2);
308        }
309    
310        @Override
311        public void error(final String format, final Object... args) {
312            logger.logIfEnabled(FQCN, Level.ERROR, null, format, args);
313        }
314    
315        @Override
316        public void error(final String format, final Throwable t) {
317            logger.logIfEnabled(FQCN, Level.ERROR, null, format, t);
318        }
319    
320        @Override
321        public boolean isErrorEnabled() {
322            return logger.isEnabled(Level.ERROR, null, null);
323        }
324    
325        @Override
326        public boolean isErrorEnabled(final Marker marker) {
327            return logger.isEnabled(Level.ERROR, getMarker(marker), null);
328        }
329    
330        @Override
331        public void error(final Marker marker, final String s) {
332            logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s);
333        }
334    
335        @Override
336        public void error(final Marker marker, final String s, final Object o) {
337            logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o);
338        }
339    
340        @Override
341        public void error(final Marker marker, final String s, final Object o, final Object o1) {
342            logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o, o1);
343        }
344    
345        @Override
346        public void error(final Marker marker, final String s, final Object... objects) {
347            logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, objects);
348        }
349    
350        @Override
351        public void error(final Marker marker, final String s, final Throwable throwable) {
352            logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, throwable);
353        }
354    
355        @Override
356        public void log(final Marker marker, final String fqcn, final int level, final String message, final Object[] params, Throwable throwable) {
357            final Level log4jLevel = getLevel(level);
358            final org.apache.logging.log4j.Marker log4jMarker = getMarker(marker);
359    
360            if (!logger.isEnabled(log4jLevel, log4jMarker, message, params)) {
361                return;
362            }
363            final Message msg;
364            if (eventLogger && marker != null && marker.contains(EVENT_MARKER) && converter != null) {
365                msg = converter.convertEvent(message, params, throwable);
366            } else if (params == null) {
367                msg = new SimpleMessage(message);
368            } else {
369                msg = new ParameterizedMessage(message, params, throwable);
370                if (throwable != null) {
371                    throwable = msg.getThrowable();
372                }
373            }
374            logger.logMessage(fqcn, log4jLevel, log4jMarker, msg, throwable);
375        }
376    
377        private static org.apache.logging.log4j.Marker getMarker(final Marker marker) {
378            return marker != null ? ((org.apache.logging.slf4j.Log4jMarker) marker).getLog4jMarker() : null;
379        }
380    
381        @Override
382        public String getName() {
383            return name;
384        }
385    
386        /**
387         * Always treat de-serialization as a full-blown constructor, by validating the final state of
388         * the de-serialized object.
389         */
390        private void readObject(final ObjectInputStream aInputStream) throws ClassNotFoundException, IOException {
391            // always perform the default de-serialization first
392            aInputStream.defaultReadObject();
393            logger = LogManager.getContext().getLogger(name);
394            converter = createConverter();
395        }
396    
397        /**
398         * This is the default implementation of writeObject. Customise if necessary.
399         */
400        private void writeObject(final ObjectOutputStream aOutputStream) throws IOException {
401            // perform the default serialization for all non-transient, non-static fields
402            aOutputStream.defaultWriteObject();
403        }
404    
405        private static EventDataConverter createConverter() {
406            try {
407                Class.forName("org.slf4j.ext.EventData");
408                return new EventDataConverter();
409            } catch (final ClassNotFoundException cnfe) {
410                return null;
411            }
412        }
413    
414        private static Level getLevel(final int i) {
415            switch (i) {
416            case TRACE_INT:
417                return Level.TRACE;
418            case DEBUG_INT:
419                return Level.DEBUG;
420            case INFO_INT:
421                return Level.INFO;
422            case WARN_INT:
423                return Level.WARN;
424            case ERROR_INT:
425                return Level.ERROR;
426            }
427            return Level.ERROR;
428        }
429    }