1 19 20 21 27 42 package com.sslexplorer.core; 43 44 import java.io.ByteArrayInputStream ; 45 import java.io.FilterInputStream ; 46 import java.io.IOException ; 47 import java.io.InputStream ; 48 import java.io.InputStreamReader ; 49 import java.io.UnsupportedEncodingException ; 50 51 import org.apache.commons.logging.Log; 52 import org.apache.commons.logging.LogFactory; 53 54 55 76 public class LineInput extends FilterInputStream { 77 private static Log log = LogFactory.getLog(LineInput.class); 78 79 80 private byte _buf[]; 81 private ByteBuffer _byteBuffer; 82 private InputStreamReader _reader; 83 private int _mark = -1; private int _pos; private int _avail; private int _contents; private int _byteLimit = -1; 88 private boolean _newByteLimit; 89 private LineBuffer _lineBuffer; 90 private String _encoding; 91 private boolean _eof = false; 92 private boolean _lastCr = false; 93 private boolean _seenCrLf = false; 94 95 private final static int LF = 10; 96 private final static int CR = 13; 97 98 99 104 public LineInput(InputStream in) { 105 this(in, 0); 106 } 107 108 109 115 public LineInput(InputStream in, int bufferSize) { 116 super(in); 117 _mark = -1; 118 if (bufferSize == 0) 119 bufferSize = 8192; 120 _buf = ByteArrayPool.getByteArray(bufferSize); 121 _byteBuffer = new ByteBuffer(_buf); 122 _lineBuffer = new LineBuffer(bufferSize); 123 _reader = new InputStreamReader (_byteBuffer); 124 } 125 126 127 135 public LineInput(InputStream in, int bufferSize, String encoding) throws UnsupportedEncodingException { 136 super(in); 137 _mark = -1; 138 if (bufferSize == 0) 139 bufferSize = 2048; 140 _buf = ByteArrayPool.getByteArray(bufferSize); 141 _byteBuffer = new ByteBuffer(_buf); 142 _lineBuffer = new LineBuffer(bufferSize); 143 _reader = new InputStreamReader (_byteBuffer, encoding); 144 _encoding = encoding; 145 } 146 147 148 public InputStream getInputStream() { 149 return in; 150 } 151 152 153 159 public void setByteLimit(int bytes) { 160 _byteLimit = bytes; 161 162 if (bytes >= 0) { 163 _newByteLimit = true; 164 _byteLimit -= _contents - _pos; 165 if (_byteLimit < 0) { 166 _avail += _byteLimit; 167 _byteLimit = 0; 168 } 169 } else { 170 _newByteLimit = false; 171 _avail = _contents; 172 _eof = false; 173 } 174 } 175 176 177 182 public int getByteLimit() { 183 if (_byteLimit < 0) 184 return _byteLimit; 185 186 return _byteLimit + _avail - _pos; 187 } 188 189 190 197 public synchronized String readLine() throws IOException { 198 int len = fillLine(_buf.length); 199 200 if (len < 0) 201 return null; 202 203 String s = null; 204 if (_encoding == null) 205 s = new String (_buf, _mark, len); 206 else { 207 try { 208 s = new String (_buf, _mark, len, _encoding); 209 } catch (UnsupportedEncodingException e) { 210 log.warn(e); 211 } 212 } 213 _mark = -1; 214 215 return s; 216 } 217 218 219 229 public int readLine(char[] c, int off, int len) throws IOException { 230 int blen = fillLine(len); 231 232 if (blen < 0) 233 return -1; 234 if (blen == 0) 235 return 0; 236 237 _byteBuffer.setStream(_mark, blen); 238 239 int read = 0; 240 while (read < len && _reader.ready()) { 241 int r = _reader.read(c, off + read, len - read); 242 if (r <= 0) 243 break; 244 read += r; 245 } 246 247 _mark = -1; 248 249 return read; 250 } 251 252 253 262 public int readLine(byte[] b, int off, int len) throws IOException { 263 len = fillLine(len); 264 265 if (len < 0) 266 return -1; 267 if (len == 0) 268 return 0; 269 270 System.arraycopy(_buf, _mark, b, off, len); 271 _mark = -1; 272 273 return len; 274 } 275 276 277 286 public LineBuffer readLineBuffer() throws IOException { 287 return readLineBuffer(_buf.length); 288 } 289 290 291 301 public LineBuffer readLineBuffer(int len) throws IOException { 302 len = fillLine(len > 0 ? len : _buf.length); 303 304 if (len < 0) 305 return null; 306 307 if (len == 0) { 308 _lineBuffer.size = 0; 309 return _lineBuffer; 310 } 311 312 _byteBuffer.setStream(_mark, len); 313 314 _lineBuffer.size = 0; 315 int read = 0; 316 while (read < len && _reader.ready()) { 317 int r = _reader.read(_lineBuffer.buffer, read, len - read); 318 if (r <= 0) 319 break; 320 read += r; 321 } 322 _lineBuffer.size = read; 323 _mark = -1; 324 325 return _lineBuffer; 326 } 327 328 329 public synchronized int read() throws IOException { 330 int b; 331 if (_pos >= _avail) 332 fill(); 333 if (_pos >= _avail) 334 b = -1; 335 else 336 b = _buf[_pos++] & 255; 337 338 return b; 339 } 340 341 342 public synchronized int read(byte b[], int off, int len) throws IOException { 343 int avail = _avail - _pos; 344 if (avail <= 0) { 345 fill(); 346 avail = _avail - _pos; 347 } 348 349 if (avail <= 0) 350 len = -1; 351 else { 352 len = (avail < len) ? avail : len; 353 System.arraycopy(_buf, _pos, b, off, len); 354 _pos += len; 355 } 356 357 return len; 358 } 359 360 361 public long skip(long n) throws IOException { 362 int avail = _avail - _pos; 363 if (avail <= 0) { 364 fill(); 365 avail = _avail - _pos; 366 } 367 368 if (avail <= 0) 369 n = 0; 370 else { 371 n = (avail < n) ? avail : n; 372 _pos += n; 373 } 374 375 return n; 376 } 377 378 379 public synchronized int available() throws IOException { 380 int in_stream = in.available(); 381 if (_byteLimit >= 0 && in_stream > _byteLimit) 382 in_stream = _byteLimit; 383 384 return _avail - _pos + in_stream; 385 } 386 387 388 public synchronized void mark(int limit) throws IllegalArgumentException { 389 if (limit > _buf.length) { 390 byte[] new_buf = new byte[limit]; 391 System.arraycopy(_buf, _pos, new_buf, _pos, _avail - _pos); 392 _buf = new_buf; 393 if (_byteBuffer != null) 394 _byteBuffer.setBuffer(_buf); 395 } 396 _mark = _pos; 397 } 398 399 400 public synchronized void reset() throws IOException { 401 if (_mark < 0) 402 throw new IOException ("Resetting to invalid mark"); 403 _pos = _mark; 404 _mark = -1; 405 } 406 407 408 public boolean markSupported() { 409 return true; 410 } 411 412 413 private void fill() throws IOException { 414 if (_mark > 0) { 416 int saved = _contents - _mark; 418 System.arraycopy(_buf, _mark, _buf, 0, saved); 419 _pos -= _mark; 420 _avail -= _mark; 421 _contents = saved; 422 _mark = 0; 423 } else if (_mark < 0 && _pos > 0) { 424 int saved = _contents - _pos; 426 System.arraycopy(_buf, _pos, _buf, 0, saved); 427 _avail -= _pos; 428 _contents = saved; 429 _pos = 0; 430 } else if (_mark == 0 && _pos > 0 && _contents == _buf.length) { 431 _mark = -1; 433 fill(); 434 return; 435 } 436 437 int n = 0; 439 _eof = false; 440 441 if (_byteLimit == 0) 443 _eof = true; 444 else 446 while (!_eof && n == 0 && _buf.length > _contents) { 447 int space = _buf.length - _contents; 449 450 n = in.read(_buf, _contents, space); 451 452 if (n <= 0) { 453 if (n == 0) { 456 Thread.yield(); 458 459 int b = in.read(); 461 if (b >= 0) { 462 n = 1; 463 _buf[_contents++] = (byte) b; 464 } else 465 _eof = true; 466 } else 467 _eof = true; 468 } else 469 _contents += n; 470 _avail = _contents; 471 472 if (_byteLimit > 0) { 474 if (_contents - _pos >= _byteLimit) 476 _avail = _byteLimit + _pos; 477 478 if (n > _byteLimit) 479 _byteLimit = 0; 480 else if (n >= 0) 481 _byteLimit -= n; 482 else if (n == -1) 483 throw new IOException ("Premature EOF"); 484 } 485 } 486 487 if (_avail - _pos > 0 && _lastCr && _buf[_pos] == LF) { 490 _seenCrLf = true; 491 _pos++; 492 if (_mark >= 0) 493 _mark++; 494 _lastCr = false; 495 496 if (_byteLimit >= 0 && _newByteLimit) { 499 if (_avail < _contents) 500 _avail++; 501 else 502 _byteLimit++; 503 } 504 if (_pos == _avail) 506 fill(); 507 } 508 _newByteLimit = false; 509 } 510 511 512 private int fillLine(int maxLen) throws IOException { 513 _mark = _pos; 514 515 if (_pos >= _avail) 516 fill(); 517 if (_pos >= _avail) 518 return -1; 519 520 byte b; 521 boolean cr = _lastCr; 522 boolean lf = false; 523 _lastCr = false; 524 int len = 0; 525 526 LineLoop: while (_pos <= _avail) { 527 while (_pos == _avail) { 529 if (_eof || (_mark == 0 && _contents == _buf.length)) { 532 _lastCr = !_eof && _buf[_avail - 1] == CR; 533 534 cr = true; 535 lf = true; 536 break LineLoop; 537 } 538 539 if (cr && in.available() == 0 && !_seenCrLf) { 541 _lastCr = true; 542 cr = true; 543 lf = true; 544 break LineLoop; 545 } else { 546 _pos = _mark; 548 fill(); 549 _pos = len; 550 cr = false; 551 } 552 } 553 554 b = _buf[_pos++]; 556 557 switch (b) { 558 case LF: 559 if (cr) 560 _seenCrLf = true; 561 lf = true; 562 break LineLoop; 563 564 case CR: 565 if (cr) { 566 if (_pos > 1) { 568 _pos--; 569 break LineLoop; 570 } 571 } 572 cr = true; 573 break; 574 575 default: 576 if (cr) { 577 if (_pos == 1) 578 cr = false; 579 else { 580 _pos--; 581 break LineLoop; 582 } 583 } 584 585 len++; 586 if (len == maxLen) { 587 if (_mark != 0 && _pos + 2 >= _avail && _avail < _buf.length) 589 fill(); 590 591 if (_pos < _avail && _buf[_pos] == CR) { 592 cr = true; 593 _pos++; 594 } 595 if (_pos < _avail && _buf[_pos] == LF) { 596 lf = true; 597 _pos++; 598 } 599 600 if (!cr && !lf) { 601 lf = true; 603 cr = true; 604 } 605 break LineLoop; 606 } 607 608 break; 609 } 610 } 611 612 if (!cr && !lf && len == 0) 613 len = -1; 614 615 return len; 616 } 617 618 619 private static class ByteBuffer extends ByteArrayInputStream { 620 ByteBuffer(byte[] buffer) { 621 super(buffer); 622 } 623 624 void setBuffer(byte[] buffer) { 625 buf = buffer; 626 } 627 628 void setStream(int offset, int length) { 629 pos = offset; 630 count = offset + length; 631 mark = -1; 632 } 633 } 634 635 636 639 public static class LineBuffer { 640 public char[] buffer; 641 public int size; 642 643 public LineBuffer(int maxLineLength) { 644 buffer = new char[maxLineLength]; 645 } 646 647 public String toString() { 648 return new String (buffer, 0, size); 649 } 650 } 651 652 653 public void destroy() { 654 ByteArrayPool.returnByteArray(_buf); 655 _byteBuffer = null; 656 _reader = null; 657 _lineBuffer = null; 658 _encoding = null; 659 } 660 661 } 662 | Popular Tags |