13469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project/* 23469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 33469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * 43469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 53469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * you may not use this file except in compliance with the License. 63469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * You may obtain a copy of the License at 73469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * 83469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 93469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * 103469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 113469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 123469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * See the License for the specific language governing permissions and 143469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * limitations under the License. 153469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project */ 163469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 1731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankpackage com.android.emailcommon.utility; 183469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 1931d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.Logging; 20560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils; 213469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 22dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onukiimport java.io.FilterInputStream; 233469902379242c723b871d1dcb09b02d0998d538The Android Open Source Projectimport java.io.IOException; 243469902379242c723b871d1dcb09b02d0998d538The Android Open Source Projectimport java.io.InputStream; 253469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 263469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project/** 273469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Simple class used for debugging only that affords us a view of the raw IMAP or POP3 stream, 283469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * in addition to the tokenized version. 29560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy * 303469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Use of this class *MUST* be restricted to logging-enabled situations only. 313469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project */ 32dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onukipublic class LoggingInputStream extends FilterInputStream { 33dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki private StringBuilder mSb; 34dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki private boolean mDumpEmptyLines; 35dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki private final String mTag; 363469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 373469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project public LoggingInputStream(InputStream in) { 38dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki this(in, "RAW", false); 39dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } 40dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki 41dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki public LoggingInputStream(InputStream in, String tag, boolean dumpEmptyLines) { 42dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki super(in); 43dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki mTag = tag + " "; 44dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki mDumpEmptyLines = dumpEmptyLines; 45dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki initBuffer(); 46560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.d(Logging.LOG_TAG, mTag + "dump start"); 47dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } 48dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki 49dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki private void initBuffer() { 50dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki mSb = new StringBuilder(mTag); 513469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 523469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 533469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project /** 543469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Collect chars as read, and log them when EOL reached. 553469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project */ 563469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project @Override 573469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project public int read() throws IOException { 58dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki int oneByte = super.read(); 593469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project logRaw(oneByte); 603469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project return oneByte; 613469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 623469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 633469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project /** 643469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Collect chars as read, and log them when EOL reached. 653469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project */ 663469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project @Override 673469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project public int read(byte[] b, int offset, int length) throws IOException { 68dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki int bytesRead = super.read(b, offset, length); 693469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project int copyBytes = bytesRead; 703469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project while (copyBytes > 0) { 71dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki logRaw(b[offset] & 0xFF); 723469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project copyBytes--; 733469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project offset++; 743469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 753469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 763469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project return bytesRead; 773469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 783469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 793469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project /** 803469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Write and clear the buffer 813469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project */ 823469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project private void logRaw(int oneByte) { 83dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki if (oneByte == '\r') { 84dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki // Don't log. 85dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } else if (oneByte == '\n') { 86dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki flushLog(); 87dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } else if (0x20 <= oneByte && oneByte <= 0x7e) { // Printable ASCII. 883469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project mSb.append((char)oneByte); 89dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } else { 90dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki // email protocols are supposed to be all 7bits, but there are wrong implementations 91dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki // that do send 8 bit characters... 92dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki mSb.append("\\x" + Utility.byteToHex(oneByte)); 933469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 943469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 95dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki 96dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki private void flushLog() { 97dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki if (mDumpEmptyLines || (mSb.length() > mTag.length())) { 98560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.d(Logging.LOG_TAG, mSb.toString()); 99dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki initBuffer(); 100dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } 101dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } 102dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki 103dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki @Override 104dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki public void close() throws IOException { 105dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki super.close(); 106dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki flushLog(); 107dfeb1184ebf6c59fc6e617149e03edb73b7e0df7Makoto Onuki } 1083469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project} 109