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