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     /**
86      * Package access allows only {@link AndroidLoggerFactory} to instantiate
87      * SimpleLogger instances.
88      */
AndroidLoggerAdapter(String tag)89     AndroidLoggerAdapter(String tag) {
90         this.name = tag;
91     }
92 
93     /**
94      * Is this logger instance enabled for the VERBOSE level?
95      *
96      * @return True if this Logger is enabled for level VERBOSE, false otherwise.
97      */
isTraceEnabled()98     public boolean isTraceEnabled() {
99         return isLoggable(Log.VERBOSE);
100     }
101 
102     /**
103      * Log a message object at level VERBOSE.
104      *
105      * @param msg
106      *          - the message object to be logged
107      */
trace(String msg)108     public void trace(String msg) {
109         log(Log.VERBOSE, msg, null);
110     }
111 
112     /**
113      * Log a message at level VERBOSE according to the specified format and
114      * argument.
115      *
116      * <p>
117      * This form avoids superfluous object creation when the logger is disabled
118      * for level VERBOSE.
119      * </p>
120      *
121      * @param format
122      *          the format string
123      * @param arg
124      *          the argument
125      */
trace(String format, Object arg)126     public void trace(String format, Object arg) {
127         formatAndLog(Log.VERBOSE, format, arg);
128     }
129 
130     /**
131      * Log a message at level VERBOSE according to the specified format and
132      * arguments.
133      *
134      * <p>
135      * This form avoids superfluous object creation when the logger is disabled
136      * for the VERBOSE level.
137      * </p>
138      *
139      * @param format
140      *          the format string
141      * @param arg1
142      *          the first argument
143      * @param arg2
144      *          the second argument
145      */
trace(String format, Object arg1, Object arg2)146     public void trace(String format, Object arg1, Object arg2) {
147         formatAndLog(Log.VERBOSE, format, arg1, arg2);
148     }
149 
150     /**
151      * Log a message at level VERBOSE according to the specified format and
152      * arguments.
153      *
154      * <p>
155      * This form avoids superfluous object creation when the logger is disabled
156      * for the VERBOSE level.
157      * </p>
158      *
159      * @param format
160      *          the format string
161      * @param argArray
162      *          an array of arguments
163      */
trace(String format, Object... argArray)164     public void trace(String format, Object... argArray) {
165         formatAndLog(Log.VERBOSE, format, argArray);
166     }
167 
168     /**
169      * Log an exception (throwable) at level VERBOSE with an accompanying message.
170      *
171      * @param msg
172      *          the message accompanying the exception
173      * @param t
174      *          the exception (throwable) to log
175      */
trace(String msg, Throwable t)176     public void trace(String msg, Throwable t) {
177         log(Log.VERBOSE, msg, t);
178     }
179 
180     /**
181      * Is this logger instance enabled for the DEBUG level?
182      *
183      * @return True if this Logger is enabled for level DEBUG, false otherwise.
184      */
isDebugEnabled()185     public boolean isDebugEnabled() {
186         return isLoggable(Log.DEBUG);
187     }
188 
189     /**
190      * Log a message object at level DEBUG.
191      *
192      * @param msg
193      *          - the message object to be logged
194      */
debug(String msg)195     public void debug(String msg) {
196         log(Log.DEBUG, msg, null);
197     }
198 
199     /**
200      * Log a message at level DEBUG according to the specified format and argument.
201      *
202      * <p>
203      * This form avoids superfluous object creation when the logger is disabled
204      * for level DEBUG.
205      * </p>
206      *
207      * @param format
208      *          the format string
209      * @param arg
210      *          the argument
211      */
debug(String format, Object arg)212     public void debug(String format, Object arg) {
213         formatAndLog(Log.DEBUG, format, arg);
214     }
215 
216     /**
217      * Log a message at level DEBUG according to the specified format and
218      * arguments.
219      *
220      * <p>
221      * This form avoids superfluous object creation when the logger is disabled
222      * for the DEBUG level.
223      * </p>
224      *
225      * @param format
226      *          the format string
227      * @param arg1
228      *          the first argument
229      * @param arg2
230      *          the second argument
231      */
debug(String format, Object arg1, Object arg2)232     public void debug(String format, Object arg1, Object arg2) {
233         formatAndLog(Log.DEBUG, format, arg1, arg2);
234     }
235 
236     /**
237      * Log a message at level DEBUG according to the specified format and
238      * arguments.
239      *
240      * <p>
241      * This form avoids superfluous object creation when the logger is disabled
242      * for the DEBUG level.
243      * </p>
244      *
245      * @param format
246      *          the format string
247      * @param argArray
248      *          an array of arguments
249      */
debug(String format, Object... argArray)250     public void debug(String format, Object... argArray) {
251         formatAndLog(Log.DEBUG, format, argArray);
252     }
253 
254     /**
255      * Log an exception (throwable) at level DEBUG with an accompanying message.
256      *
257      * @param msg
258      *          the message accompanying the exception
259      * @param t
260      *          the exception (throwable) to log
261      */
debug(String msg, Throwable t)262     public void debug(String msg, Throwable t) {
263         log(Log.VERBOSE, msg, t);
264     }
265 
266     /**
267      * Is this logger instance enabled for the INFO level?
268      *
269      * @return True if this Logger is enabled for the INFO level, false otherwise.
270      */
isInfoEnabled()271     public boolean isInfoEnabled() {
272         return isLoggable(Log.INFO);
273     }
274 
275     /**
276      * Log a message object at the INFO level.
277      *
278      * @param msg
279      *          - the message object to be logged
280      */
info(String msg)281     public void info(String msg) {
282         log(Log.INFO, msg, null);
283     }
284 
285     /**
286      * Log a message at level INFO according to the specified format and argument.
287      *
288      * <p>
289      * This form avoids superfluous object creation when the logger is disabled
290      * for the INFO level.
291      * </p>
292      *
293      * @param format
294      *          the format string
295      * @param arg
296      *          the argument
297      */
info(String format, Object arg)298     public void info(String format, Object arg) {
299         formatAndLog(Log.INFO, format, arg);
300     }
301 
302     /**
303      * Log a message at the INFO level according to the specified format and
304      * arguments.
305      *
306      * <p>
307      * This form avoids superfluous object creation when the logger is disabled
308      * for the INFO level.
309      * </p>
310      *
311      * @param format
312      *          the format string
313      * @param arg1
314      *          the first argument
315      * @param arg2
316      *          the second argument
317      */
info(String format, Object arg1, Object arg2)318     public void info(String format, Object arg1, Object arg2) {
319         formatAndLog(Log.INFO, format, arg1, arg2);
320     }
321 
322     /**
323      * Log a message at level INFO according to the specified format and
324      * arguments.
325      *
326      * <p>
327      * This form avoids superfluous object creation when the logger is disabled
328      * for the INFO level.
329      * </p>
330      *
331      * @param format
332      *          the format string
333      * @param argArray
334      *          an array of arguments
335      */
info(String format, Object... argArray)336     public void info(String format, Object... argArray) {
337         formatAndLog(Log.INFO, format, argArray);
338     }
339 
340     /**
341      * Log an exception (throwable) at the INFO level with an accompanying
342      * message.
343      *
344      * @param msg
345      *          the message accompanying the exception
346      * @param t
347      *          the exception (throwable) to log
348      */
info(String msg, Throwable t)349     public void info(String msg, Throwable t) {
350         log(Log.INFO, msg, t);
351     }
352 
353     /**
354      * Is this logger instance enabled for the WARN level?
355      *
356      * @return True if this Logger is enabled for the WARN level, false
357      *         otherwise.
358      */
isWarnEnabled()359     public boolean isWarnEnabled() {
360         return isLoggable(Log.WARN);
361     }
362 
363     /**
364      * Log a message object at the WARN level.
365      *
366      * @param msg
367      *          - the message object to be logged
368      */
warn(String msg)369     public void warn(String msg) {
370         log(Log.WARN, msg, null);
371     }
372 
373     /**
374      * Log a message at the WARN level according to the specified format and
375      * argument.
376      *
377      * <p>
378      * This form avoids superfluous object creation when the logger is disabled
379      * for the WARN level.
380      * </p>
381      *
382      * @param format
383      *          the format string
384      * @param arg
385      *          the argument
386      */
warn(String format, Object arg)387     public void warn(String format, Object arg) {
388         formatAndLog(Log.WARN, format, arg);
389     }
390 
391     /**
392      * Log a message at the WARN level according to the specified format and
393      * arguments.
394      *
395      * <p>
396      * This form avoids superfluous object creation when the logger is disabled
397      * for the WARN level.
398      * </p>
399      *
400      * @param format
401      *          the format string
402      * @param arg1
403      *          the first argument
404      * @param arg2
405      *          the second argument
406      */
warn(String format, Object arg1, Object arg2)407     public void warn(String format, Object arg1, Object arg2) {
408         formatAndLog(Log.WARN, format, arg1, arg2);
409     }
410 
411     /**
412      * Log a message at level WARN according to the specified format and
413      * arguments.
414      *
415      * <p>
416      * This form avoids superfluous object creation when the logger is disabled
417      * for the WARN level.
418      * </p>
419      *
420      * @param format
421      *          the format string
422      * @param argArray
423      *          an array of arguments
424      */
warn(String format, Object... argArray)425     public void warn(String format, Object... argArray) {
426         formatAndLog(Log.WARN, format, argArray);
427     }
428 
429     /**
430      * Log an exception (throwable) at the WARN level with an accompanying
431      * message.
432      *
433      * @param msg
434      *          the message accompanying the exception
435      * @param t
436      *          the exception (throwable) to log
437      */
warn(String msg, Throwable t)438     public void warn(String msg, Throwable t) {
439         log(Log.WARN, msg, t);
440     }
441 
442     /**
443      * Is this logger instance enabled for level ERROR?
444      *
445      * @return True if this Logger is enabled for level ERROR, false otherwise.
446      */
isErrorEnabled()447     public boolean isErrorEnabled() {
448         return isLoggable(Log.ERROR);
449     }
450 
451     /**
452      * Log a message object at the ERROR level.
453      *
454      * @param msg
455      *          - the message object to be logged
456      */
error(String msg)457     public void error(String msg) {
458         log(Log.ERROR, msg, null);
459     }
460 
461     /**
462      * Log a message at the ERROR level according to the specified format and
463      * argument.
464      *
465      * <p>
466      * This form avoids superfluous object creation when the logger is disabled
467      * for the ERROR level.
468      * </p>
469      *
470      * @param format
471      *          the format string
472      * @param arg
473      *          the argument
474      */
error(String format, Object arg)475     public void error(String format, Object arg) {
476         formatAndLog(Log.ERROR, format, arg);
477     }
478 
479     /**
480      * Log a message at the ERROR level according to the specified format and
481      * arguments.
482      *
483      * <p>
484      * This form avoids superfluous object creation when the logger is disabled
485      * for the ERROR level.
486      * </p>
487      *
488      * @param format
489      *          the format string
490      * @param arg1
491      *          the first argument
492      * @param arg2
493      *          the second argument
494      */
error(String format, Object arg1, Object arg2)495     public void error(String format, Object arg1, Object arg2) {
496         formatAndLog(Log.ERROR, format, arg1, arg2);
497     }
498 
499     /**
500      * Log a message at level ERROR according to the specified format and
501      * arguments.
502      *
503      * <p>
504      * This form avoids superfluous object creation when the logger is disabled
505      * for the ERROR level.
506      * </p>
507      *
508      * @param format
509      *          the format string
510      * @param argArray
511      *          an array of arguments
512      */
error(String format, Object... argArray)513     public void error(String format, Object... argArray) {
514         formatAndLog(Log.ERROR, format, argArray);
515     }
516 
517     /**
518      * Log an exception (throwable) at the ERROR level with an accompanying
519      * message.
520      *
521      * @param msg
522      *          the message accompanying the exception
523      * @param t
524      *          the exception (throwable) to log
525      */
error(String msg, Throwable t)526     public void error(String msg, Throwable t) {
527         log(Log.ERROR, msg, t);
528     }
529 
formatAndLog(int priority, String format, Object... argArray)530     private void formatAndLog(int priority, String format, Object... argArray) {
531         if (isLoggable(priority)) {
532             FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
533             _log(priority, ft.getMessage(), ft.getThrowable());
534         }
535     }
536 
log(int priority, String message, Throwable throwable)537     private void log(int priority, String message, Throwable throwable) {
538         if (isLoggable(priority)) {
539             _log(priority, message, throwable);
540         }
541     }
542 
isLoggable(int priority)543     private boolean isLoggable(int priority) {
544         return Log.isLoggable(name, priority);
545     }
546 
_log(int priority, String message, Throwable throwable)547     private void _log(int priority, String message, Throwable throwable) {
548         if (throwable != null) {
549             message += '\n' + Log.getStackTraceString(throwable);
550         }
551         Log.println(priority, name, message);
552     }
553 }