LoggingPrintStream.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/* 2 * Copyright (C) 2008 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 17package com.android.internal.os; 18 19import java.io.PrintStream; 20import java.io.OutputStream; 21import java.io.IOException; 22import java.util.Locale; 23import java.util.Formatter; 24 25/** 26 * A print stream which logs output line by line. 27 * 28 * {@hide} 29 */ 30abstract class LoggingPrintStream extends PrintStream { 31 32 private final StringBuilder builder = new StringBuilder(); 33 34 protected LoggingPrintStream() { 35 super(new OutputStream() { 36 public void write(int oneByte) throws IOException { 37 throw new AssertionError(); 38 } 39 }); 40 } 41 42 /** 43 * Logs the given line. 44 */ 45 protected abstract void log(String line); 46 47 @Override 48 public synchronized void flush() { 49 flush(true); 50 } 51 52 /** 53 * Searches buffer for line breaks and logs a message for each one. 54 * 55 * @param completely true if the ending chars should be treated as a line 56 * even though they don't end in a line break 57 */ 58 private void flush(boolean completely) { 59 int length = builder.length(); 60 61 int start = 0; 62 int nextBreak; 63 64 // Log one line for each line break. 65 while (start < length 66 && (nextBreak = builder.indexOf("\n", start)) != -1) { 67 log(builder.substring(start, nextBreak)); 68 start = nextBreak + 1; 69 } 70 71 if (completely) { 72 // Log the remainder of the buffer. 73 if (start < length) { 74 log(builder.substring(start)); 75 } 76 builder.setLength(0); 77 } else { 78 // Delete characters leading up to the next starting point. 79 builder.delete(0, start); 80 } 81 } 82 83 /* 84 * We have no idea of how these bytes are encoded, so just ignore them. 85 */ 86 87 /** Ignored. */ 88 public void write(int oneByte) {} 89 90 /** Ignored. */ 91 @Override 92 public void write(byte buffer[]) {} 93 94 /** Ignored. */ 95 @Override 96 public void write(byte bytes[], int start, int count) {} 97 98 /** Always returns false. */ 99 @Override 100 public boolean checkError() { 101 return false; 102 } 103 104 /** Ignored. */ 105 @Override 106 protected void setError() { /* ignored */ } 107 108 /** Ignored. */ 109 @Override 110 public void close() { /* ignored */ } 111 112 @Override 113 public PrintStream format(String format, Object... args) { 114 return format(Locale.getDefault(), format, args); 115 } 116 117 @Override 118 public PrintStream printf(String format, Object... args) { 119 return format(format, args); 120 } 121 122 @Override 123 public PrintStream printf(Locale l, String format, Object... args) { 124 return format(l, format, args); 125 } 126 127 private final Formatter formatter = new Formatter(builder, null); 128 129 @Override 130 public synchronized PrintStream format( 131 Locale l, String format, Object... args) { 132 if (format == null) { 133 throw new NullPointerException("format"); 134 } 135 136 formatter.format(l, format, args); 137 flush(false); 138 return this; 139 } 140 141 @Override 142 public synchronized void print(char[] charArray) { 143 builder.append(charArray); 144 flush(false); 145 } 146 147 @Override 148 public synchronized void print(char ch) { 149 builder.append(ch); 150 if (ch == '\n') { 151 flush(false); 152 } 153 } 154 155 @Override 156 public synchronized void print(double dnum) { 157 builder.append(dnum); 158 } 159 160 @Override 161 public synchronized void print(float fnum) { 162 builder.append(fnum); 163 } 164 165 @Override 166 public synchronized void print(int inum) { 167 builder.append(inum); 168 } 169 170 @Override 171 public synchronized void print(long lnum) { 172 builder.append(lnum); 173 } 174 175 @Override 176 public synchronized void print(Object obj) { 177 builder.append(obj); 178 flush(false); 179 } 180 181 @Override 182 public synchronized void print(String str) { 183 builder.append(str); 184 flush(false); 185 } 186 187 @Override 188 public synchronized void print(boolean bool) { 189 builder.append(bool); 190 } 191 192 @Override 193 public synchronized void println() { 194 flush(true); 195 } 196 197 @Override 198 public synchronized void println(char[] charArray) { 199 builder.append(charArray); 200 flush(true); 201 } 202 203 @Override 204 public synchronized void println(char ch) { 205 builder.append(ch); 206 flush(true); 207 } 208 209 @Override 210 public synchronized void println(double dnum) { 211 builder.append(dnum); 212 flush(true); 213 } 214 215 @Override 216 public synchronized void println(float fnum) { 217 builder.append(fnum); 218 flush(true); 219 } 220 221 @Override 222 public synchronized void println(int inum) { 223 builder.append(inum); 224 flush(true); 225 } 226 227 @Override 228 public synchronized void println(long lnum) { 229 builder.append(lnum); 230 flush(true); 231 } 232 233 @Override 234 public synchronized void println(Object obj) { 235 builder.append(obj); 236 flush(true); 237 } 238 239 @Override 240 public synchronized void println(String s) { 241 if (builder.length() == 0) { 242 // Optimization for a simple println. 243 int length = s.length(); 244 245 int start = 0; 246 int nextBreak; 247 248 // Log one line for each line break. 249 while (start < length 250 && (nextBreak = s.indexOf('\n', start)) != -1) { 251 log(s.substring(start, nextBreak)); 252 start = nextBreak + 1; 253 } 254 255 if (start < length) { 256 log(s.substring(start)); 257 } 258 } else { 259 builder.append(s); 260 flush(true); 261 } 262 } 263 264 @Override 265 public synchronized void println(boolean bool) { 266 builder.append(bool); 267 flush(true); 268 } 269 270 @Override 271 public synchronized PrintStream append(char c) { 272 print(c); 273 return this; 274 } 275 276 @Override 277 public synchronized PrintStream append(CharSequence csq) { 278 builder.append(csq); 279 flush(false); 280 return this; 281 } 282 283 @Override 284 public synchronized PrintStream append( 285 CharSequence csq, int start, int end) { 286 builder.append(csq, start, end); 287 flush(false); 288 return this; 289 } 290} 291