1 /* 2 * Copyright (C) 2010 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.email.mail.transport; 18 19 import com.android.emailcommon.Logging; 20 21 import android.util.Log; 22 23 import java.util.ArrayList; 24 25 /** 26 * A class to keep last N of lines sent to the server and responses received from the server. 27 * They are sent to logcat when {@link #logLastDiscourse} is called. 28 * 29 * <p>This class is used to log the recent network activities when a response parser crashes. 30 */ 31 public class DiscourseLogger { 32 private final int mBufferSize; 33 private String[] mBuffer; 34 private int mPos; 35 private final StringBuilder mReceivingLine = new StringBuilder(100); 36 37 public DiscourseLogger(int bufferSize) { 38 mBufferSize = bufferSize; 39 initBuffer(); 40 } 41 42 private void initBuffer() { 43 mBuffer = new String[mBufferSize]; 44 } 45 46 /** Add a single line to {@link #mBuffer}. */ 47 private void addLine(String s) { 48 mBuffer[mPos] = s; 49 mPos++; 50 if (mPos >= mBufferSize) { 51 mPos = 0; 52 } 53 } 54 55 private void addReceivingLineToBuffer() { 56 if (mReceivingLine.length() > 0) { 57 addLine(mReceivingLine.toString()); 58 mReceivingLine.delete(0, Integer.MAX_VALUE); 59 } 60 } 61 62 /** 63 * Store a single byte received from the server in {@link #mReceivingLine}. When LF is 64 * received, the content of {@link #mReceivingLine} is added to {@link #mBuffer}. 65 */ 66 public void addReceivedByte(int b) { 67 if (0x20 <= b && b <= 0x7e) { // Append only printable ASCII chars. 68 mReceivingLine.append((char) b); 69 } else if (b == '\n') { // LF 70 addReceivingLineToBuffer(); 71 } else if (b == '\r') { // CR 72 } else { 73 final String hex = "00" + Integer.toHexString(b); 74 mReceivingLine.append("\\x" + hex.substring(hex.length() - 2, hex.length())); 75 } 76 } 77 78 /** Add a line sent to the server to {@link #mBuffer}. */ 79 public void addSentCommand(String command) { 80 addLine(command); 81 } 82 83 /** @return the contents of {@link #mBuffer} as a String array. */ 84 /* package for testing */ String[] getLines() { 85 addReceivingLineToBuffer(); 86 87 ArrayList<String> list = new ArrayList<String>(); 88 89 final int start = mPos; 90 int pos = mPos; 91 do { 92 String s = mBuffer[pos]; 93 if (s != null) { 94 list.add(s); 95 } 96 pos = (pos + 1) % mBufferSize; 97 } while (pos != start); 98 99 String[] ret = new String[list.size()]; 100 list.toArray(ret); 101 return ret; 102 } 103 104 /** 105 * Log the contents of the {@link mBuffer}, and clears it out. (So it's okay to call this 106 * method successively more than once. There will be no duplicate log.) 107 */ 108 public void logLastDiscourse() { 109 String[] lines = getLines(); 110 if (lines.length == 0) { 111 return; 112 } 113 114 Log.w(Logging.LOG_TAG, "Last network activities:"); 115 for (String r : getLines()) { 116 Log.w(Logging.LOG_TAG, r); 117 } 118 initBuffer(); 119 } 120 } 121