1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.impl.nio;
29
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.RandomAccessFile;
33 import java.nio.ByteBuffer;
34 import java.nio.channels.FileChannel;
35 import java.nio.channels.ReadableByteChannel;
36 import java.nio.charset.StandardCharsets;
37
38 import org.apache.hc.core5.http.ConnectionClosedException;
39 import org.apache.hc.core5.http.ReadableByteChannelMock;
40 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
41 import org.apache.hc.core5.http.nio.SessionInputBuffer;
42 import org.junit.jupiter.api.AfterEach;
43 import org.junit.jupiter.api.Assertions;
44 import org.junit.jupiter.api.Test;
45
46
47
48
49 public class TestLengthDelimitedDecoder {
50
51 private File tmpfile;
52
53 protected File createTempFile() throws IOException {
54 this.tmpfile = File.createTempFile("testFile", ".txt");
55 return this.tmpfile;
56 }
57
58 @AfterEach
59 public void deleteTempFile() {
60 if (this.tmpfile != null && this.tmpfile.exists()) {
61 this.tmpfile.delete();
62 }
63 }
64
65 @Test
66 public void testBasicDecoding() throws Exception {
67 final ReadableByteChannel channel = new ReadableByteChannelMock(
68 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
69
70 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
71 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
72 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
73 channel, inbuf, metrics, 16);
74
75 final ByteBuffer dst = ByteBuffer.allocate(1024);
76
77 int bytesRead = decoder.read(dst);
78 Assertions.assertEquals(6, bytesRead);
79 Assertions.assertEquals("stuff;", CodecTestUtils.convert(dst));
80 Assertions.assertFalse(decoder.isCompleted());
81 Assertions.assertEquals(6, metrics.getBytesTransferred());
82
83 dst.clear();
84 bytesRead = decoder.read(dst);
85 Assertions.assertEquals(10, bytesRead);
86 Assertions.assertEquals("more stuff", CodecTestUtils.convert(dst));
87 Assertions.assertTrue(decoder.isCompleted());
88 Assertions.assertEquals(16, metrics.getBytesTransferred());
89
90 dst.clear();
91 bytesRead = decoder.read(dst);
92 Assertions.assertEquals(-1, bytesRead);
93 Assertions.assertTrue(decoder.isCompleted());
94 Assertions.assertEquals(16, metrics.getBytesTransferred());
95
96 Assertions.assertEquals("[content length: 16; pos: 16; completed: true]", decoder.toString());
97 }
98
99 @Test
100 public void testCodingBeyondContentLimit() throws Exception {
101 final ReadableByteChannel channel = new ReadableByteChannelMock(
102 new String[] {
103 "stuff;",
104 "more stuff; and a lot more stuff"}, StandardCharsets.US_ASCII);
105
106 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
107 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
108 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
109 channel, inbuf, metrics, 16);
110
111 final ByteBuffer dst = ByteBuffer.allocate(1024);
112
113 int bytesRead = decoder.read(dst);
114 Assertions.assertEquals(6, bytesRead);
115 Assertions.assertEquals("stuff;", CodecTestUtils.convert(dst));
116 Assertions.assertFalse(decoder.isCompleted());
117 Assertions.assertEquals(6, metrics.getBytesTransferred());
118
119 dst.clear();
120 bytesRead = decoder.read(dst);
121 Assertions.assertEquals(10, bytesRead);
122 Assertions.assertEquals("more stuff", CodecTestUtils.convert(dst));
123 Assertions.assertTrue(decoder.isCompleted());
124 Assertions.assertEquals(16, metrics.getBytesTransferred());
125
126 dst.clear();
127 bytesRead = decoder.read(dst);
128 Assertions.assertEquals(-1, bytesRead);
129 Assertions.assertTrue(decoder.isCompleted());
130 Assertions.assertEquals(16, metrics.getBytesTransferred());
131 }
132
133 @Test
134 public void testBasicDecodingSmallBuffer() throws Exception {
135 final ReadableByteChannel channel = new ReadableByteChannelMock(
136 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
137
138 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
139 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
140 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
141 channel, inbuf, metrics, 16);
142
143 final ByteBuffer dst = ByteBuffer.allocate(4);
144
145 int bytesRead = decoder.read(dst);
146 Assertions.assertEquals(4, bytesRead);
147 Assertions.assertEquals("stuf", CodecTestUtils.convert(dst));
148 Assertions.assertFalse(decoder.isCompleted());
149 Assertions.assertEquals(4, metrics.getBytesTransferred());
150
151 dst.clear();
152 bytesRead = decoder.read(dst);
153 Assertions.assertEquals(2, bytesRead);
154 Assertions.assertEquals("f;", CodecTestUtils.convert(dst));
155 Assertions.assertFalse(decoder.isCompleted());
156 Assertions.assertEquals(6, metrics.getBytesTransferred());
157
158 dst.clear();
159 bytesRead = decoder.read(dst);
160 Assertions.assertEquals(4, bytesRead);
161 Assertions.assertEquals("more", CodecTestUtils.convert(dst));
162 Assertions.assertFalse(decoder.isCompleted());
163 Assertions.assertEquals(10, metrics.getBytesTransferred());
164
165 dst.clear();
166 bytesRead = decoder.read(dst);
167 Assertions.assertEquals(4, bytesRead);
168 Assertions.assertEquals(" stu", CodecTestUtils.convert(dst));
169 Assertions.assertFalse(decoder.isCompleted());
170 Assertions.assertEquals(14, metrics.getBytesTransferred());
171
172 dst.clear();
173 bytesRead = decoder.read(dst);
174 Assertions.assertEquals(2, bytesRead);
175 Assertions.assertEquals("ff", CodecTestUtils.convert(dst));
176 Assertions.assertTrue(decoder.isCompleted());
177 Assertions.assertEquals(16, metrics.getBytesTransferred());
178
179 dst.clear();
180 bytesRead = decoder.read(dst);
181 Assertions.assertEquals(-1, bytesRead);
182 Assertions.assertTrue(decoder.isCompleted());
183 Assertions.assertEquals(16, metrics.getBytesTransferred());
184 }
185
186 @Test
187 public void testDecodingFromSessionBuffer1() throws Exception {
188 final ReadableByteChannel channel = new ReadableByteChannelMock(
189 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
190
191 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
192 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
193
194 inbuf.fill(channel);
195
196 Assertions.assertEquals(6, inbuf.length());
197
198 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
199 channel, inbuf, metrics, 16);
200
201 final ByteBuffer dst = ByteBuffer.allocate(1024);
202
203 int bytesRead = decoder.read(dst);
204 Assertions.assertEquals(6, bytesRead);
205 Assertions.assertEquals("stuff;", CodecTestUtils.convert(dst));
206 Assertions.assertFalse(decoder.isCompleted());
207 Assertions.assertEquals(0, metrics.getBytesTransferred());
208
209 dst.clear();
210 bytesRead = decoder.read(dst);
211 Assertions.assertEquals(10, bytesRead);
212 Assertions.assertEquals("more stuff", CodecTestUtils.convert(dst));
213 Assertions.assertTrue(decoder.isCompleted());
214 Assertions.assertEquals(10, metrics.getBytesTransferred());
215
216 dst.clear();
217 bytesRead = decoder.read(dst);
218 Assertions.assertEquals(-1, bytesRead);
219 Assertions.assertTrue(decoder.isCompleted());
220 Assertions.assertEquals(10, metrics.getBytesTransferred());
221 }
222
223 @Test
224 public void testDecodingFromSessionBuffer2() throws Exception {
225 final ReadableByteChannel channel = new ReadableByteChannelMock(
226 new String[] {
227 "stuff;",
228 "more stuff; and a lot more stuff"}, StandardCharsets.US_ASCII);
229
230 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
231 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
232
233 inbuf.fill(channel);
234 inbuf.fill(channel);
235
236 Assertions.assertEquals(38, inbuf.length());
237
238 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
239 channel, inbuf, metrics, 16);
240
241 final ByteBuffer dst = ByteBuffer.allocate(1024);
242
243 int bytesRead = decoder.read(dst);
244 Assertions.assertEquals(16, bytesRead);
245 Assertions.assertEquals("stuff;more stuff", CodecTestUtils.convert(dst));
246 Assertions.assertTrue(decoder.isCompleted());
247 Assertions.assertEquals(0, metrics.getBytesTransferred());
248
249 dst.clear();
250 bytesRead = decoder.read(dst);
251 Assertions.assertEquals(-1, bytesRead);
252 Assertions.assertTrue(decoder.isCompleted());
253 Assertions.assertEquals(0, metrics.getBytesTransferred());
254 }
255
256
257 @Test
258 public void testBasicDecodingFile() throws Exception {
259 final ReadableByteChannel channel = new ReadableByteChannelMock(
260 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!!!"}, StandardCharsets.US_ASCII);
261
262 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
263 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
264 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
265 channel, inbuf, metrics, 36);
266
267 createTempFile();
268 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
269 final FileChannel fchannel = testfile.getChannel();
270 long pos = 0;
271 while (!decoder.isCompleted()) {
272 final long bytesRead = decoder.transfer(fchannel, pos, 10);
273 if (bytesRead > 0) {
274 pos += bytesRead;
275 }
276 }
277 }
278 Assertions.assertEquals(this.tmpfile.length(), metrics.getBytesTransferred());
279 Assertions.assertEquals("stuff; more stuff; a lot more stuff!",
280 CodecTestUtils.readFromFile(this.tmpfile));
281 }
282
283 @Test
284 public void testDecodingFileWithBufferedSessionData() throws Exception {
285 final ReadableByteChannel channel = new ReadableByteChannelMock(
286 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!!!"}, StandardCharsets.US_ASCII);
287
288 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
289 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
290 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
291 channel, inbuf, metrics, 36);
292
293 final int i = inbuf.fill(channel);
294 Assertions.assertEquals(7, i);
295
296 createTempFile();
297 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
298 final FileChannel fchannel = testfile.getChannel();
299 long pos = 0;
300 while (!decoder.isCompleted()) {
301 final long bytesRead = decoder.transfer(fchannel, pos, 10);
302 if (bytesRead > 0) {
303 pos += bytesRead;
304 }
305 }
306 }
307 Assertions.assertEquals(this.tmpfile.length() - 7, metrics.getBytesTransferred());
308 Assertions.assertEquals("stuff; more stuff; a lot more stuff!",
309 CodecTestUtils.readFromFile(this.tmpfile));
310 }
311
312 @Test
313 public void testDecodingFileWithOffsetAndBufferedSessionData() throws Exception {
314 final ReadableByteChannel channel = new ReadableByteChannelMock(
315 new String[] {"stuff; ", "more stuff; ", "a lot more stuff!"}, StandardCharsets.US_ASCII);
316
317 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
318 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
319 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
320 channel, inbuf, metrics, 36);
321
322 final int i = inbuf.fill(channel);
323 Assertions.assertEquals(7, i);
324
325 final byte[] beginning = "beginning; ".getBytes(StandardCharsets.US_ASCII);
326
327 createTempFile();
328 RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
329 try {
330 testfile.write(beginning);
331 } finally {
332 testfile.close();
333 }
334
335 testfile = new RandomAccessFile(this.tmpfile, "rw");
336 try {
337 final FileChannel fchannel = testfile.getChannel();
338
339 long pos = beginning.length;
340 while (!decoder.isCompleted()) {
341 if(testfile.length() < pos) {
342 testfile.setLength(pos);
343 }
344 final long bytesRead = decoder.transfer(fchannel, pos, 10);
345 if (bytesRead > 0) {
346 pos += bytesRead;
347 }
348 }
349 } finally {
350 testfile.close();
351 }
352
353
354 Assertions.assertEquals(this.tmpfile.length() - 7 - beginning.length, metrics.getBytesTransferred());
355 Assertions.assertEquals("beginning; stuff; more stuff; a lot more stuff!",
356 CodecTestUtils.readFromFile(this.tmpfile));
357 }
358
359 @Test
360 public void testDecodingFileWithLimit() throws Exception {
361 final ReadableByteChannel channel = new ReadableByteChannelMock(
362 new String[] {"stuff; more stuff; ", "a lot more stuff!!!"}, StandardCharsets.US_ASCII);
363
364 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
365 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
366 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(channel, inbuf, metrics, 36);
367
368 final int i = inbuf.fill(channel);
369 Assertions.assertEquals(19, i);
370
371 createTempFile();
372 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
373 final FileChannel fchannel = testfile.getChannel();
374 long pos = 0;
375
376
377 long bytesRead = decoder.transfer(fchannel, pos, 1);
378 Assertions.assertEquals(1, bytesRead);
379 Assertions.assertFalse(decoder.isCompleted());
380 Assertions.assertEquals(0, metrics.getBytesTransferred());
381 pos += bytesRead;
382
383 bytesRead = decoder.transfer(fchannel, pos, 2);
384 Assertions.assertEquals(2, bytesRead);
385 Assertions.assertFalse(decoder.isCompleted());
386 Assertions.assertEquals(0, metrics.getBytesTransferred());
387 pos += bytesRead;
388
389 bytesRead = decoder.transfer(fchannel, pos, 17);
390 Assertions.assertEquals(16, bytesRead);
391 Assertions.assertFalse(decoder.isCompleted());
392 Assertions.assertEquals(0, metrics.getBytesTransferred());
393 pos += bytesRead;
394
395
396 bytesRead = decoder.transfer(fchannel, pos, 1);
397 Assertions.assertEquals(1, bytesRead);
398 Assertions.assertFalse(decoder.isCompleted());
399 Assertions.assertEquals(1, metrics.getBytesTransferred());
400 pos += bytesRead;
401
402 bytesRead = decoder.transfer(fchannel, pos, 2);
403 Assertions.assertEquals(2, bytesRead);
404 Assertions.assertFalse(decoder.isCompleted());
405 Assertions.assertEquals(3, metrics.getBytesTransferred());
406 pos += bytesRead;
407
408 bytesRead = decoder.transfer(fchannel, pos, 15);
409 Assertions.assertEquals(14, bytesRead);
410 Assertions.assertTrue(decoder.isCompleted());
411 Assertions.assertEquals(17, metrics.getBytesTransferred());
412 pos += bytesRead;
413
414 bytesRead = decoder.transfer(fchannel, pos, 1);
415 Assertions.assertEquals(-1, bytesRead);
416 Assertions.assertTrue(decoder.isCompleted());
417 Assertions.assertEquals(17, metrics.getBytesTransferred());
418 }
419 Assertions.assertEquals("stuff; more stuff; a lot more stuff!",
420 CodecTestUtils.readFromFile(this.tmpfile));
421 }
422
423 @Test
424 public void testWriteBeyondFileSize() throws Exception {
425 final ReadableByteChannel channel = new ReadableByteChannelMock(
426 new String[] {"a"}, StandardCharsets.US_ASCII);
427
428 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
429 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
430 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
431 channel, inbuf, metrics, 1);
432
433 createTempFile();
434 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
435 final FileChannel fchannel = testfile.getChannel();
436 Assertions.assertEquals(0, testfile.length());
437 Assertions.assertThrows(IOException.class, () -> decoder.transfer(fchannel, 5, 10));
438 }
439 }
440
441 @Test
442 public void testCodingBeyondContentLimitFile() throws Exception {
443 final ReadableByteChannel channel = new ReadableByteChannelMock(
444 new String[] {
445 "stuff;",
446 "more stuff; and a lot more stuff"}, StandardCharsets.US_ASCII);
447
448 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
449 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
450 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
451 channel, inbuf, metrics, 16);
452
453 createTempFile();
454 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
455 final FileChannel fchannel = testfile.getChannel();
456
457 long bytesRead = decoder.transfer(fchannel, 0, 6);
458 Assertions.assertEquals(6, bytesRead);
459 Assertions.assertFalse(decoder.isCompleted());
460 Assertions.assertEquals(6, metrics.getBytesTransferred());
461
462 bytesRead = decoder.transfer(fchannel,0 , 10);
463 Assertions.assertEquals(10, bytesRead);
464 Assertions.assertTrue(decoder.isCompleted());
465 Assertions.assertEquals(16, metrics.getBytesTransferred());
466
467 bytesRead = decoder.transfer(fchannel, 0, 1);
468 Assertions.assertEquals(-1, bytesRead);
469 Assertions.assertTrue(decoder.isCompleted());
470 Assertions.assertEquals(16, metrics.getBytesTransferred());
471 }
472 }
473
474 @Test
475 public void testInvalidConstructor() {
476 final ReadableByteChannel channel = new ReadableByteChannelMock(
477 new String[] {"stuff;", "more stuff"}, StandardCharsets.US_ASCII);
478
479 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
480 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
481 Assertions.assertThrows(NullPointerException.class, () -> new LengthDelimitedDecoder(null, null, null, 10));
482 Assertions.assertThrows(NullPointerException.class, () -> new LengthDelimitedDecoder(channel, null, null, 10));
483 Assertions.assertThrows(NullPointerException.class, () -> new LengthDelimitedDecoder(channel, inbuf, null, 10));
484 Assertions.assertThrows(IllegalArgumentException.class, () -> new LengthDelimitedDecoder(channel, inbuf, metrics, -10));
485 }
486
487 @Test
488 public void testInvalidInput() throws Exception {
489 final String s = "stuff";
490 final ReadableByteChannel channel = new ReadableByteChannelMock(
491 new String[] {s}, StandardCharsets.US_ASCII);
492
493 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
494 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
495 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
496 channel, inbuf, metrics, 3);
497
498 Assertions.assertThrows(NullPointerException.class, () -> decoder.read(null));
499 }
500
501 @Test
502 public void testZeroLengthDecoding() throws Exception {
503 final ReadableByteChannel channel = new ReadableByteChannelMock(
504 new String[] {"stuff"}, StandardCharsets.US_ASCII);
505
506 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
507 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
508 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
509 channel, inbuf, metrics, 0);
510
511 final ByteBuffer dst = ByteBuffer.allocate(1024);
512
513 final int bytesRead = decoder.read(dst);
514 Assertions.assertEquals(-1, bytesRead);
515 Assertions.assertTrue(decoder.isCompleted());
516 Assertions.assertEquals(0, metrics.getBytesTransferred());
517 }
518
519 @Test
520 public void testTruncatedContent() throws Exception {
521 final ReadableByteChannel channel = new ReadableByteChannelMock(
522 new String[] {"1234567890"}, StandardCharsets.US_ASCII);
523
524 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
525 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
526 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
527 channel, inbuf, metrics, 20);
528
529 final ByteBuffer dst = ByteBuffer.allocate(1024);
530
531 final int bytesRead = decoder.read(dst);
532 Assertions.assertEquals(10, bytesRead);
533 Assertions.assertThrows(ConnectionClosedException.class, () ->
534 decoder.read(dst));
535 }
536
537 @Test
538 public void testTruncatedContentWithFile() throws Exception {
539 final ReadableByteChannel channel = new ReadableByteChannelMock(
540 new String[] {"1234567890"}, StandardCharsets.US_ASCII);
541
542 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
543 final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
544 final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(
545 channel, inbuf, metrics, 20);
546
547 createTempFile();
548 try (RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw")) {
549 final FileChannel fchannel = testfile.getChannel();
550 final long bytesRead = decoder.transfer(fchannel, 0, Integer.MAX_VALUE);
551 Assertions.assertEquals(10, bytesRead);
552 Assertions.assertThrows(ConnectionClosedException.class, () ->
553 decoder.transfer(fchannel, 0, Integer.MAX_VALUE));
554 }
555 }
556
557 }