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