Home | History | Annotate | Download | only in utils
      1 /**
      2  * Copyright (c) 2011, Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.mail.utils;
     17 
     18 import android.net.Uri;
     19 import android.text.TextUtils;
     20 import android.util.Log;
     21 
     22 import com.google.common.annotations.VisibleForTesting;
     23 
     24 import java.util.List;
     25 import java.util.regex.Pattern;
     26 
     27 public class LogUtils {
     28 
     29     public static final String TAG = LogTag.getLogTag();
     30 
     31     // "GMT" + "+" or "-" + 4 digits
     32     private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE =
     33             Pattern.compile("GMT([-+]\\d{4})$");
     34 
     35     private static final String ACCOUNT_PREFIX = "account:";
     36 
     37     /**
     38      * Priority constant for the println method; use LogUtils.v.
     39      */
     40     public static final int VERBOSE = Log.VERBOSE;
     41 
     42     /**
     43      * Priority constant for the println method; use LogUtils.d.
     44      */
     45     public static final int DEBUG = Log.DEBUG;
     46 
     47     /**
     48      * Priority constant for the println method; use LogUtils.i.
     49      */
     50     public static final int INFO = Log.INFO;
     51 
     52     /**
     53      * Priority constant for the println method; use LogUtils.w.
     54      */
     55     public static final int WARN = Log.WARN;
     56 
     57     /**
     58      * Priority constant for the println method; use LogUtils.e.
     59      */
     60     public static final int ERROR = Log.ERROR;
     61 
     62     /**
     63      * Used to enable/disable logging that we don't want included in
     64      * production releases.  This should be set to DEBUG for production releases, and VERBOSE for
     65      * internal builds.
     66      */
     67     private static final int MAX_ENABLED_LOG_LEVEL = DEBUG;
     68 
     69     private static Boolean sDebugLoggingEnabledForTests = null;
     70 
     71     /**
     72      * Enable debug logging for unit tests.
     73      */
     74     @VisibleForTesting
     75     public static void setDebugLoggingEnabledForTests(boolean enabled) {
     76         setDebugLoggingEnabledForTestsInternal(enabled);
     77     }
     78 
     79     protected static void setDebugLoggingEnabledForTestsInternal(boolean enabled) {
     80         sDebugLoggingEnabledForTests = Boolean.valueOf(enabled);
     81     }
     82 
     83     /**
     84      * Returns true if the build configuration prevents debug logging.
     85      */
     86     @VisibleForTesting
     87     public static boolean buildPreventsDebugLogging() {
     88         return MAX_ENABLED_LOG_LEVEL > VERBOSE;
     89     }
     90 
     91     /**
     92      * Returns a boolean indicating whether debug logging is enabled.
     93      */
     94     protected static boolean isDebugLoggingEnabled(String tag) {
     95         if (buildPreventsDebugLogging()) {
     96             return false;
     97         }
     98         if (sDebugLoggingEnabledForTests != null) {
     99             return sDebugLoggingEnabledForTests.booleanValue();
    100         }
    101         return Log.isLoggable(tag, Log.DEBUG) || Log.isLoggable(TAG, Log.DEBUG);
    102     }
    103 
    104     /**
    105      * Returns a String for the specified content provider uri.  This will do
    106      * sanitation of the uri to remove PII if debug logging is not enabled.
    107      */
    108     public static String contentUriToString(final Uri uri) {
    109         return contentUriToString(TAG, uri);
    110     }
    111 
    112     /**
    113      * Returns a String for the specified content provider uri.  This will do
    114      * sanitation of the uri to remove PII if debug logging is not enabled.
    115      */
    116     public static String contentUriToString(String tag, Uri uri) {
    117         if (isDebugLoggingEnabled(tag)) {
    118             // Debug logging has been enabled, so log the uri as is
    119             return uri.toString();
    120         } else {
    121             // Debug logging is not enabled, we want to remove the email address from the uri.
    122             List<String> pathSegments = uri.getPathSegments();
    123 
    124             Uri.Builder builder = new Uri.Builder()
    125                     .scheme(uri.getScheme())
    126                     .authority(uri.getAuthority())
    127                     .query(uri.getQuery())
    128                     .fragment(uri.getFragment());
    129 
    130             // This assumes that the first path segment is the account
    131             final String account = pathSegments.get(0);
    132 
    133             builder = builder.appendPath(sanitizeAccountName(account));
    134             for (int i = 1; i < pathSegments.size(); i++) {
    135                 builder.appendPath(pathSegments.get(i));
    136             }
    137             return builder.toString();
    138         }
    139     }
    140 
    141     /**
    142      * Sanitizes an account name.  If debug logging is not enabled, a sanitized name
    143      * is returned.
    144      */
    145     public static String sanitizeAccountName(String accountName) {
    146         if (TextUtils.isEmpty(accountName)) {
    147             return "";
    148         }
    149 
    150         return ACCOUNT_PREFIX + sanitizeName(TAG, accountName);
    151     }
    152 
    153     public static String sanitizeName(final String tag, final String name) {
    154         if (TextUtils.isEmpty(name)) {
    155             return "";
    156         }
    157 
    158         if (isDebugLoggingEnabled(tag)) {
    159             return name;
    160         }
    161 
    162         return String.valueOf(name.hashCode());
    163     }
    164 
    165     /**
    166      * Checks to see whether or not a log for the specified tag is loggable at the specified level.
    167      */
    168     public static boolean isLoggable(String tag, int level) {
    169         if (MAX_ENABLED_LOG_LEVEL > level) {
    170             return false;
    171         }
    172         return Log.isLoggable(tag, level) || Log.isLoggable(TAG, level);
    173     }
    174 
    175     /**
    176      * Send a {@link #VERBOSE} log message.
    177      * @param tag Used to identify the source of a log message.  It usually identifies
    178      *        the class or activity where the log call occurs.
    179      * @param format the format string (see {@link java.util.Formatter#format})
    180      * @param args
    181      *            the list of arguments passed to the formatter. If there are
    182      *            more arguments than required by {@code format},
    183      *            additional arguments are ignored.
    184      */
    185     public static int v(String tag, String format, Object... args) {
    186         if (isLoggable(tag, VERBOSE)) {
    187             return Log.v(tag, String.format(format, args));
    188         }
    189         return 0;
    190     }
    191 
    192     /**
    193      * Send a {@link #VERBOSE} log message.
    194      * @param tag Used to identify the source of a log message.  It usually identifies
    195      *        the class or activity where the log call occurs.
    196      * @param tr An exception to log
    197      * @param format the format string (see {@link java.util.Formatter#format})
    198      * @param args
    199      *            the list of arguments passed to the formatter. If there are
    200      *            more arguments than required by {@code format},
    201      *            additional arguments are ignored.
    202      */
    203     public static int v(String tag, Throwable tr, String format, Object... args) {
    204         if (isLoggable(tag, VERBOSE)) {
    205             return Log.v(tag, String.format(format, args), tr);
    206         }
    207         return 0;
    208     }
    209 
    210     /**
    211      * Send a {@link #DEBUG} log message.
    212      * @param tag Used to identify the source of a log message.  It usually identifies
    213      *        the class or activity where the log call occurs.
    214      * @param format the format string (see {@link java.util.Formatter#format})
    215      * @param args
    216      *            the list of arguments passed to the formatter. If there are
    217      *            more arguments than required by {@code format},
    218      *            additional arguments are ignored.
    219      */
    220     public static int d(String tag, String format, Object... args) {
    221         if (isLoggable(tag, DEBUG)) {
    222             return Log.d(tag, String.format(format, args));
    223         }
    224         return 0;
    225     }
    226 
    227     /**
    228      * Send a {@link #DEBUG} log message.
    229      * @param tag Used to identify the source of a log message.  It usually identifies
    230      *        the class or activity where the log call occurs.
    231      * @param tr An exception to log
    232      * @param format the format string (see {@link java.util.Formatter#format})
    233      * @param args
    234      *            the list of arguments passed to the formatter. If there are
    235      *            more arguments than required by {@code format},
    236      *            additional arguments are ignored.
    237      */
    238     public static int d(String tag, Throwable tr, String format, Object... args) {
    239         if (isLoggable(tag, DEBUG)) {
    240             return Log.d(tag, String.format(format, args), tr);
    241         }
    242         return 0;
    243     }
    244 
    245     /**
    246      * Send a {@link #INFO} log message.
    247      * @param tag Used to identify the source of a log message.  It usually identifies
    248      *        the class or activity where the log call occurs.
    249      * @param format the format string (see {@link java.util.Formatter#format})
    250      * @param args
    251      *            the list of arguments passed to the formatter. If there are
    252      *            more arguments than required by {@code format},
    253      *            additional arguments are ignored.
    254      */
    255     public static int i(String tag, String format, Object... args) {
    256         if (isLoggable(tag, INFO)) {
    257             return Log.i(tag, String.format(format, args));
    258         }
    259         return 0;
    260     }
    261 
    262     /**
    263      * Send a {@link #INFO} log message.
    264      * @param tag Used to identify the source of a log message.  It usually identifies
    265      *        the class or activity where the log call occurs.
    266      * @param tr An exception to log
    267      * @param format the format string (see {@link java.util.Formatter#format})
    268      * @param args
    269      *            the list of arguments passed to the formatter. If there are
    270      *            more arguments than required by {@code format},
    271      *            additional arguments are ignored.
    272      */
    273     public static int i(String tag, Throwable tr, String format, Object... args) {
    274         if (isLoggable(tag, INFO)) {
    275             return Log.i(tag, String.format(format, args), tr);
    276         }
    277         return 0;
    278     }
    279 
    280     /**
    281      * Send a {@link #WARN} log message.
    282      * @param tag Used to identify the source of a log message.  It usually identifies
    283      *        the class or activity where the log call occurs.
    284      * @param format the format string (see {@link java.util.Formatter#format})
    285      * @param args
    286      *            the list of arguments passed to the formatter. If there are
    287      *            more arguments than required by {@code format},
    288      *            additional arguments are ignored.
    289      */
    290     public static int w(String tag, String format, Object... args) {
    291         if (isLoggable(tag, WARN)) {
    292             return Log.w(tag, String.format(format, args));
    293         }
    294         return 0;
    295     }
    296 
    297     /**
    298      * Send a {@link #WARN} log message.
    299      * @param tag Used to identify the source of a log message.  It usually identifies
    300      *        the class or activity where the log call occurs.
    301      * @param tr An exception to log
    302      * @param format the format string (see {@link java.util.Formatter#format})
    303      * @param args
    304      *            the list of arguments passed to the formatter. If there are
    305      *            more arguments than required by {@code format},
    306      *            additional arguments are ignored.
    307      */
    308     public static int w(String tag, Throwable tr, String format, Object... args) {
    309         if (isLoggable(tag, WARN)) {
    310             return Log.w(tag, String.format(format, args), tr);
    311         }
    312         return 0;
    313     }
    314 
    315     /**
    316      * Send a {@link #ERROR} log message.
    317      * @param tag Used to identify the source of a log message.  It usually identifies
    318      *        the class or activity where the log call occurs.
    319      * @param format the format string (see {@link java.util.Formatter#format})
    320      * @param args
    321      *            the list of arguments passed to the formatter. If there are
    322      *            more arguments than required by {@code format},
    323      *            additional arguments are ignored.
    324      */
    325     public static int e(String tag, String format, Object... args) {
    326         if (isLoggable(tag, ERROR)) {
    327             return Log.e(tag, String.format(format, args));
    328         }
    329         return 0;
    330     }
    331 
    332     /**
    333      * Send a {@link #ERROR} log message.
    334      * @param tag Used to identify the source of a log message.  It usually identifies
    335      *        the class or activity where the log call occurs.
    336      * @param tr An exception to log
    337      * @param format the format string (see {@link java.util.Formatter#format})
    338      * @param args
    339      *            the list of arguments passed to the formatter. If there are
    340      *            more arguments than required by {@code format},
    341      *            additional arguments are ignored.
    342      */
    343     public static int e(String tag, Throwable tr, String format, Object... args) {
    344         if (isLoggable(tag, ERROR)) {
    345             return Log.e(tag, String.format(format, args), tr);
    346         }
    347         return 0;
    348     }
    349 
    350     /**
    351      * What a Terrible Failure: Report a condition that should never happen.
    352      * The error will always be logged at level ASSERT with the call stack.
    353      * Depending on system configuration, a report may be added to the
    354      * {@link android.os.DropBoxManager} and/or the process may be terminated
    355      * immediately with an error dialog.
    356      * @param tag Used to identify the source of a log message.  It usually identifies
    357      *        the class or activity where the log call occurs.
    358      * @param format the format string (see {@link java.util.Formatter#format})
    359      * @param args
    360      *            the list of arguments passed to the formatter. If there are
    361      *            more arguments than required by {@code format},
    362      *            additional arguments are ignored.
    363      */
    364     public static int wtf(String tag, String format, Object... args) {
    365         return Log.wtf(tag, String.format(format, args), new Error());
    366     }
    367 
    368     /**
    369      * What a Terrible Failure: Report a condition that should never happen.
    370      * The error will always be logged at level ASSERT with the call stack.
    371      * Depending on system configuration, a report may be added to the
    372      * {@link android.os.DropBoxManager} and/or the process may be terminated
    373      * immediately with an error dialog.
    374      * @param tag Used to identify the source of a log message.  It usually identifies
    375      *        the class or activity where the log call occurs.
    376      * @param tr An exception to log
    377      * @param format the format string (see {@link java.util.Formatter#format})
    378      * @param args
    379      *            the list of arguments passed to the formatter. If there are
    380      *            more arguments than required by {@code format},
    381      *            additional arguments are ignored.
    382      */
    383     public static int wtf(String tag, Throwable tr, String format, Object... args) {
    384         return Log.wtf(tag, String.format(format, args), tr);
    385     }
    386 
    387 
    388     /**
    389      * Try to make a date MIME(RFC 2822/5322)-compliant.
    390      *
    391      * It fixes:
    392      * - "Thu, 10 Dec 09 15:08:08 GMT-0700" to "Thu, 10 Dec 09 15:08:08 -0700"
    393      *   (4 digit zone value can't be preceded by "GMT")
    394      *   We got a report saying eBay sends a date in this format
    395      */
    396     public static String cleanUpMimeDate(String date) {
    397         if (TextUtils.isEmpty(date)) {
    398             return date;
    399         }
    400         date = DATE_CLEANUP_PATTERN_WRONG_TIMEZONE.matcher(date).replaceFirst("$1");
    401         return date;
    402     }
    403 
    404 
    405     public static String byteToHex(int b) {
    406         return byteToHex(new StringBuilder(), b).toString();
    407     }
    408 
    409     public static StringBuilder byteToHex(StringBuilder sb, int b) {
    410         b &= 0xFF;
    411         sb.append("0123456789ABCDEF".charAt(b >> 4));
    412         sb.append("0123456789ABCDEF".charAt(b & 0xF));
    413         return sb;
    414     }
    415 
    416 }
    417