169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki/* 269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Copyright (C) 2010 The Android Open Source Project 369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * 469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * you may not use this file except in compliance with the License. 669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * You may obtain a copy of the License at 769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * 869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * 1069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Unless required by applicable law or agreed to in writing, software 1169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 1269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * See the License for the specific language governing permissions and 1469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * limitations under the License. 1569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 1669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 1769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onukipackage com.android.email.mail.transport; 1869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 1931d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.Logging; 20560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils; 2169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 2269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onukiimport java.util.ArrayList; 2369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 2469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki/** 2569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * A class to keep last N of lines sent to the server and responses received from the server. 2669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * They are sent to logcat when {@link #logLastDiscourse} is called. 2769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * 2869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * <p>This class is used to log the recent network activities when a response parser crashes. 2969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 3069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onukipublic class DiscourseLogger { 3169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private final int mBufferSize; 3269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private String[] mBuffer; 3369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private int mPos; 3469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private final StringBuilder mReceivingLine = new StringBuilder(100); 3569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 3669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public DiscourseLogger(int bufferSize) { 3769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mBufferSize = bufferSize; 3869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki initBuffer(); 3969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 4069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 4169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private void initBuffer() { 4269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mBuffer = new String[mBufferSize]; 4369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 4469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 4569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** Add a single line to {@link #mBuffer}. */ 4669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private void addLine(String s) { 4769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mBuffer[mPos] = s; 4869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mPos++; 4969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (mPos >= mBufferSize) { 5069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mPos = 0; 5169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 5269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 5369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 5469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private void addReceivingLineToBuffer() { 5569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (mReceivingLine.length() > 0) { 5669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addLine(mReceivingLine.toString()); 5769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mReceivingLine.delete(0, Integer.MAX_VALUE); 5869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 5969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 6069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 6169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** 6269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Store a single byte received from the server in {@link #mReceivingLine}. When LF is 6369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * received, the content of {@link #mReceivingLine} is added to {@link #mBuffer}. 6469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 6569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public void addReceivedByte(int b) { 6669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (0x20 <= b && b <= 0x7e) { // Append only printable ASCII chars. 6769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mReceivingLine.append((char) b); 6869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } else if (b == '\n') { // LF 6969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addReceivingLineToBuffer(); 7069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } else if (b == '\r') { // CR 7169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } else { 7269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki final String hex = "00" + Integer.toHexString(b); 7369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mReceivingLine.append("\\x" + hex.substring(hex.length() - 2, hex.length())); 7469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 7569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 7669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 7769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** Add a line sent to the server to {@link #mBuffer}. */ 7869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public void addSentCommand(String command) { 7969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addLine(command); 8069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 8169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 8269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** @return the contents of {@link #mBuffer} as a String array. */ 8369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /* package for testing */ String[] getLines() { 8469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addReceivingLineToBuffer(); 8569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 8669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki ArrayList<String> list = new ArrayList<String>(); 8769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 8869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki final int start = mPos; 8969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki int pos = mPos; 9069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki do { 9169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki String s = mBuffer[pos]; 9269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (s != null) { 9369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki list.add(s); 9469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 9569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki pos = (pos + 1) % mBufferSize; 9669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } while (pos != start); 9769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 9869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki String[] ret = new String[list.size()]; 9969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki list.toArray(ret); 10069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki return ret; 10169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 10269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 10369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** 10469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Log the contents of the {@link mBuffer}, and clears it out. (So it's okay to call this 10569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * method successively more than once. There will be no duplicate log.) 10669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 10769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public void logLastDiscourse() { 10869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki String[] lines = getLines(); 10969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (lines.length == 0) { 11069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki return; 11169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 11269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 113560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.w(Logging.LOG_TAG, "Last network activities:"); 11469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki for (String r : getLines()) { 1155a3fe57f4e13125a050948a7a5abf629f431f60bPaul Westbrook LogUtils.w(Logging.LOG_TAG, "%s", r); 11669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 11769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki initBuffer(); 11869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 11969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki} 120