View Javadoc

1   /*
2    * Copyright (c) 2004-2013 QOS.ch
3    * All rights reserved.
4    *
5    * Permission is hereby granted, free  of charge, to any person obtaining
6    * a  copy  of this  software  and  associated  documentation files  (the
7    * "Software"), to  deal in  the Software without  restriction, including
8    * without limitation  the rights to  use, copy, modify,  merge, publish,
9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
10   * permit persons to whom the Software  is furnished to do so, subject to
11   * the following conditions:
12   *
13   * The  above  copyright  notice  and  this permission  notice  shall  be
14   * included in all copies or substantial portions of the Software.
15   *
16   * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
17   * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
18   * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21   * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
22   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23   *
24   */
25  package org.slf4j.impl;
26  
27  import android.util.Log;
28  import org.slf4j.helpers.FormattingTuple;
29  import org.slf4j.helpers.MarkerIgnoringBase;
30  import org.slf4j.helpers.MessageFormatter;
31  
32  /**
33   * <p>A simple implementation that delegates all log requests to the Google Android
34   * logging facilities. Note that this logger does not support {@link org.slf4j.Marker}.
35   * Methods taking marker data as parameter simply invoke the eponymous method
36   * without the Marker argument, discarding any marker data in the process.</p>
37   *
38   * <p>The logging levels specified for SLF4J can be almost directly mapped to
39   * the levels that exist in the Google Android platform. The following table
40   * shows the mapping implemented by this logger.</p>
41   *
42   * <table border="1">
43   * <tr><th><b>SLF4J<b></th><th><b>Android</b></th></tr>
44   * <tr><td>TRACE</td><td>{@link android.util.Log#VERBOSE}</td></tr>
45   * <tr><td>DEBUG</td><td>{@link android.util.Log#DEBUG}</td></tr>
46   * <tr><td>INFO</td><td>{@link android.util.Log#INFO}</td></tr>
47   * <tr><td>WARN</td><td>{@link android.util.Log#WARN}</td></tr>
48   * <tr><td>ERROR</td><td>{@link android.util.Log#ERROR}</td></tr>
49   * </table>
50   *
51   * <p>Use loggers as usual:
52   * <ul>
53   *     <li>
54   *         Declare a logger<br/>
55   *         <code>private static final Logger logger = LoggerFactory.getLogger(MyClass.class);</code>
56   *     </li>
57   *     <li>
58   *         Invoke logging methods, e.g.,<br/>
59   *         <code>logger.debug("Some log message. Details: {}", someObject);</code><br/>
60   *         <code>logger.debug("Some log message with varargs. Details: {}, {}, {}", someObject1, someObject2, someObject3);</code>
61   *     </li>
62   * </ul>
63   * </p>
64   *
65   * <p>Logger instances created using the LoggerFactory are named either according to the name
66   * or the fully qualified class name of the class given as a parameter.
67   * Each logger name will be used as the log message tag on the Android platform.
68   * However, tag names cannot be longer than 23 characters so if logger name exceeds this limit then
69   * it will be truncated by the LoggerFactory. The following examples illustrate this.
70   * <table border="1">
71   * <tr><th><b>Original Name<b></th><th><b>Truncated Name</b></th></tr>
72   * <tr><td>org.example.myproject.mypackage.MyClass</td><td>o*.e*.m*.m*.MyClass</td></tr>
73   * <tr><td>o.e.myproject.mypackage.MyClass</td><td>o.e.m*.m*.MyClass</td></tr>
74   * <tr><td>org.example.ThisNameIsWayTooLongAndWillBeTruncated</td><td>*LongAndWillBeTruncated</td></tr>
75   * <tr><td>ThisNameIsWayTooLongAndWillBeTruncated</td><td>*LongAndWillBeTruncated</td></tr>
76   * </table>
77   * </p>
78   *
79   * @author Andrey Korzhevskiy <a.korzhevskiy@gmail.com>
80   */
81  class AndroidLoggerAdapter extends MarkerIgnoringBase {
82      private static final long serialVersionUID = -1227274521521287937L;
83  
84      /**
85       * Package access allows only {@link AndroidLoggerFactory} to instantiate
86       * SimpleLogger instances.
87       */
88      AndroidLoggerAdapter(String tag) {
89          this.name = tag;
90      }
91  
92      /**
93       * Is this logger instance enabled for the VERBOSE level?
94       *
95       * @return True if this Logger is enabled for level VERBOSE, false otherwise.
96       */
97      public boolean isTraceEnabled() {
98          return isLoggable(Log.VERBOSE);
99      }
100 
101     /**
102      * Log a message object at level VERBOSE.
103      *
104      * @param msg
105      *          - the message object to be logged
106      */
107     public void trace(String msg) {
108         log(Log.VERBOSE, msg, null);
109     }
110 
111     /**
112      * Log a message at level VERBOSE according to the specified format and
113      * argument.
114      *
115      * <p>
116      * This form avoids superfluous object creation when the logger is disabled
117      * for level VERBOSE.
118      * </p>
119      *
120      * @param format
121      *          the format string
122      * @param arg
123      *          the argument
124      */
125     public void trace(String format, Object arg) {
126         formatAndLog(Log.VERBOSE, format, arg);
127     }
128 
129     /**
130      * Log a message at level VERBOSE according to the specified format and
131      * arguments.
132      *
133      * <p>
134      * This form avoids superfluous object creation when the logger is disabled
135      * for the VERBOSE level.
136      * </p>
137      *
138      * @param format
139      *          the format string
140      * @param arg1
141      *          the first argument
142      * @param arg2
143      *          the second argument
144      */
145     public void trace(String format, Object arg1, Object arg2) {
146         formatAndLog(Log.VERBOSE, format, arg1, arg2);
147     }
148 
149     /**
150      * Log a message at level VERBOSE according to the specified format and
151      * arguments.
152      *
153      * <p>
154      * This form avoids superfluous object creation when the logger is disabled
155      * for the VERBOSE level.
156      * </p>
157      *
158      * @param format
159      *          the format string
160      * @param argArray
161      *          an array of arguments
162      */
163     public void trace(String format, Object... argArray) {
164         formatAndLog(Log.VERBOSE, format, argArray);
165     }
166 
167     /**
168      * Log an exception (throwable) at level VERBOSE with an accompanying message.
169      *
170      * @param msg
171      *          the message accompanying the exception
172      * @param t
173      *          the exception (throwable) to log
174      */
175     public void trace(String msg, Throwable t) {
176         log(Log.VERBOSE, msg, t);
177     }
178 
179     /**
180      * Is this logger instance enabled for the DEBUG level?
181      *
182      * @return True if this Logger is enabled for level DEBUG, false otherwise.
183      */
184     public boolean isDebugEnabled() {
185         return isLoggable(Log.DEBUG);
186     }
187 
188     /**
189      * Log a message object at level DEBUG.
190      *
191      * @param msg
192      *          - the message object to be logged
193      */
194     public void debug(String msg) {
195         log(Log.DEBUG, msg, null);
196     }
197 
198     /**
199      * Log a message at level DEBUG according to the specified format and argument.
200      *
201      * <p>
202      * This form avoids superfluous object creation when the logger is disabled
203      * for level DEBUG.
204      * </p>
205      *
206      * @param format
207      *          the format string
208      * @param arg
209      *          the argument
210      */
211     public void debug(String format, Object arg) {
212         formatAndLog(Log.DEBUG, format, arg);
213     }
214 
215     /**
216      * Log a message at level DEBUG according to the specified format and
217      * arguments.
218      *
219      * <p>
220      * This form avoids superfluous object creation when the logger is disabled
221      * for the DEBUG level.
222      * </p>
223      *
224      * @param format
225      *          the format string
226      * @param arg1
227      *          the first argument
228      * @param arg2
229      *          the second argument
230      */
231     public void debug(String format, Object arg1, Object arg2) {
232         formatAndLog(Log.DEBUG, format, arg1, arg2);
233     }
234 
235     /**
236      * Log a message at level DEBUG according to the specified format and
237      * arguments.
238      *
239      * <p>
240      * This form avoids superfluous object creation when the logger is disabled
241      * for the DEBUG level.
242      * </p>
243      *
244      * @param format
245      *          the format string
246      * @param argArray
247      *          an array of arguments
248      */
249     public void debug(String format, Object... argArray) {
250         formatAndLog(Log.DEBUG, format, argArray);
251     }
252 
253     /**
254      * Log an exception (throwable) at level DEBUG with an accompanying message.
255      *
256      * @param msg
257      *          the message accompanying the exception
258      * @param t
259      *          the exception (throwable) to log
260      */
261     public void debug(String msg, Throwable t) {
262         log(Log.VERBOSE, msg, t);
263     }
264 
265     /**
266      * Is this logger instance enabled for the INFO level?
267      *
268      * @return True if this Logger is enabled for the INFO level, false otherwise.
269      */
270     public boolean isInfoEnabled() {
271         return isLoggable(Log.INFO);
272     }
273 
274     /**
275      * Log a message object at the INFO level.
276      *
277      * @param msg
278      *          - the message object to be logged
279      */
280     public void info(String msg) {
281         log(Log.INFO, msg, null);
282     }
283 
284     /**
285      * Log a message at level INFO according to the specified format and argument.
286      *
287      * <p>
288      * This form avoids superfluous object creation when the logger is disabled
289      * for the INFO level.
290      * </p>
291      *
292      * @param format
293      *          the format string
294      * @param arg
295      *          the argument
296      */
297     public void info(String format, Object arg) {
298         formatAndLog(Log.INFO, format, arg);
299     }
300 
301     /**
302      * Log a message at the INFO level according to the specified format and
303      * arguments.
304      *
305      * <p>
306      * This form avoids superfluous object creation when the logger is disabled
307      * for the INFO level.
308      * </p>
309      *
310      * @param format
311      *          the format string
312      * @param arg1
313      *          the first argument
314      * @param arg2
315      *          the second argument
316      */
317     public void info(String format, Object arg1, Object arg2) {
318         formatAndLog(Log.INFO, format, arg1, arg2);
319     }
320 
321     /**
322      * Log a message at level INFO according to the specified format and
323      * arguments.
324      *
325      * <p>
326      * This form avoids superfluous object creation when the logger is disabled
327      * for the INFO level.
328      * </p>
329      *
330      * @param format
331      *          the format string
332      * @param argArray
333      *          an array of arguments
334      */
335     public void info(String format, Object... argArray) {
336         formatAndLog(Log.INFO, format, argArray);
337     }
338 
339     /**
340      * Log an exception (throwable) at the INFO level with an accompanying
341      * message.
342      *
343      * @param msg
344      *          the message accompanying the exception
345      * @param t
346      *          the exception (throwable) to log
347      */
348     public void info(String msg, Throwable t) {
349         log(Log.INFO, msg, t);
350     }
351 
352     /**
353      * Is this logger instance enabled for the WARN level?
354      *
355      * @return True if this Logger is enabled for the WARN level, false
356      *         otherwise.
357      */
358     public boolean isWarnEnabled() {
359         return isLoggable(Log.WARN);
360     }
361 
362     /**
363      * Log a message object at the WARN level.
364      *
365      * @param msg
366      *          - the message object to be logged
367      */
368     public void warn(String msg) {
369         log(Log.WARN, msg, null);
370     }
371 
372     /**
373      * Log a message at the WARN level according to the specified format and
374      * argument.
375      *
376      * <p>
377      * This form avoids superfluous object creation when the logger is disabled
378      * for the WARN level.
379      * </p>
380      *
381      * @param format
382      *          the format string
383      * @param arg
384      *          the argument
385      */
386     public void warn(String format, Object arg) {
387         formatAndLog(Log.WARN, format, arg);
388     }
389 
390     /**
391      * Log a message at the WARN level according to the specified format and
392      * arguments.
393      *
394      * <p>
395      * This form avoids superfluous object creation when the logger is disabled
396      * for the WARN level.
397      * </p>
398      *
399      * @param format
400      *          the format string
401      * @param arg1
402      *          the first argument
403      * @param arg2
404      *          the second argument
405      */
406     public void warn(String format, Object arg1, Object arg2) {
407         formatAndLog(Log.WARN, format, arg1, arg2);
408     }
409 
410     /**
411      * Log a message at level WARN according to the specified format and
412      * arguments.
413      *
414      * <p>
415      * This form avoids superfluous object creation when the logger is disabled
416      * for the WARN level.
417      * </p>
418      *
419      * @param format
420      *          the format string
421      * @param argArray
422      *          an array of arguments
423      */
424     public void warn(String format, Object... argArray) {
425         formatAndLog(Log.WARN, format, argArray);
426     }
427 
428     /**
429      * Log an exception (throwable) at the WARN level with an accompanying
430      * message.
431      *
432      * @param msg
433      *          the message accompanying the exception
434      * @param t
435      *          the exception (throwable) to log
436      */
437     public void warn(String msg, Throwable t) {
438         log(Log.WARN, msg, t);
439     }
440 
441     /**
442      * Is this logger instance enabled for level ERROR?
443      *
444      * @return True if this Logger is enabled for level ERROR, false otherwise.
445      */
446     public boolean isErrorEnabled() {
447         return isLoggable(Log.ERROR);
448     }
449 
450     /**
451      * Log a message object at the ERROR level.
452      *
453      * @param msg
454      *          - the message object to be logged
455      */
456     public void error(String msg) {
457         log(Log.ERROR, msg, null);
458     }
459 
460     /**
461      * Log a message at the ERROR level according to the specified format and
462      * argument.
463      *
464      * <p>
465      * This form avoids superfluous object creation when the logger is disabled
466      * for the ERROR level.
467      * </p>
468      *
469      * @param format
470      *          the format string
471      * @param arg
472      *          the argument
473      */
474     public void error(String format, Object arg) {
475         formatAndLog(Log.ERROR, format, arg);
476     }
477 
478     /**
479      * Log a message at the ERROR level according to the specified format and
480      * arguments.
481      *
482      * <p>
483      * This form avoids superfluous object creation when the logger is disabled
484      * for the ERROR level.
485      * </p>
486      *
487      * @param format
488      *          the format string
489      * @param arg1
490      *          the first argument
491      * @param arg2
492      *          the second argument
493      */
494     public void error(String format, Object arg1, Object arg2) {
495         formatAndLog(Log.ERROR, format, arg1, arg2);
496     }
497 
498     /**
499      * Log a message at level ERROR according to the specified format and
500      * arguments.
501      *
502      * <p>
503      * This form avoids superfluous object creation when the logger is disabled
504      * for the ERROR level.
505      * </p>
506      *
507      * @param format
508      *          the format string
509      * @param argArray
510      *          an array of arguments
511      */
512     public void error(String format, Object... argArray) {
513         formatAndLog(Log.ERROR, format, argArray);
514     }
515 
516     /**
517      * Log an exception (throwable) at the ERROR level with an accompanying
518      * message.
519      *
520      * @param msg
521      *          the message accompanying the exception
522      * @param t
523      *          the exception (throwable) to log
524      */
525     public void error(String msg, Throwable t) {
526         log(Log.ERROR, msg, t);
527     }
528 
529     private void formatAndLog(int priority, String format, Object... argArray) {
530         if (isLoggable(priority)) {
531             FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
532             logInternal(priority, ft.getMessage(), ft.getThrowable());
533         }
534     }
535 
536     private void log(int priority, String message, Throwable throwable) {
537         if (isLoggable(priority)) {
538             logInternal(priority, message, throwable);
539         }
540     }
541 
542     private boolean isLoggable(int priority) {
543         return Log.isLoggable(name, priority);
544     }
545 
546     private void logInternal(int priority, String message, Throwable throwable) {
547         if (throwable != null) {
548             message += '\n' + Log.getStackTraceString(throwable);
549         }
550         Log.println(priority, name, message);
551     }
552 }