1
22
23 package com.liferay.portal.kernel.io.unsync;
24
25 import com.liferay.portal.kernel.util.CharPool;
26 import com.liferay.portal.kernel.util.StringBundler;
27
28 import java.io.IOException;
29 import java.io.Reader;
30
31
40 public class UnsyncBufferedReader extends Reader {
41
42 public UnsyncBufferedReader(Reader reader) {
43 this(reader, _DEFAULT_BUFFER_SIZE);
44 }
45
46 public UnsyncBufferedReader(Reader reader, int size) {
47 this.reader = reader;
48 buffer = new char[size];
49 }
50
51 public void close() throws IOException {
52 if (reader != null) {
53 reader.close();
54
55 reader = null;
56 }
57
58 buffer = null;
59 }
60
61 public void mark(int markLimit) throws IOException {
62 if (reader == null) {
63 throw new IOException("Reader is null");
64 }
65
66 this.markLimit = markLimit;
67 markIndex = index;
68 }
69
70 public boolean markSupported() {
71 return true;
72 }
73
74 public int read() throws IOException {
75 if (reader == null) {
76 throw new IOException("Reader is null");
77 }
78
79 if (index >= firstInvalidIndex) {
80 readUnderlyingReader();
81
82 if (index >= firstInvalidIndex) {
83 return -1;
84 }
85 }
86
87 return buffer[index++];
88 }
89
90 public int read(char[] charArray) throws IOException {
91 return read(charArray, 0, charArray.length);
92 }
93
94 public int read(char[] charArray, int offset, int length)
95 throws IOException {
96
97 if (reader == null) {
98 throw new IOException("Reader is null");
99 }
100
101 if (length <= 0) {
102 return 0;
103 }
104
105 int read = 0;
106
107 while (true) {
108 int available = firstInvalidIndex - index;
109
110 if ((available + read) >= length) {
111
112
114 int leftSize = length - read;
115
116 System.arraycopy(buffer, index, charArray, read, leftSize);
117
118 index += leftSize;
119
120 return length;
121 }
122
123 if (available <= 0) {
124
125
127 readUnderlyingReader();
128
129 available = firstInvalidIndex - index;
130
131 if (available <= 0) {
132
133
135 if (read == 0) {
136 return -1;
137 }
138 else {
139 return read;
140 }
141 }
142 }
143 else {
144
145
147 System.arraycopy(buffer, index, charArray, read, available);
148
149 index += available;
150 read += available;
151 }
152 }
153 }
154
155 public String readLine() throws IOException {
156 if (reader == null) {
157 throw new IOException("Reader is null");
158 }
159
160 StringBundler sb = null;
161
162 while (true) {
163 if (index >= firstInvalidIndex) {
164 readUnderlyingReader();
165 }
166
167 if (index >= firstInvalidIndex) {
168 if ((sb != null) && (sb.index() > 0)) {
169 return sb.toString();
170 }
171 else {
172 return null;
173 }
174 }
175
176 boolean hasLineBreak = false;
177 char lineEndChar = 0;
178
179 int x = index;
180 int y = index;
181
182 while (y < firstInvalidIndex) {
183 lineEndChar = buffer[y];
184
185 if ((lineEndChar == CharPool.NEW_LINE) ||
186 (lineEndChar == CharPool.RETURN)) {
187
188 hasLineBreak = true;
189
190 break;
191 }
192
193 y++;
194 }
195
196 String line = new String(buffer, x, y - x);
197
198 index = y;
199
200 if (hasLineBreak) {
201 index++;
202
203 if (lineEndChar == CharPool.RETURN) {
204 if ((index < buffer.length) &&
205 (buffer[index] == CharPool.NEW_LINE)) {
206
207 index++;
208 }
209 }
210
211 if (sb == null) {
212 return line;
213 }
214 else {
215 sb.append(line);
216
217 return sb.toString();
218 }
219 }
220
221 if (sb == null) {
222 sb = new StringBundler();
223 }
224
225 sb.append(line);
226 }
227 }
228
229 public boolean ready() throws IOException {
230 if (reader == null) {
231 throw new IOException("Reader is null");
232 }
233
234 return (index < firstInvalidIndex) || reader.ready();
235 }
236
237 public void reset() throws IOException {
238 if (reader == null) {
239 throw new IOException("Reader is null");
240 }
241
242 if (markIndex < 0) {
243 throw new IOException("Resetting to invalid mark");
244 }
245
246 index = markIndex;
247 }
248
249 public long skip(long skip) throws IOException {
250 if (reader == null) {
251 throw new IOException("Reader is null");
252 }
253
254 if (skip <= 0) {
255 return 0;
256 }
257
258 long available = firstInvalidIndex - index;
259
260 if (available > 0) {
261
262
264 if (available < skip) {
265 skip = available;
266 }
267 }
268 else {
269
270
272 if (markIndex < 0) {
273
274
276 skip = reader.skip(skip);
277 }
278 else {
279
280
282 readUnderlyingReader();
283
284 available = firstInvalidIndex - index;
285
286 if (available > 0) {
287
288
290 if (available < skip) {
291 skip = available;
292 }
293 }
294 }
295 }
296
297 index += skip;
298
299 return skip;
300 }
301
302 protected void readUnderlyingReader() throws IOException {
303 if (markIndex < 0) {
304
305
307 index = firstInvalidIndex = 0;
308
309 int number = reader.read(buffer);
310
311 if (number > 0) {
312 firstInvalidIndex = number;
313 }
314
315 return;
316 }
317
318
320 if (index >= buffer.length) {
321
322
324 if ((firstInvalidIndex - markIndex) > markLimit) {
325
326
328 markIndex = -1;
329 index = 0;
330 }
331 else if (markIndex > _MAX_MARK_WASTE_SIZE) {
332
333
336 int realDataSize = index - markIndex;
337
338 System.arraycopy(
339 buffer, markIndex, buffer, 0, realDataSize);
340
341 markIndex = 0;
342 index = realDataSize;
343 }
344 else {
345
346
349 int newBufferSize = index << 1;
350
351 if ((newBufferSize - _MAX_MARK_WASTE_SIZE) > markLimit) {
352
353
355 newBufferSize = markLimit + _MAX_MARK_WASTE_SIZE;
356 }
357
358 char[] newBuffer = new char[newBufferSize];
359
360 System.arraycopy(buffer, 0, newBuffer, 0, index);
361
362 buffer = newBuffer;
363 }
364 }
365
366
368 firstInvalidIndex = index;
369
370 int number = reader.read(buffer, index, buffer.length - index);
371
372 if (number > 0) {
373 firstInvalidIndex += number;
374 }
375 }
376
377 protected char[] buffer;
378 protected int firstInvalidIndex;
379 protected int index;
380 protected int markIndex = -1;
381 protected int markLimit;
382 protected Reader reader;
383
384 private static int _DEFAULT_BUFFER_SIZE = 8192;
385
386 private static int _MAX_MARK_WASTE_SIZE = 4096;
387
388 }