Home | History | Annotate | Download | only in utility
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      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 
     17 package com.android.exchange.utility;
     18 
     19 import android.util.Base64;
     20 import android.util.Log;
     21 
     22 import com.android.exchange.Eas;
     23 import com.android.mail.utils.LogUtils;
     24 
     25 import org.apache.http.Header;
     26 import org.apache.http.HttpEntity;
     27 import org.apache.http.entity.BufferedHttpEntity;
     28 import org.apache.http.HttpResponse;
     29 import org.apache.http.HttpResponseInterceptor;
     30 import org.apache.http.protocol.HttpContext;
     31 
     32 import java.io.ByteArrayOutputStream;
     33 import java.io.IOException;
     34 import java.io.InputStream;
     35 import java.util.zip.GZIPInputStream;
     36 
     37 /**
     38  * Dumps the wbxml in base64 (much like {@link CurlLogger}) so that the
     39  * response from Exchange can be viewed for debugging purposes.
     40  */
     41 public class WbxmlResponseLogger implements HttpResponseInterceptor {
     42     private static final String TAG = Eas.LOG_TAG;
     43     protected static final int MAX_LENGTH = 1024;
     44 
     45     protected static boolean shouldLogResponse(final long contentLength) {
     46         // Not going to bother if there is a lot of content since most of that information
     47         // will probably just be message contents anyways.
     48         return contentLength < MAX_LENGTH;
     49     }
     50 
     51     protected static String processContentEncoding(final Header encodingHeader) {
     52         if (encodingHeader != null) {
     53             final String encodingValue = encodingHeader.getValue();
     54             return (encodingValue == null) ? "UTF-8" : encodingValue;
     55         }
     56         return "UTF-8";
     57     }
     58 
     59     protected static byte[] getContentAsByteArray(InputStream is, int batchSize)
     60         throws IOException {
     61         // Start building our byte array to encode and dump.
     62         int count;
     63         final byte[] data = new byte[batchSize];
     64         final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
     65         while ((count = is.read(data, 0, data.length)) != -1) {
     66             buffer.write(data, 0, count);
     67         }
     68         buffer.flush();
     69         return buffer.toByteArray();
     70     }
     71 
     72     @Override
     73     public void process(HttpResponse response, HttpContext context) throws IOException {
     74         if (Log.isLoggable(TAG, Log.DEBUG)) {
     75             // Wrap the HttpEntity so the response InputStream can be requested and processed
     76             // numerous times.
     77             response.setEntity(new BufferedHttpEntity(response.getEntity()));
     78 
     79             // Now grab the wrapped HttpEntity so that you safely can process the response w/o
     80             // affecting the core response processing module.
     81             final HttpEntity entity = response.getEntity();
     82             if (!shouldLogResponse(entity.getContentLength())) {
     83                 LogUtils.d(TAG, "wbxml response: [TOO MUCH DATA TO INCLUDE]");
     84                 return;
     85             }
     86 
     87             // We need to figure out the encoding in the case that it is gzip and we need to
     88             // inflate it during processing.
     89             final Header encodingHeader = entity.getContentEncoding();
     90             final String encoding = processContentEncoding(encodingHeader);
     91 
     92             final InputStream is;
     93             if (encoding.equals("gzip")) {
     94                 // We need to inflate this first.
     95                 final InputStream unwrappedIs = response.getEntity().getContent();
     96                 is = new GZIPInputStream(unwrappedIs);
     97             } else {
     98                 is = response.getEntity().getContent();
     99             }
    100 
    101             final byte currentXMLBytes[] = getContentAsByteArray(is, MAX_LENGTH);
    102 
    103             // Now let's dump out the base 64 encoded bytes and the rest of the command that will
    104             // tell us what the response is.
    105             final String base64 = Base64.encodeToString(currentXMLBytes, Base64.NO_WRAP);
    106             LogUtils.d(TAG, "wbxml response: echo '%s' | base64 -d | wbxml", base64);
    107         }
    108     }
    109 
    110 }
    111