1   /**
2    * Distribution License:
3    * JSword is free software; you can redistribute it and/or modify it under
4    * the terms of the GNU Lesser General Public License, version 2.1 or later
5    * as published by the Free Software Foundation. This program is distributed
6    * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
7    * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8    * See the GNU Lesser General Public License for more details.
9    *
10   * The License is available on the internet at:
11   *       http://www.gnu.org/copyleft/lgpl.html
12   * or by writing to:
13   *      Free Software Foundation, Inc.
14   *      59 Temple Place - Suite 330
15   *      Boston, MA 02111-1307, USA
16   *
17   * Copyright: 2005-2013
18   *     The copyright to this program is held by it's authors.
19   *
20   */
21  package org.crosswire.common.util;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.MissingResourceException;
26  import java.util.logging.Level;
27  import java.util.logging.LogManager;
28  
29  /**
30   * This class is going away. It is a facade for slf4j, which itself is a facade
31   * for an application's logger of choice.
32   * 
33   * This class is very similar to Commons-Logging except it should be even
34   * smaller and have an API closer to the Log4J API (and even J2SE 1.4 logging).
35   * 
36   * This implementation is lazy. The actual internal logger is not initialized
37   * until first use. Turns out that this class indirectly depends upon JSword's
38   * Project class to help find the logging configuration file. If it is not lazy,
39   * it looks in the wrong places for the configuration file.
40   * 
41   * @see gnu.lgpl.License for license details.<br>
42   *      The copyright to this program is held by it's authors.
43   * @author Joe Walker [joe at eireneh dot com]
44   * @author DM Smith
45   * @deprecated Use {@link org.slf4j.LoggerFactory} and {@link org.slf4j.Logger} directly.
46   */
47  @Deprecated
48  public final class Logger {
49      /**
50       * Get a new logger for the class that shows the class, method and line
51       * number of the caller.
52       * @param clazz the class that holds the logger.
53       * @deprecated Use {@link org.slf4j.LoggerFactory#getLogger(Class)} instead.
54       */
55      @Deprecated
56      public static <T> Logger getLogger(Class<T> clazz) {
57          return new Logger(clazz);
58      }
59  
60      /**
61       * Get a new logger for the class that shows the class of the caller.
62       * @param clazz the class that holds the logger.
63       * @param showLocation when true it will get the method and line where logging occurred.
64       * @deprecated Use {@link org.slf4j.LoggerFactory#getLogger(Class)} instead.
65       */
66      @Deprecated
67      public static <T> Logger getLogger(Class<T> clazz, boolean showLocation) {
68          return new Logger(clazz);
69      }
70  
71      /**
72       * Set the level at which output occurs for this Logger.
73       * 
74       * @param newLevel
75       *            the level to apply
76       * @deprecated Use your underlying logger to set levels
77       */
78      @Deprecated
79      public void setLevel(Level newLevel) {
80          level = newLevel;
81      }
82  
83      /**
84       * Stop all logging output
85       * @deprecated Use your underlying logger to set levels
86       */
87      @Deprecated
88      public static synchronized void outputNothing() {
89          level = Level.OFF;
90      }
91  
92      /**
93       * Output a minimum of stuff
94       * @deprecated Use your underlying logger to set levels
95       */
96      @Deprecated
97      public static synchronized void outputInfoMinimum() {
98          level = Level.WARNING;
99      }
100 
101     /**
102      * Output everything
103      * @deprecated Use your underlying logger to set levels
104      */
105     @Deprecated
106     public static synchronized void outputEverything() {
107         level = Level.ALL;
108     }
109 
110     /**
111      * Log a message object with the SEVERE level.
112      * 
113      * @param msg
114      *            the message to log.
115      * @deprecated Use {@link Logger#error(String)} instead.
116      */
117     @Deprecated
118     public void fatal(String msg) {
119         Logger.establishLogging();
120         logger.error(msg);
121     }
122 
123     /**
124      * Log a message object with the SEVERE level.
125      * 
126      * @param msg
127      *            the message object to log.
128      * @deprecated Use {@link Logger#error(String, Throwable)} instead.
129      */
130     @Deprecated
131     public void fatal(String msg, Throwable th) {
132         Logger.establishLogging();
133         logger.error(msg, th);
134     }
135 
136     /**
137      * Is the logger instance enabled for the ERROR level?
138      *
139      * @return True if this Logger is enabled for the ERROR level,
140      *         false otherwise.
141      */
142     public boolean isErrorEnabled() {
143         Logger.establishLogging();
144         return logger.isErrorEnabled();
145     }
146 
147     /**
148      * Log a message at the ERROR level.
149      *
150      * @param msg the message string to be logged
151      */
152     public void error(String msg) {
153         Logger.establishLogging();
154         logger.error(msg);
155     }
156 
157     /**
158      * Log a message at the ERROR level according to the specified format
159      * and argument.
160      * <p/>
161      * <p>This form avoids superfluous object creation when the logger
162      * is disabled for the ERROR level. </p>
163      *
164      * @param format the format string
165      * @param arg    the argument
166      */
167     public void error(String format, Object arg) {
168         Logger.establishLogging();
169         logger.error(format, arg);
170     }
171 
172     /**
173      * Log a message at the ERROR level according to the specified format
174      * and arguments.
175      * <p/>
176      * <p>This form avoids superfluous object creation when the logger
177      * is disabled for the ERROR level. </p>
178      *
179      * @param format the format string
180      * @param arg1   the first argument
181      * @param arg2   the second argument
182      */
183     public void error(String format, Object arg1, Object arg2) {
184         Logger.establishLogging();
185         logger.error(format, arg1, arg2);
186     }
187 
188     /**
189      * Log a message at the ERROR level according to the specified format
190      * and arguments.
191      * <p/>
192      * <p>This form avoids superfluous string concatenation when the logger
193      * is disabled for the ERROR level. However, this variant incurs the hidden
194      * (and relatively small) cost of creating an <code>Object[]</code> before invoking the method,
195      * even if this logger is disabled for ERROR. The variants taking
196      * {@link #error(String, Object) one} and {@link #error(String, Object, Object) two}
197      * arguments exist solely in order to avoid this hidden cost.</p>
198      *
199      * @param format    the format string
200      * @param arguments a list of 3 or more arguments
201      */
202     public void error(String format, Object... arguments) {
203         Logger.establishLogging();
204         logger.error(format, arguments);
205     }
206 
207     /**
208      * Log an exception (throwable) at the ERROR level with an
209      * accompanying message.
210      *
211      * @param msg the message accompanying the exception
212      * @param t   the exception (throwable) to log
213      */
214     public void error(String msg, Throwable th) {
215         Logger.establishLogging();
216         logger.error(msg, th);
217     }
218 
219     /**
220      * Is the logger instance enabled for the INFO level?
221      *
222      * @return True if this Logger is enabled for the INFO level,
223      *         false otherwise.
224      */
225     public boolean isInfoEnabled() {
226         Logger.establishLogging();
227         return logger.isInfoEnabled();
228     }
229 
230     /**
231      * Log a message at the INFO level.
232      *
233      * @param msg the message string to be logged
234      */
235     public void info(String msg) {
236         Logger.establishLogging();
237         logger.info(msg);
238     }
239 
240     /**
241      * Log a message at the INFO level according to the specified format
242      * and argument.
243      * <p/>
244      * <p>This form avoids superfluous object creation when the logger
245      * is disabled for the INFO level. </p>
246      *
247      * @param format the format string
248      * @param arg    the argument
249      */
250     public void info(String format, Object arg) {
251         Logger.establishLogging();
252         logger.info(format, arg);
253     }
254 
255     /**
256      * Log a message at the INFO level according to the specified format
257      * and arguments.
258      * <p/>
259      * <p>This form avoids superfluous object creation when the logger
260      * is disabled for the INFO level. </p>
261      *
262      * @param format the format string
263      * @param arg1   the first argument
264      * @param arg2   the second argument
265      */
266     public void info(String format, Object arg1, Object arg2) {
267         Logger.establishLogging();
268         logger.info(format, arg1, arg2);
269     }
270 
271     /**
272      * Log a message at the INFO level according to the specified format
273      * and arguments.
274      * <p/>
275      * <p>This form avoids superfluous string concatenation when the logger
276      * is disabled for the INFO level. However, this variant incurs the hidden
277      * (and relatively small) cost of creating an <code>Object[]</code> before invoking the method,
278      * even if this logger is disabled for INFO. The variants taking
279      * {@link #info(String, Object) one} and {@link #info(String, Object, Object) two}
280      * arguments exist solely in order to avoid this hidden cost.</p>
281      *
282      * @param format    the format string
283      * @param arguments a list of 3 or more arguments
284      */
285     public void info(String format, Object... arguments) {
286         Logger.establishLogging();
287         logger.info(format, arguments);
288     }
289 
290     /**
291      * Log an exception (throwable) at the INFO level with an
292      * accompanying message.
293      *
294      * @param msg the message accompanying the exception
295      * @param t   the exception (throwable) to log
296      */
297     public void info(String msg, Throwable th) {
298         Logger.establishLogging();
299         logger.info(msg, th);
300     }
301 
302     /**
303      * Is the logger instance enabled for the WARN level?
304      *
305      * @return True if this Logger is enabled for the WARN level,
306      *         false otherwise.
307      */
308     public boolean isWarnEnabled() {
309         Logger.establishLogging();
310         return logger.isWarnEnabled();
311     }
312 
313     /**
314      * Log a message at the WARN level.
315      *
316      * @param msg the message string to be logged
317      */
318     public void warn(String msg) {
319         Logger.establishLogging();
320         logger.warn(msg);
321     }
322 
323     /**
324      * Log a message at the WARN level according to the specified format
325      * and argument.
326      * <p/>
327      * <p>This form avoids superfluous object creation when the logger
328      * is disabled for the WARN level. </p>
329      *
330      * @param format the format string
331      * @param arg    the argument
332      */
333     public void warn(String format, Object arg) {
334         Logger.establishLogging();
335         logger.warn(format, arg);
336     }
337 
338     /**
339      * Log a message at the WARN level according to the specified format
340      * and arguments.
341      * <p/>
342      * <p>This form avoids superfluous object creation when the logger
343      * is disabled for the WARN level. </p>
344      *
345      * @param format the format string
346      * @param arg1   the first argument
347      * @param arg2   the second argument
348      */
349     public void warn(String format, Object arg1, Object arg2) {
350         Logger.establishLogging();
351         logger.warn(format, arg1, arg2);
352     }
353 
354     /**
355      * Log a message at the WARN level according to the specified format
356      * and arguments.
357      * <p/>
358      * <p>This form avoids superfluous string concatenation when the logger
359      * is disabled for the WARN level. However, this variant incurs the hidden
360      * (and relatively small) cost of creating an <code>Object[]</code> before invoking the method,
361      * even if this logger is disabled for WARN. The variants taking
362      * {@link #warn(String, Object) one} and {@link #warn(String, Object, Object) two}
363      * arguments exist solely in order to avoid this hidden cost.</p>
364      *
365      * @param format    the format string
366      * @param arguments a list of 3 or more arguments
367      */
368     public void warn(String format, Object... arguments) {
369         Logger.establishLogging();
370         logger.warn(format, arguments);
371     }
372 
373     /**
374      * Log an exception (throwable) at the WARN level with an
375      * accompanying message.
376      *
377      * @param msg the message accompanying the exception
378      * @param t   the exception (throwable) to log
379      */
380     public void warn(String msg, Throwable th) {
381         Logger.establishLogging();
382         logger.debug(msg, th);
383     }
384 
385     /**
386      * Is the logger instance enabled for the DEBUG level?
387      *
388      * @return True if this Logger is enabled for the DEBUG level,
389      *         false otherwise.
390      */
391     public boolean isDebugEnabled() {
392         Logger.establishLogging();
393         return logger.isDebugEnabled();
394     }
395 
396     /**
397      * Log a message at the DEBUG level.
398      *
399      * @param msg the message string to be logged
400      */
401     public void debug(String msg) {
402         Logger.establishLogging();
403         logger.debug(msg);
404     }
405 
406     /**
407      * Log a message at the DEBUG level according to the specified format
408      * and argument.
409      * <p/>
410      * <p>This form avoids superfluous object creation when the logger
411      * is disabled for the DEBUG level. </p>
412      *
413      * @param format the format string
414      * @param arg    the argument
415      */
416     public void debug(String format, Object arg) {
417         Logger.establishLogging();
418         logger.debug(format, arg);
419     }
420 
421     /**
422      * Log a message at the DEBUG level according to the specified format
423      * and arguments.
424      * <p/>
425      * <p>This form avoids superfluous object creation when the logger
426      * is disabled for the DEBUG level. </p>
427      *
428      * @param format the format string
429      * @param arg1   the first argument
430      * @param arg2   the second argument
431      */
432     public void debug(String format, Object arg1, Object arg2) {
433         Logger.establishLogging();
434         logger.debug(format, arg1, arg2);
435     }
436 
437     /**
438      * Log a message at the DEBUG level according to the specified format
439      * and arguments.
440      * <p/>
441      * <p>This form avoids superfluous string concatenation when the logger
442      * is disabled for the DEBUG level. However, this variant incurs the hidden
443      * (and relatively small) cost of creating an <code>Object[]</code> before invoking the method,
444      * even if this logger is disabled for DEBUG. The variants taking
445      * {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two}
446      * arguments exist solely in order to avoid this hidden cost.</p>
447      *
448      * @param format    the format string
449      * @param arguments a list of 3 or more arguments
450      */
451     public void debug(String format, Object... arguments) {
452         Logger.establishLogging();
453         logger.debug(format, arguments);
454     }
455 
456     /**
457      * Log an exception (throwable) at the DEBUG level with an
458      * accompanying message.
459      *
460      * @param msg the message accompanying the exception
461      * @param t   the exception (throwable) to log
462      */
463     public void debug(String msg, Throwable t) {
464         Logger.establishLogging();
465         logger.debug(msg, t);
466     }
467 
468     /**
469      * Log a message with the supplied level.
470      * 
471      * @param lev
472      *            the level at which to log.
473      * @param msg
474      *            the message to log.
475      * @deprecated Use {@link Logger#error(String)},
476      *                 {@link Logger#warn(String)},
477      *                 {@link Logger#info(String)}, 
478      *                 {@link Logger#debug(String)},
479      *              or {@link Logger#trace(String)} 
480      */
481     @Deprecated
482     public void log(Level lev, String msg) {
483         if (lev == null) {
484             throw new IllegalArgumentException("must supply a Level");
485         }
486         int intLevel = lev.intValue();
487         if (intLevel == Level.OFF.intValue() || intLevel == Level.ALL.intValue()) {
488             return;
489         }
490         if (intLevel >= Level.SEVERE.intValue()) {
491             logger.error(msg);
492         } else if (intLevel >= Level.WARNING.intValue()) {
493             logger.warn(msg);
494         } else if (intLevel >= Level.INFO.intValue()) {
495             logger.info(msg);
496         } else if (intLevel >= Level.FINE.intValue()) {
497             logger.debug(msg);
498         } else if (intLevel >= Level.FINEST.intValue()) {
499             logger.trace(msg);
500         }
501     }
502 
503     /**
504      * Log a message with the supplied level, recording the exception when not
505      * null.
506      * 
507      * @param msg
508      *            the message object to log.
509      * @deprecated Use {@link Logger#error(String, Throwable)},
510      *                 {@link Logger#warn(String, Throwable)},
511      *                 {@link Logger#info(String, Throwable)}, 
512      *                 {@link Logger#debug(String, Throwable)},
513      *              or {@link Logger#trace(String, Throwable)} 
514      */
515     @Deprecated
516     public void log(Level lev, String msg, Throwable th) {
517         if (lev == null) {
518             throw new IllegalArgumentException("must supply a Level");
519         }
520         int intLevel = lev.intValue();
521         if (intLevel == Level.OFF.intValue() || intLevel == Level.ALL.intValue()) {
522             return;
523         }
524         if (intLevel >= Level.SEVERE.intValue()) {
525             logger.error(msg, th);
526         } else if (intLevel >= Level.WARNING.intValue()) {
527             logger.warn(msg, th);
528         } else if (intLevel >= Level.INFO.intValue()) {
529             logger.info(msg, th);
530         } else if (intLevel >= Level.FINE.intValue()) {
531             logger.debug(msg, th);
532         } else { //if (intLevel >= Level.FINEST.intValue()) {
533             logger.trace(msg, th);
534         }
535     }
536 
537     /**
538      * Create a logger for the class. Wrapped by {@link org.slf4j.Logger#getLogger(Class)}.
539      */
540     private <T> Logger(Class<T> id) {
541         this.logger = org.slf4j.LoggerFactory.getLogger(id);
542     }
543 
544     // Private method to infer the caller's class and method names
545 //    private void doLogging(Level theLevel, String message, Throwable th) {
546 //        // now check whether we should do any work
547 //        if (!shouldLog(theLevel)) {
548 //            return;
549 //        }
550 //
551 //        LogRecord logRecord = new LogRecord(theLevel, message);
552 //        logRecord.setLoggerName(logger.getName());
553 //        logRecord.setSourceClassName(CallContext.getCallingClass(1).getName());
554 //        logRecord.setThrown(th);
555 //
556 //        if (showLocation && (showLocationForInfoDebugTrace || theLevel.intValue() > Level.INFO.intValue())) {
557 //            String methodName = null;
558 //            int lineNumber = -1;
559 //
560 //            // Get the stack trace.
561 //            StackTraceElement[] stack = (new Throwable()).getStackTrace();
562 //
563 //            // First, search back to a method in the Logger class.
564 //            int ix = 0;
565 //            while (ix < stack.length) {
566 //                StackTraceElement frame = stack[ix];
567 //                String cname = frame.getClassName();
568 //                if (cname.equals(CLASS_NAME)) {
569 //                    break;
570 //                }
571 //                ix++;
572 //            }
573 //
574 //            // Now search for the first frame with the name of the caller.
575 //            while (ix < stack.length) {
576 //                StackTraceElement frame = stack[ix];
577 //                if (!frame.getClassName().equals(CLASS_NAME)) {
578 //                    // We've found the relevant frame.
579 //                    methodName = frame.getMethodName();
580 //                    lineNumber = frame.getLineNumber();
581 //                    break;
582 //                }
583 //                ix++;
584 //            }
585 //
586 //            logRecord.setSourceMethodName(methodName);
587 //            // This is a non-standard use of sequence number.
588 //            // We could just subclass LogRecord and add line number.
589 //            logRecord.setSequenceNumber(lineNumber);
590 //        }
591 //
592 //        logger.log(logRecord);
593 //    }
594 
595     /**
596      * Should log, returns true if theLevel should be logged by this logger. See {@link java.util.logging.Logger#isLoggable(Level) for more details}
597      *
598      * @param theLevel the the level
599      * @return true, if successful
600      * @deprecated Use {@link Logger#isErrorEnabled()},
601      *                 {@link Logger#isWarnEnabled()},
602      *                 {@link Logger#isInfoEnabled()}, 
603      *                 {@link Logger#isDebugEnabled()},
604      *              or {@link Logger#isTraceEnabled()} 
605      */
606     @Deprecated
607     public boolean shouldLog(Level theLevel) {
608         int levelValue = level.intValue();
609         if (theLevel.intValue() < levelValue || levelValue == Level.OFF.intValue()) {
610             return false;
611         }
612         return true;
613     }
614 
615     public static void establishLogging() {
616         if (established) {
617             return;
618         }
619         established = true;
620 
621         Exception ex = null;
622         try {
623             InputStream cwConfigStream = ResourceUtil.getResourceAsStream("CWLogging.properties");
624             LogManager.getLogManager().readConfiguration(cwConfigStream);
625         } catch (SecurityException e) {
626             ex = e;
627         } catch (MissingResourceException e) {
628             ex = e;
629         } catch (IOException e) {
630             ex = e;
631         }
632         if (ex != null) {
633             cwLogger.info("Can't load CWLogging.properties", ex);
634         }
635     }
636 
637     /**
638      * Sets the show location for debug and trace.
639      *
640      * @param enabled true to display the location on info, debug and trace as well as error and warn
641      */
642     public static void setShowLocationForInfoDebugTrace(boolean enabled) {
643         //showLocationForInfoDebugTrace = enabled;
644     }
645 
646     private static volatile boolean established;
647     private static volatile Level level;
648 
649     /**
650      * The actual logger.
651      */
652     private org.slf4j.Logger logger;
653     private static Logger cwLogger = getLogger(Logger.class);
654 
655 }
656