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 if ((index < firstInvalidIndex) || reader.ready()) {
242 return true;
243 }
244
245 return false;
246 }
247
248 @Override
249 public void reset() throws IOException {
250 if (reader == null) {
251 throw new IOException("Reader is null");
252 }
253
254 if (markLimitIndex < 0) {
255 throw new IOException("Resetting to invalid mark");
256 }
257
258 index = 0;
259 }
260
261 @Override
262 public long skip(long skip) throws IOException {
263 if (skip < 0) {
264 throw new IllegalArgumentException("Skip is less than 0");
265 }
266
267 if (reader == null) {
268 throw new IOException("Reader is null");
269 }
270
271 if (skip == 0) {
272 return 0;
273 }
274
275 long available = firstInvalidIndex - index;
276
277 if (available <= 0) {
278 if (markLimitIndex < 0) {
279
280
281
282 return reader.skip(skip);
283 }
284 else {
285
286
287
288 fillInBuffer();
289
290 available = firstInvalidIndex - index;
291
292 if (available <= 0) {
293 return 0;
294 }
295 }
296 }
297
298
299
300 if (available < skip) {
301 skip = available;
302 }
303
304 index += skip;
305
306 return skip;
307 }
308
309 protected void fillInBuffer() throws IOException {
310 if (markLimitIndex < 0) {
311
312
313
314 index = firstInvalidIndex = 0;
315
316 int number = reader.read(buffer);
317
318 if (number > 0) {
319 firstInvalidIndex = number;
320 }
321
322 return;
323 }
324
325
326
327 if (index >= markLimitIndex) {
328
329
330
331 markLimitIndex = -1;
332
333 index = firstInvalidIndex = 0;
334 }
335 else if (index == buffer.length) {
336
337
338
339
340 int newBufferSize = buffer.length * 2;
341
342 if (newBufferSize > markLimitIndex) {
343 newBufferSize = markLimitIndex;
344 }
345
346 char[] newBuffer = new char[newBufferSize];
347
348 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
349
350 buffer = newBuffer;
351 }
352
353
354
355 firstInvalidIndex = index;
356
357 int number = reader.read(buffer, index, buffer.length - index);
358
359 if (number > 0) {
360 firstInvalidIndex += number;
361 }
362 }
363
364 protected int readOnce(char[] chars, int offset, int length)
365 throws IOException {
366
367 int available = firstInvalidIndex - index;
368
369 if (available <= 0) {
370
371
372
373 if ((markLimitIndex < 0) && (length >= buffer.length)) {
374
375
376
377
378
379 return reader.read(chars, offset, length);
380 }
381 else {
382
383
384
385
386 fillInBuffer();
387
388 available = firstInvalidIndex - index;
389
390 if (available <= 0) {
391 return -1;
392 }
393 }
394 }
395
396 if (length > available) {
397 length = available;
398 }
399
400 System.arraycopy(buffer, index, chars, offset, length);
401
402 index += length;
403
404 return length;
405 }
406
407 protected char[] buffer;
408 protected int firstInvalidIndex;
409 protected int index;
410 protected int markLimitIndex = -1;
411 protected Reader reader;
412
413 private static final int _DEFAULT_BUFFER_SIZE = 8192;
414
415 }