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