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 import com.google.common.annotations.VisibleForTesting;
     22 
     23 import java.util.List;
     24 import java.util.regex.Pattern;
     25 
     26 public class LogUtils {
     27 
     28     // "GMT" + "+" or "-" + 4 digits
     29     private static final Pattern DATE_CLEANUP_PATTERN_WRONG_TIMEZONE =
     30             Pattern.compile("GMT([-+]\\d{4})$");
     31     private static String LOG_TAG = "UnifiedEmail";
     32 
     33     /**
     34      * Get the log tag to apply to logging.
     35      */
     36     public String getLogTag() {
     37         return LOG_TAG;
     38     }
     39 
     40     /**
     41      * Priority constant for the println method; use LogUtils.v.
     42      */
     43     public static final int VERBOSE = Log.VERBOSE;
     44 
     45     /**
     46      * Priority constant for the println method; use LogUtils.d.
     47      */
     48     public static final int DEBUG = Log.DEBUG;
     49 
     50     /**
     51      * Priority constant for the println method; use LogUtils.i.
     52      */
     53     public static final int INFO = Log.INFO;
     54 
     55     /**
     56      * Priority constant for the println method; use LogUtils.w.
     57      */
     58     public static final int WARN = Log.WARN;
     59 
     60     /**
     61      * Priority constant for the println method; use LogUtils.e.
     62      */
     63     public static final int ERROR = Log.ERROR;
     64 
     65     /**
     66      * Used to enable/disable logging that we don't want included in
     67      * production releases.
     68      */
     69     private static final int MAX_ENABLED_LOG_LEVEL = VERBOSE;
     70 
     71     private static Boolean sDebugLoggingEnabledForTests = null;
     72 
     73     /**
     74      * Enable debug logging for unit tests.
     75      */
     76     @VisibleForTesting
     77     static void setDebugLoggingEnabledForTests(boolean enabled) {
     78         sDebugLoggingEnabledForTests = Boolean.valueOf(enabled);
     79     }
     80 
     81     /**
     82      * Returns true if the build configuration prevents debug logging.
     83      */
     84     @VisibleForTesting
     85     public static boolean buildPreventsDebugLogging() {
     86         return MAX_ENABLED_LOG_LEVEL > VERBOSE;
     87     }
     88 
     89     /**
     90      * Returns a boolean indicating whether debug logging is enabled.
     91      */
     92     protected static boolean isDebugLoggingEnabled() {
     93         if (buildPreventsDebugLogging()) {
     94             return false;
     95         }
     96         if (sDebugLoggingEnabledForTests != null) {
     97             return sDebugLoggingEnabledForTests.booleanValue();
     98         }
     99         return Log.isLoggable(LOG_TAG, Log.DEBUG);
    100     }
    101 
    102     /**
    103      * Returns a String for the specified content provider uri.  This will do
    104      * sanitation of the uri to remove PII if debug logging is not enabled.
    105      */
    106     public static String contentUriToString(Uri uri) {
    107 
    108         if (isDebugLoggingEnabled()) {
    109             // Debug logging has been enabled, so log the uri as is
    110             return uri.toString();
    111         } else {
    112             // Debug logging is not enabled, we want to remove the email address from the uri.
    113             List<String> pathSegments = uri.getPathSegments();
    114 
    115             Uri.Builder builder = new Uri.Builder()
    116                     .scheme(uri.getScheme())
    117                     .authority(uri.getAuthority())
    118                     .query(uri.getQuery())
    119                     .fragment(uri.getFragment());
    120 
    121             // This assumes that the first path segment is the account
    122             final String account = pathSegments.get(0);
    123 
    124             builder = builder.appendPath(String.valueOf(account.hashCode()));
    125             for (int i = 1; i < pathSegments.size(); i++) {
    126                 builder.appendPath(pathSegments.get(i));
    127             }
    128             return builder.toString();
    129         }
    130     }
    131 
    132    /* TODO: what is the correct behavior for base case and the Gmail case? Seems like this
    133     * belongs in override code in UnifiedGmail.
    134     *Converts the specified set of labels to a string, and removes any PII as necessary
    135     * public static String labelSetToString(Set<String> labelSet) {
    136         if (isDebugLoggingEnabled() || labelSet == null) {
    137             return labelSet != null ? labelSet.toString() : "";
    138         } else {
    139             final StringBuilder builder = new StringBuilder("[");
    140             int i = 0;
    141             for(String label : labelSet) {
    142                 if (i > 0) {
    143                     builder.append(", ");
    144                 }
    145                 builder.append(sanitizeLabelName(label));
    146                 i++;
    147             }
    148             builder.append(']');
    149             return builder.toString();
    150         }
    151     }
    152 
    153     private static String sanitizeLabelName(String canonicalName) {
    154         if (TextUtils.isEmpty(canonicalName)) {
    155             return "";
    156         }
    157 
    158         if (Gmail.isSystemLabel(canonicalName)) {
    159             return canonicalName;
    160         }
    161 
    162         return USER_LABEL_PREFIX + String.valueOf(canonicalName.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);
    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