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; 2069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 2169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onukiimport android.util.Log; 2269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 2369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onukiimport java.util.ArrayList; 2469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 2569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki/** 2669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * A class to keep last N of lines sent to the server and responses received from the server. 2769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * They are sent to logcat when {@link #logLastDiscourse} is called. 2869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * 2969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * <p>This class is used to log the recent network activities when a response parser crashes. 3069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 3169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onukipublic class DiscourseLogger { 3269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private final int mBufferSize; 3369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private String[] mBuffer; 3469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private int mPos; 3569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private final StringBuilder mReceivingLine = new StringBuilder(100); 3669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 3769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public DiscourseLogger(int bufferSize) { 3869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mBufferSize = bufferSize; 3969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki initBuffer(); 4069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 4169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 4269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private void initBuffer() { 4369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mBuffer = new String[mBufferSize]; 4469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 4569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 4669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** Add a single line to {@link #mBuffer}. */ 4769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private void addLine(String s) { 4869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mBuffer[mPos] = s; 4969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mPos++; 5069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (mPos >= mBufferSize) { 5169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mPos = 0; 5269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 5369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 5469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 5569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki private void addReceivingLineToBuffer() { 5669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (mReceivingLine.length() > 0) { 5769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addLine(mReceivingLine.toString()); 5869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mReceivingLine.delete(0, Integer.MAX_VALUE); 5969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 6069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 6169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 6269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** 6369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Store a single byte received from the server in {@link #mReceivingLine}. When LF is 6469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * received, the content of {@link #mReceivingLine} is added to {@link #mBuffer}. 6569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 6669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public void addReceivedByte(int b) { 6769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (0x20 <= b && b <= 0x7e) { // Append only printable ASCII chars. 6869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mReceivingLine.append((char) b); 6969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } else if (b == '\n') { // LF 7069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addReceivingLineToBuffer(); 7169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } else if (b == '\r') { // CR 7269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } else { 7369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki final String hex = "00" + Integer.toHexString(b); 7469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki mReceivingLine.append("\\x" + hex.substring(hex.length() - 2, hex.length())); 7569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 7669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 7769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 7869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** Add a line sent to the server to {@link #mBuffer}. */ 7969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public void addSentCommand(String command) { 8069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addLine(command); 8169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 8269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 8369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** @return the contents of {@link #mBuffer} as a String array. */ 8469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /* package for testing */ String[] getLines() { 8569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki addReceivingLineToBuffer(); 8669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 8769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki ArrayList<String> list = new ArrayList<String>(); 8869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 8969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki final int start = mPos; 9069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki int pos = mPos; 9169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki do { 9269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki String s = mBuffer[pos]; 9369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (s != null) { 9469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki list.add(s); 9569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 9669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki pos = (pos + 1) % mBufferSize; 9769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } while (pos != start); 9869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 9969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki String[] ret = new String[list.size()]; 10069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki list.toArray(ret); 10169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki return ret; 10269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 10369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 10469ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki /** 10569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * Log the contents of the {@link mBuffer}, and clears it out. (So it's okay to call this 10669ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki * method successively more than once. There will be no duplicate log.) 10769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki */ 10869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki public void logLastDiscourse() { 10969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki String[] lines = getLines(); 11069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki if (lines.length == 0) { 11169ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki return; 11269ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 11369ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki 11431d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blank Log.w(Logging.LOG_TAG, "Last network activities:"); 11569ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki for (String r : getLines()) { 11631d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blank Log.w(Logging.LOG_TAG, r); 11769ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 11869ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki initBuffer(); 11969ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki } 12069ade70f2d0857f4eadae97734ee8891e77895cbMakoto Onuki} 121