001
014
015 package com.liferay.portal.kernel.io.unsync;
016
017 import com.liferay.portal.kernel.util.CharPool;
018 import com.liferay.portal.kernel.util.StringBundler;
019
020 import java.io.IOException;
021 import java.io.Reader;
022
023
030 public class UnsyncBufferedReader extends Reader {
031
032 public UnsyncBufferedReader(Reader reader) {
033 this(reader, _DEFAULT_BUFFER_SIZE);
034 }
035
036 public UnsyncBufferedReader(Reader reader, int size) {
037 if (size <= 0) {
038 throw new IllegalArgumentException("Size is less than 0");
039 }
040
041 this.reader = reader;
042
043 buffer = new char[size];
044 }
045
046 @Override
047 public void close() throws IOException {
048 if (reader != null) {
049 reader.close();
050
051 reader = null;
052 buffer = null;
053 }
054 }
055
056 @Override
057 public void mark(int markLimit) throws IOException {
058 if (markLimit < 0) {
059 throw new IllegalArgumentException("Mark limit is less than 0");
060 }
061
062 if (reader == null) {
063 throw new IOException("Reader is null");
064 }
065
066 if (markLimit == 0) {
067 return;
068 }
069
070 markLimitIndex = markLimit;
071
072 if (index > 0) {
073 int available = firstInvalidIndex - index;
074
075 if (available > 0) {
076
077
078
079 System.arraycopy(buffer, index, buffer, 0, available);
080
081 index = 0;
082
083 firstInvalidIndex = available;
084 }
085 else {
086
087
088
089 index = firstInvalidIndex = 0;
090 }
091 }
092 }
093
094 @Override
095 public boolean markSupported() {
096 return true;
097 }
098
099 @Override
100 public int read() throws IOException {
101 if (reader == null) {
102 throw new IOException("Reader is null");
103 }
104
105 if (index >= firstInvalidIndex) {
106 fillInBuffer();
107
108 if (index >= firstInvalidIndex) {
109 return -1;
110 }
111 }
112
113 return buffer[index++];
114 }
115
116 @Override
117 public int read(char[] chars) throws IOException {
118 return read(chars, 0, chars.length);
119 }
120
121 @Override
122 public int read(char[] chars, int offset, int length) throws IOException {
123 if (reader == null) {
124 throw new IOException("Reader is null");
125 }
126
127 if (length <= 0) {
128 return 0;
129 }
130
131 int read = 0;
132
133 while (true) {
134
135
136
137 int currentRead = readOnce(chars, offset + read, length - read);
138
139 if (currentRead <= 0) {
140 if (read == 0) {
141 read = currentRead;
142 }
143
144 break;
145 }
146
147 read += currentRead;
148
149 if (!reader.ready() || (read >= length)) {
150
151
152
153 break;
154 }
155 }
156
157 return read;
158 }
159
160 public String readLine() throws IOException {
161 if (reader == null) {
162 throw new IOException("Reader is null");
163 }
164
165 StringBundler sb = null;
166
167 while (true) {
168 if (index >= firstInvalidIndex) {
169 fillInBuffer();
170 }
171
172 if (index >= firstInvalidIndex) {
173 if ((sb != null) && (sb.index() > 0)) {
174 return sb.toString();
175 }
176 else {
177 return null;
178 }
179 }
180
181 boolean hasLineBreak = false;
182 char lineEndChar = 0;
183
184 int x = index;
185 int y = index;
186
187 while (y < firstInvalidIndex) {
188 lineEndChar = buffer[y];
189
190 if ((lineEndChar == CharPool.NEW_LINE) ||
191 (lineEndChar == CharPool.RETURN)) {
192
193 hasLineBreak = true;
194
195 break;
196 }
197
198 y++;
199 }
200
201 String line = new String(buffer, x, y - x);
202
203 index = y;
204
205 if (hasLineBreak) {
206 index++;
207
208 if (lineEndChar == CharPool.RETURN) {
209 if ((index < buffer.length) &&
210 (buffer[index] == CharPool.NEW_LINE)) {
211
212 index++;
213 }
214 }
215
216 if (sb == null) {
217 return line;
218 }
219 else {
220 sb.append(line);
221
222 return sb.toString();
223 }
224 }
225
226 if (sb == null) {
227 sb = new StringBundler();
228 }
229
230 sb.append(line);
231 }
232 }
233
234 @Override
235 public boolean ready() throws IOException {
236 if (reader == null) {
237 throw new IOException("Reader is null");
238 }
239
240 return (index < firstInvalidIndex) || reader.ready();
241 }
242
243 @Override
244 public void reset() throws IOException {
245 if (reader == null) {
246 throw new IOException("Reader is null");
247 }
248
249 if (markLimitIndex < 0) {
250 throw new IOException("Resetting to invalid mark");
251 }
252
253 index = 0;
254 }
255
256 @Override
257 public long skip(long skip) throws IOException {
258 if (skip < 0) {
259 throw new IllegalArgumentException("Skip is less than 0");
260 }
261
262 if (reader == null) {
263 throw new IOException("Reader is null");
264 }
265
266 if (skip == 0) {
267 return 0;
268 }
269
270 long available = firstInvalidIndex - index;
271
272 if (available <= 0) {
273 if (markLimitIndex < 0) {
274
275
276
277 return reader.skip(skip);
278 }
279 else {
280
281
282
283 fillInBuffer();
284
285 available = firstInvalidIndex - index;
286
287 if (available <= 0) {
288 return 0;
289 }
290 }
291 }
292
293
294
295 if (available < skip) {
296 skip = available;
297 }
298
299 index += skip;
300
301 return skip;
302 }
303
304 protected void fillInBuffer() throws IOException {
305 if (markLimitIndex < 0) {
306
307
308
309 index = firstInvalidIndex = 0;
310
311 int number = reader.read(buffer);
312
313 if (number > 0) {
314 firstInvalidIndex = number;
315 }
316
317 return;
318 }
319
320
321
322 if (index >= markLimitIndex) {
323
324
325
326 markLimitIndex = -1;
327
328 index = firstInvalidIndex = 0;
329 }
330 else if (index == buffer.length) {
331
332
333
334
335 int newBufferSize = buffer.length * 2;
336
337 if (newBufferSize > markLimitIndex) {
338 newBufferSize = markLimitIndex;
339 }
340
341 char[] newBuffer = new char[newBufferSize];
342
343 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
344
345 buffer = newBuffer;
346 }
347
348
349
350 firstInvalidIndex = index;
351
352 int number = reader.read(buffer, index, buffer.length - index);
353
354 if (number > 0) {
355 firstInvalidIndex += number;
356 }
357 }
358
359 protected int readOnce(char[] chars, int offset, int length)
360 throws IOException {
361
362 int available = firstInvalidIndex - index;
363
364 if (available <= 0) {
365
366
367
368 if ((markLimitIndex < 0) && (length >= buffer.length)) {
369
370
371
372
373
374 return reader.read(chars, offset, length);
375 }
376 else {
377
378
379
380
381 fillInBuffer();
382
383 available = firstInvalidIndex - index;
384
385 if (available <= 0) {
386 return -1;
387 }
388 }
389 }
390
391 if (length > available) {
392 length = available;
393 }
394
395 System.arraycopy(buffer, index, chars, offset, length);
396
397 index += length;
398
399 return length;
400 }
401
402 protected char[] buffer;
403 protected int firstInvalidIndex;
404 protected int index;
405 protected int markLimitIndex = -1;
406 protected Reader reader;
407
408 private static final int _DEFAULT_BUFFER_SIZE = 8192;
409
410 }