1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.exec;
19
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.nio.charset.Charset;
24
25
26
27
28
29 public abstract class LogOutputStream extends OutputStream {
30
31 private static final class ByteArrayOutputStreamX extends ByteArrayOutputStream {
32 private ByteArrayOutputStreamX(final int size) {
33 super(size);
34 }
35
36 public synchronized String toString(final Charset charset) {
37 return new String(buf, 0, count, charset);
38 }
39 }
40
41
42 private static final int INTIAL_SIZE = 132;
43
44
45 private static final int CR = 0x0d;
46
47
48 private static final int LF = 0x0a;
49
50
51 private final ByteArrayOutputStreamX buffer = new ByteArrayOutputStreamX(INTIAL_SIZE);
52
53 private boolean skip;
54
55 private final int level;
56
57 private final Charset charset;
58
59
60
61
62 public LogOutputStream() {
63 this(999);
64 }
65
66
67
68
69
70
71 public LogOutputStream(final int level) {
72 this(level, null);
73 }
74
75
76
77
78
79
80
81 public LogOutputStream(final int level, final Charset charset) {
82 this.level = level;
83 this.charset = charset == null ? Charset.defaultCharset() : charset;
84 }
85
86
87
88
89
90
91 @Override
92 public void close() throws IOException {
93 if (buffer.size() > 0) {
94 processBuffer();
95 }
96 super.close();
97 }
98
99
100
101
102
103
104 @Override
105 public void flush() {
106 if (buffer.size() > 0) {
107 processBuffer();
108 }
109 }
110
111
112
113
114
115
116 public int getMessageLevel() {
117 return level;
118 }
119
120
121
122
123 protected void processBuffer() {
124 processLine(buffer.toString(charset));
125 buffer.reset();
126 }
127
128
129
130
131
132
133 protected void processLine(final String line) {
134 processLine(line, level);
135 }
136
137
138
139
140
141
142
143 protected abstract void processLine(final String line, final int logLevel);
144
145
146
147
148
149
150
151
152
153
154 @Override
155 public void write(final byte[] b, final int off, final int len) throws IOException {
156
157 int offset = off;
158 int blockStartOffset = offset;
159 int remaining = len;
160 while (remaining > 0) {
161 while (remaining > 0 && b[offset] != LF && b[offset] != CR) {
162 offset++;
163 remaining--;
164 }
165
166 final int blockLength = offset - blockStartOffset;
167 if (blockLength > 0) {
168 buffer.write(b, blockStartOffset, blockLength);
169 }
170 while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) {
171 write(b[offset]);
172 offset++;
173 remaining--;
174 }
175 blockStartOffset = offset;
176 }
177 }
178
179
180
181
182
183
184
185 @Override
186 public void write(final int cc) throws IOException {
187 final byte c = (byte) cc;
188 if (c == '\n' || c == '\r') {
189 if (!skip) {
190 processBuffer();
191 }
192 } else {
193 buffer.write(cc);
194 }
195 skip = c == '\r';
196 }
197 }