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
018package org.apache.commons.logging.impl;
019
020import java.io.Serializable;
021import java.util.logging.Level;
022import java.util.logging.Logger;
023import java.util.logging.LogRecord;
024import java.util.StringTokenizer;
025import java.io.PrintWriter;
026import java.io.StringWriter;
027
028import org.apache.commons.logging.Log;
029
030/**
031 * Implementation of the <code>org.apache.commons.logging.Log</code>
032 * interface that wraps the standard JDK logging mechanisms that are
033 * available in SourceForge's Lumberjack for JDKs prior to 1.4.
034 *
035 * @version $Id: Jdk13LumberjackLogger.html 915605 2014-07-09 20:22:43Z tn $
036 * @since 1.1
037 */
038public class Jdk13LumberjackLogger implements Log, Serializable {
039
040    /** Serializable version identifier. */
041    private static final long serialVersionUID = -8649807923527610591L;
042
043    // ----------------------------------------------------- Instance Variables
044
045    /**
046     * The underlying Logger implementation we are using.
047     */
048    protected transient Logger logger = null;
049    protected String name = null;
050    private String sourceClassName = "unknown";
051    private String sourceMethodName = "unknown";
052    private boolean classAndMethodFound = false;
053
054    /**
055     * This member variable simply ensures that any attempt to initialise
056     * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError.
057     * It must not be private, as an optimising compiler could detect that it
058     * is not used and optimise it away.
059     */
060    protected static final Level dummyLevel = Level.FINE;
061
062    // ----------------------------------------------------------- Constructors
063
064    /**
065     * Construct a named instance of this Logger.
066     *
067     * @param name Name of the logger to be constructed
068     */
069    public Jdk13LumberjackLogger(String name) {
070        this.name = name;
071        logger = getLogger();
072    }
073
074    // --------------------------------------------------------- Public Methods
075
076    private void log( Level level, String msg, Throwable ex ) {
077        if( getLogger().isLoggable(level) ) {
078            LogRecord record = new LogRecord(level, msg);
079            if( !classAndMethodFound ) {
080                getClassAndMethod();
081            }
082            record.setSourceClassName(sourceClassName);
083            record.setSourceMethodName(sourceMethodName);
084            if( ex != null ) {
085                record.setThrown(ex);
086            }
087            getLogger().log(record);
088        }
089    }
090
091    /**
092     * Gets the class and method by looking at the stack trace for the
093     * first entry that is not this class.
094     */
095    private void getClassAndMethod() {
096        try {
097            Throwable throwable = new Throwable();
098            throwable.fillInStackTrace();
099            StringWriter stringWriter = new StringWriter();
100            PrintWriter printWriter = new PrintWriter( stringWriter );
101            throwable.printStackTrace( printWriter );
102            String traceString = stringWriter.getBuffer().toString();
103            StringTokenizer tokenizer =
104                new StringTokenizer( traceString, "\n" );
105            tokenizer.nextToken();
106            String line = tokenizer.nextToken();
107            while ( line.indexOf( this.getClass().getName() )  == -1 ) {
108                line = tokenizer.nextToken();
109            }
110            while ( line.indexOf( this.getClass().getName() ) >= 0 ) {
111                line = tokenizer.nextToken();
112            }
113            int start = line.indexOf( "at " ) + 3;
114            int end = line.indexOf( '(' );
115            String temp = line.substring( start, end );
116            int lastPeriod = temp.lastIndexOf( '.' );
117            sourceClassName = temp.substring( 0, lastPeriod );
118            sourceMethodName = temp.substring( lastPeriod + 1 );
119        } catch ( Exception ex ) {
120            // ignore - leave class and methodname unknown
121        }
122        classAndMethodFound = true;
123    }
124
125    /**
126     * Logs a message with <code>java.util.logging.Level.FINE</code>.
127     *
128     * @param message to log
129     * @see org.apache.commons.logging.Log#debug(Object)
130     */
131    public void debug(Object message) {
132        log(Level.FINE, String.valueOf(message), null);
133    }
134
135    /**
136     * Logs a message with <code>java.util.logging.Level.FINE</code>.
137     *
138     * @param message to log
139     * @param exception log this cause
140     * @see org.apache.commons.logging.Log#debug(Object, Throwable)
141     */
142    public void debug(Object message, Throwable exception) {
143        log(Level.FINE, String.valueOf(message), exception);
144    }
145
146    /**
147     * Logs a message with <code>java.util.logging.Level.SEVERE</code>.
148     *
149     * @param message to log
150     * @see org.apache.commons.logging.Log#error(Object)
151     */
152    public void error(Object message) {
153        log(Level.SEVERE, String.valueOf(message), null);
154    }
155
156    /**
157     * Logs a message with <code>java.util.logging.Level.SEVERE</code>.
158     *
159     * @param message to log
160     * @param exception log this cause
161     * @see org.apache.commons.logging.Log#error(Object, Throwable)
162     */
163    public void error(Object message, Throwable exception) {
164        log(Level.SEVERE, String.valueOf(message), exception);
165    }
166
167    /**
168     * Logs a message with <code>java.util.logging.Level.SEVERE</code>.
169     *
170     * @param message to log
171     * @see org.apache.commons.logging.Log#fatal(Object)
172     */
173    public void fatal(Object message) {
174        log(Level.SEVERE, String.valueOf(message), null);
175    }
176
177    /**
178     * Logs a message with <code>java.util.logging.Level.SEVERE</code>.
179     *
180     * @param message to log
181     * @param exception log this cause
182     * @see org.apache.commons.logging.Log#fatal(Object, Throwable)
183     */
184    public void fatal(Object message, Throwable exception) {
185        log(Level.SEVERE, String.valueOf(message), exception);
186    }
187
188    /**
189     * Return the native Logger instance we are using.
190     */
191    public Logger getLogger() {
192        if (logger == null) {
193            logger = Logger.getLogger(name);
194        }
195        return logger;
196    }
197
198    /**
199     * Logs a message with <code>java.util.logging.Level.INFO</code>.
200     *
201     * @param message to log
202     * @see org.apache.commons.logging.Log#info(Object)
203     */
204    public void info(Object message) {
205        log(Level.INFO, String.valueOf(message), null);
206    }
207
208    /**
209     * Logs a message with <code>java.util.logging.Level.INFO</code>.
210     *
211     * @param message to log
212     * @param exception log this cause
213     * @see org.apache.commons.logging.Log#info(Object, Throwable)
214     */
215    public void info(Object message, Throwable exception) {
216        log(Level.INFO, String.valueOf(message), exception);
217    }
218
219    /**
220     * Is debug logging currently enabled?
221     */
222    public boolean isDebugEnabled() {
223        return getLogger().isLoggable(Level.FINE);
224    }
225
226    /**
227     * Is error logging currently enabled?
228     */
229    public boolean isErrorEnabled() {
230        return getLogger().isLoggable(Level.SEVERE);
231    }
232
233    /**
234     * Is fatal logging currently enabled?
235     */
236    public boolean isFatalEnabled() {
237        return getLogger().isLoggable(Level.SEVERE);
238    }
239
240    /**
241     * Is info logging currently enabled?
242     */
243    public boolean isInfoEnabled() {
244        return getLogger().isLoggable(Level.INFO);
245    }
246
247    /**
248     * Is trace logging currently enabled?
249     */
250    public boolean isTraceEnabled() {
251        return getLogger().isLoggable(Level.FINEST);
252    }
253
254    /**
255     * Is warn logging currently enabled?
256     */
257    public boolean isWarnEnabled() {
258        return getLogger().isLoggable(Level.WARNING);
259    }
260
261    /**
262     * Logs a message with <code>java.util.logging.Level.FINEST</code>.
263     *
264     * @param message to log
265     * @see org.apache.commons.logging.Log#trace(Object)
266     */
267    public void trace(Object message) {
268        log(Level.FINEST, String.valueOf(message), null);
269    }
270
271    /**
272     * Logs a message with <code>java.util.logging.Level.FINEST</code>.
273     *
274     * @param message to log
275     * @param exception log this cause
276     * @see org.apache.commons.logging.Log#trace(Object, Throwable)
277     */
278    public void trace(Object message, Throwable exception) {
279        log(Level.FINEST, String.valueOf(message), exception);
280    }
281
282    /**
283     * Logs a message with <code>java.util.logging.Level.WARNING</code>.
284     *
285     * @param message to log
286     * @see org.apache.commons.logging.Log#warn(Object)
287     */
288    public void warn(Object message) {
289        log(Level.WARNING, String.valueOf(message), null);
290    }
291
292    /**
293     * Logs a message with <code>java.util.logging.Level.WARNING</code>.
294     *
295     * @param message to log
296     * @param exception log this cause
297     * @see org.apache.commons.logging.Log#warn(Object, Throwable)
298     */
299    public void warn(Object message, Throwable exception) {
300        log(Level.WARNING, String.valueOf(message), exception);
301    }
302}