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