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