1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/* 2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Copyright (C) 2008 The Android Open Source Project 3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License"); 5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * you may not use this file except in compliance with the License. 6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * You may obtain a copy of the License at 7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * http://www.apache.org/licenses/LICENSE-2.0 9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software 11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS, 12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and 14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License. 15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage com.android.mail.utils; 18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.util.Log; 20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.FilterInputStream; 22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.IOException; 23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.InputStream; 24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/** 26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Simple class used for debugging only that affords us a view of the raw IMAP or POP3 stream, 27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * in addition to the tokenized version. 28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Use of this class *MUST* be restricted to logging-enabled situations only. 30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class LoggingInputStream extends FilterInputStream { 32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private static final String LOG_TAG = new LogUtils().getLogTag(); 33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private StringBuilder mSb; 34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private boolean mDumpEmptyLines; 35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private final String mTag; 36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public LoggingInputStream(InputStream in) { 38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this(in, "RAW", false); 39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public LoggingInputStream(InputStream in, String tag, boolean dumpEmptyLines) { 42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook super(in); 43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook mTag = tag + " "; 44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook mDumpEmptyLines = dumpEmptyLines; 45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook initBuffer(); 46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook Log.d(LOG_TAG, mTag + "dump start"); 47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private void initBuffer() { 50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook mSb = new StringBuilder(mTag); 51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Collect chars as read, and log them when EOL reached. 55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook @Override 57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public int read() throws IOException { 58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook int oneByte = super.read(); 59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook logRaw(oneByte); 60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return oneByte; 61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Collect chars as read, and log them when EOL reached. 65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook @Override 67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public int read(byte[] b, int offset, int length) throws IOException { 68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook int bytesRead = super.read(b, offset, length); 69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook int copyBytes = bytesRead; 70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook while (copyBytes > 0) { 71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook logRaw(b[offset] & 0xFF); 72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook copyBytes--; 73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook offset++; 74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return bytesRead; 77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Write and clear the buffer 81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private void logRaw(int oneByte) { 83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook if (oneByte == '\r') { 84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook // Don't log. 85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } else if (oneByte == '\n') { 86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook flushLog(); 87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } else if (0x20 <= oneByte && oneByte <= 0x7e) { // Printable ASCII. 88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook mSb.append((char)oneByte); 89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } else { 90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook // email protocols are supposed to be all 7bits, but there are wrong implementations 91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook // that do send 8 bit characters... 92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook mSb.append("\\x" + LogUtils.byteToHex(oneByte)); 93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private void flushLog() { 97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook if (mDumpEmptyLines || (mSb.length() > mTag.length())) { 98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook Log.d(LOG_TAG, mSb.toString()); 99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook initBuffer(); 100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook @Override 104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public void close() throws IOException { 105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook super.close(); 106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook flushLog(); 107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook} 109