| Logger.java |
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