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     // STOPSHIP: ship with DEBUG set
     68     private static final int MAX_ENABLED_LOG_LEVEL = VERBOSE;
     69 
     70     private static Boolean sDebugLoggingEnabledForTests = null;
     71 
     72     /**
     73      * Enable debug logging for unit tests.
     74      */
     75     @VisibleForTesting
     76     public static void setDebugLoggingEnabledForTests(boolean enabled) {
     77         setDebugLoggingEnabledForTestsInternal(enabled);
     78     }
     79 
     80     protected static void setDebugLoggingEnabledForTestsInternal(boolean enabled) {
     81         sDebugLoggingEnabledForTests = Boolean.valueOf(enabled);
     82     }
     83 
     84     /**
     85      * Returns true if the build configuration prevents debug logging.
     86      */
     87     @VisibleForTesting
     88     public static boolean buildPreventsDebugLogging() {
     89         return MAX_ENABLED_LOG_LEVEL > VERBOSE;
     90     }
     91 
     92     /**
     93      * Returns a boolean indicating whether debug logging is enabled.
     94      */
     95     protected static boolean isDebugLoggingEnabled(String tag) {
     96         if (buildPreventsDebugLogging()) {
     97             return false;
     98         }
     99         if (sDebugLoggingEnabledForTests != null) {
    100             return sDebugLoggingEnabledForTests.booleanValue();
    101         }
    102         return Log.isLoggable(tag, Log.DEBUG) || Log.isLoggable(TAG, Log.DEBUG);
    103     }
    104 
    105     /**
    106      * Returns a String for the specified content provider uri.  This will do
    107      * sanitation of the uri to remove PII if debug logging is not enabled.
    108      */
    109     public static String contentUriToString(final Uri uri) {
    110         return contentUriToString(TAG, uri);
    111     }
    112 
    113     /**
    114      * Returns a String for the specified content provider uri.  This will do
    115      * sanitation of the uri to remove PII if debug logging is not enabled.
    116      */
    117     public static String contentUriToString(String tag, Uri uri) {
    118         if (isDebugLoggingEnabled(tag)) {
    119             // Debug logging has been enabled, so log the uri as is
    120             return uri.toString();
    121         } else {
    122             // Debug logging is not enabled, we want to remove the email address from the uri.
    123             List<String> pathSegments = uri.getPathSegments();
    124 
    125             Uri.Builder builder = new Uri.Builder()
    126                     .scheme(uri.getScheme())
    127                     .authority(uri.getAuthority())
    128                     .query(uri.getQuery())
    129                     .fragment(uri.getFragment());
    130 
    131             // This assumes that the first path segment is the account
    132             final String account = pathSegments.get(0);
    133 
    134             builder = builder.appendPath(sanitizeAccountName(account));
    135             for (int i = 1; i < pathSegments.size(); i++) {
    136                 builder.appendPath(pathSegments.get(i));
    137             }
    138             return builder.toString();
    139         }
    140     }
    141 
    142     /**
    143      * Sanitizes an account name.  If debug logging is not enabled, a sanitized name
    144      * is returned.
    145      */
    146     public static String sanitizeAccountName(String accountName) {
    147         if (TextUtils.isEmpty(accountName)) {
    148             return "";
    149         }
    150 
    151         return ACCOUNT_PREFIX + sanitizeName(TAG, accountName);
    152     }
    153 
    154     public static String sanitizeName(final String tag, final String name) {
    155         if (TextUtils.isEmpty(name)) {
    156             return "";
    157         }
    158 
    159         if (isDebugLoggingEnabled(tag)) {
    160             return name;
    161         }
    162 
    163         return String.valueOf(name.hashCode());
    164     }
    165 
    166     /**
    167      * Checks to see whether or not a log for the specified tag is loggable at the specified level.
    168      */
    169     public static boolean isLoggable(String tag, int level) {
    170         if (MAX_ENABLED_LOG_LEVEL > level) {
    171             return false;
    172         }
    173         return Log.isLoggable(tag, level) || Log.isLoggable(TAG, level);
    174     }
    175 
    176     /**
    177      * Send a {@link #VERBOSE} log message.
    178      * @param tag Used to identify the source of a log message.  It usually identifies
    179      *        the class or activity where the log call occurs.
    180      * @param format the format string (see {@link java.util.Formatter#format})
    181      * @param args
    182      *            the list of arguments passed to the formatter. If there are
    183      *            more arguments than required by {@code format},
    184      *            additional arguments are ignored.
    185      */
    186     public static int v(String tag, String format, Object... args) {
    187         if (isLoggable(tag, VERBOSE)) {
    188             return Log.v(tag, String.format(format, args));
    189         }
    190         return 0;
    191     }
    192 
    193     /**
    194      * Send a {@link #VERBOSE} log message.
    195      * @param tag Used to identify the source of a log message.  It usually identifies
    196      *        the class or activity where the log call occurs.
    197      * @param tr An exception to log
    198      * @param format the format string (see {@link java.util.Formatter#format})
    199      * @param args
    200      *            the list of arguments passed to the formatter. If there are
    201      *            more arguments than required by {@code format},
    202      *            additional arguments are ignored.
    203      */
    204     public static int v(String tag, Throwable tr, String format, Object... args) {
    205         if (isLoggable(tag, VERBOSE)) {
    206             return Log.v(tag, String.format(format, args), tr);
    207         }
    208         return 0;
    209     }
    210 
    211     /**
    212      * Send a {@link #DEBUG} log message.
    213      * @param tag Used to identify the source of a log message.  It usually identifies
    214      *        the class or activity where the log call occurs.
    215      * @param format the format string (see {@link java.util.Formatter#format})
    216      * @param args
    217      *            the list of arguments passed to the formatter. If there are
    218      *            more arguments than required by {@code format},
    219      *            additional arguments are ignored.
    220      */
    221     public static int d(String tag, String format, Object... args) {
    222         if (isLoggable(tag, DEBUG)) {
    223             return Log.d(tag, String.format(format, args));
    224         }
    225         return 0;
    226     }
    227 
    228     /**
    229      * Send a {@link #DEBUG} log message.
    230      * @param tag Used to identify the source of a log message.  It usually identifies
    231      *        the class or activity where the log call occurs.
    232      * @param tr An exception to log
    233      * @param format the format string (see {@link java.util.Formatter#format})
    234      * @param args
    235      *            the list of arguments passed to the formatter. If there are
    236      *            more arguments than required by {@code format},
    237      *            additional arguments are ignored.
    238      */
    239     public static int d(String tag, Throwable tr, String format, Object... args) {
    240         if (isLoggable(tag, DEBUG)) {
    241             return Log.d(tag, String.format(format, args), tr);
    242         }
    243         return 0;
    244     }
    245 
    246     /**
    247      * Send a {@link #INFO} log message.
    248      * @param tag Used to identify the source of a log message.  It usually identifies
    249      *        the class or activity where the log call occurs.
    250      * @param format the format string (see {@link java.util.Formatter#format})
    251      * @param args
    252      *            the list of arguments passed to the formatter. If there are
    253      *            more arguments than required by {@code format},
    254      *            additional arguments are ignored.
    255      */
    256     public static int i(String tag, String format, Object... args) {
    257         if (isLoggable(tag, INFO)) {
    258             return Log.i(tag, String.format(format, args));
    259         }
    260         return 0;
    261     }
    262 
    263     /**
    264      * Send a {@link #INFO} log message.
    265      * @param tag Used to identify the source of a log message.  It usually identifies
    266      *        the class or activity where the log call occurs.
    267      * @param tr An exception to log
    268      * @param format the format string (see {@link java.util.Formatter#format})
    269      * @param args
    270      *            the list of arguments passed to the formatter. If there are
    271      *            more arguments than required by {@code format},
    272      *            additional arguments are ignored.
    273      */
    274     public static int i(String tag, Throwable tr, String format, Object... args) {
    275         if (isLoggable(tag, INFO)) {
    276             return Log.i(tag, String.format(format, args), tr);
    277         }
    278         return 0;
    279     }
    280 
    281     /**
    282      * Send a {@link #WARN} log message.
    283      * @param tag Used to identify the source of a log message.  It usually identifies
    284      *        the class or activity where the log call occurs.
    285      * @param format the format string (see {@link java.util.Formatter#format})
    286      * @param args
    287      *            the list of arguments passed to the formatter. If there are
    288      *            more arguments than required by {@code format},
    289      *            additional arguments are ignored.
    290      */
    291     public static int w(String tag, String format, Object... args) {
    292         if (isLoggable(tag, WARN)) {
    293             return Log.w(tag, String.format(format, args));
    294         }
    295         return 0;
    296     }
    297 
    298     /**
    299      * Send a {@link #WARN} log message.
    300      * @param tag Used to identify the source of a log message.  It usually identifies
    301      *        the class or activity where the log call occurs.
    302      * @param tr An exception to log
    303      * @param format the format string (see {@link java.util.Formatter#format})
    304      * @param args
    305      *            the list of arguments passed to the formatter. If there are
    306      *            more arguments than required by {@code format},
    307      *            additional arguments are ignored.
    308      */
    309     public static int w(String tag, Throwable tr, String format, Object... args) {
    310         if (isLoggable(tag, WARN)) {
    311             return Log.w(tag, String.format(format, args), tr);
    312         }
    313         return 0;
    314     }
    315 
    316     /**
    317      * Send a {@link #ERROR} log message.
    318      * @param tag Used to identify the source of a log message.  It usually identifies
    319      *        the class or activity where the log call occurs.
    320      * @param format the format string (see {@link java.util.Formatter#format})
    321      * @param args
    322      *            the list of arguments passed to the formatter. If there are
    323      *            more arguments than required by {@code format},
    324      *            additional arguments are ignored.
    325      */
    326     public static int e(String tag, String format, Object... args) {
    327         if (isLoggable(tag, ERROR)) {
    328             return Log.e(tag, String.format(format, args));
    329         }
    330         return 0;
    331     }
    332 
    333     /**
    334      * Send a {@link #ERROR} log message.
    335      * @param tag Used to identify the source of a log message.  It usually identifies
    336      *        the class or activity where the log call occurs.
    337      * @param tr An exception to log
    338      * @param format the format string (see {@link java.util.Formatter#format})
    339      * @param args
    340      *            the list of arguments passed to the formatter. If there are
    341      *            more arguments than required by {@code format},
    342      *            additional arguments are ignored.
    343      */
    344     public static int e(String tag, Throwable tr, String format, Object... args) {
    345         if (isLoggable(tag, ERROR)) {
    346             return Log.e(tag, String.format(format, args), tr);
    347         }
    348         return 0;
    349     }
    350 
    351     /**
    352      * What a Terrible Failure: Report a condition that should never happen.
    353      * The error will always be logged at level ASSERT with the call stack.
    354      * Depending on system configuration, a report may be added to the
    355      * {@link android.os.DropBoxManager} and/or the process may be terminated
    356      * immediately with an error dialog.
    357      * @param tag Used to identify the source of a log message.  It usually identifies
    358      *        the class or activity where the log call occurs.
    359      * @param format the format string (see {@link java.util.Formatter#format})
    360      * @param args
    361      *            the list of arguments passed to the formatter. If there are
    362      *            more arguments than required by {@code format},
    363      *            additional arguments are ignored.
    364      */
    365     public static int wtf(String tag, String format, Object... args) {
    366         return Log.wtf(tag, String.format(format, args), new Error());
    367     }
    368 
    369     /**
    370      * What a Terrible Failure: Report a condition that should never happen.
    371      * The error will always be logged at level ASSERT with the call stack.
    372      * Depending on system configuration, a report may be added to the
    373      * {@link android.os.DropBoxManager} and/or the process may be terminated
    374      * immediately with an error dialog.
    375      * @param tag Used to identify the source of a log message.  It usually identifies
    376      *        the class or activity where the log call occurs.
    377      * @param tr An exception to log
    378      * @param format the format string (see {@link java.util.Formatter#format})
    379      * @param args
    380      *            the list of arguments passed to the formatter. If there are
    381      *            more arguments than required by {@code format},
    382      *            additional arguments are ignored.
    383      */
    384     public static int wtf(String tag, Throwable tr, String format, Object... args) {
    385         return Log.wtf(tag, String.format(format, args), tr);
    386     }
    387 
    388 
    389     /**
    390      * Try to make a date MIME(RFC 2822/5322)-compliant.
    391      *
    392      * It fixes:
    393      * - "Thu, 10 Dec 09 15:08:08 GMT-0700" to "Thu, 10 Dec 09 15:08:08 -0700"
    394      *   (4 digit zone value can't be preceded by "GMT")
    395      *   We got a report saying eBay sends a date in this format
    396      */
    397     public static String cleanUpMimeDate(String date) {
    398         if (TextUtils.isEmpty(date)) {
    399             return date;
    400         }
    401         date = DATE_CLEANUP_PATTERN_WRONG_TIMEZONE.matcher(date).replaceFirst("$1");
    402         return date;
    403     }
    404 
    405 
    406     public static String byteToHex(int b) {
    407         return byteToHex(new StringBuilder(), b).toString();
    408     }
    409 
    410     public static StringBuilder byteToHex(StringBuilder sb, int b) {
    411         b &= 0xFF;
    412         sb.append("0123456789ABCDEF".charAt(b >> 4));
    413         sb.append("0123456789ABCDEF".charAt(b & 0xF));
    414         return sb;
    415     }
    416 
    417 }
    418