1 28 29 package com.caucho.vfs; 30 31 import com.caucho.util.Alarm; 32 import com.caucho.util.CharBuffer; 33 34 import java.io.IOException ; 35 import java.io.InputStream ; 36 import java.io.OutputStream ; 37 import java.io.Reader ; 38 import java.io.UnsupportedEncodingException ; 39 import java.io.Writer ; 40 import java.util.Iterator ; 41 import java.util.logging.Level ; 42 import java.util.logging.Logger ; 43 44 58 public final class ReadStream extends InputStream { 59 public static int ZERO_COPY_SIZE = 1024; 60 61 private TempBuffer _tempRead; 62 private byte []_readBuffer; 63 private int _readOffset; 64 private int _readLength; 65 66 private WriteStream _sibling; 67 68 private StreamImpl _source; 69 private long _position; 70 71 private long _readTime; 72 73 private Reader _readEncoding; 74 private String _readEncodingName; 75 private int _specialEncoding; 76 77 private boolean _disableClose; 78 private boolean _isDisableCloseSource; 79 private boolean _reuseBuffer; 80 private Reader _reader; 81 82 85 public ReadStream() 86 { 87 } 88 89 94 public ReadStream(StreamImpl source) 95 { 96 init(source, null); 97 } 98 99 105 public ReadStream(StreamImpl source, WriteStream sibling) 106 { 107 init(source, sibling); 108 } 109 110 116 public void init(StreamImpl source, WriteStream sibling) 117 { 118 _disableClose = false; 119 _isDisableCloseSource = false; 120 _readTime = 0; 121 122 if (_source != null && _source != source) { 123 close(); 124 } 125 126 if (source == null) 127 throw new IllegalArgumentException (); 128 129 _source = source; 130 _sibling = sibling; 131 132 if (source.canRead()) { 133 if (_tempRead == null) { 134 _tempRead = TempBuffer.allocate(); 135 _readBuffer = _tempRead._buf; 136 } 137 } 138 _readOffset = 0; 139 _readLength = 0; 140 141 _readEncoding = null; 142 _readEncodingName = "ISO-8859-1"; 143 } 144 145 public void setSibling(WriteStream sibling) 146 { 147 _sibling = sibling; 148 } 149 150 public WriteStream getSibling() 151 { 152 return _sibling; 153 } 154 155 160 public StreamImpl getSource() 161 { 162 return _source; 163 } 164 165 public void setReuseBuffer(boolean reuse) 166 { 167 _reuseBuffer = reuse; 168 } 169 170 175 public void pushFilter(StreamFilter filter) 176 { 177 filter.init(_source); 178 _source = filter; 179 } 180 181 public byte []getBuffer() 182 { 183 return _readBuffer; 184 } 185 186 public int getOffset() 187 { 188 return _readOffset; 189 } 190 191 public int getLength() 192 { 193 return _readLength; 194 } 195 196 public void setOffset(int offset) 197 { 198 _readOffset = offset; 199 } 200 201 204 public long getPosition() 205 { 206 return _position - (_readLength - _readOffset); 207 } 208 209 212 public long getReadTime() 213 { 214 return _readTime; 215 } 216 217 220 public boolean setPosition(long pos) 221 throws IOException 222 { 223 if (_readEncoding != null) 225 _readEncoding = Encoding.getReadEncoding(this, _readEncodingName); 226 227 if (pos < _position) { 228 _position = pos; 229 _readLength = _readOffset = 0; 230 231 if (_source != null) { 232 _source.seekStart(pos); 233 234 return true; 235 } 236 else 237 return false; 238 } 239 else if (pos < _position + _readLength) { 240 _readOffset = (int) (pos - _position); 241 242 return true; 243 } 244 else { 245 long n = pos - _position - _readOffset; 246 247 return skip(n) == n; 248 } 249 } 250 251 254 public boolean canRead() 255 { 256 return _source.canRead(); 257 } 258 259 262 public void clearRead() 263 { 264 _readOffset = 0; 265 _readLength = 0; 266 } 267 268 272 public int getAvailable() throws IOException 273 { 274 if (_readOffset < _readLength) { 275 return _readLength - _readOffset; 276 } 277 278 if (_sibling != null) 279 _sibling.flush(); 280 281 return _source.getAvailable(); 282 } 283 284 287 public int getBufferAvailable() throws IOException 288 { 289 return _readLength - _readOffset; 290 } 291 292 295 public int available() throws IOException 296 { 297 return getAvailable(); 298 } 299 300 303 public final int read() throws IOException 304 { 305 if (_readLength <= _readOffset) { 306 if (! readBuffer()) 307 return -1; 308 } 309 310 return _readBuffer[_readOffset++] & 0xff; 311 } 312 313 316 public final void unread() 317 { 318 if (_readOffset <= 0) 319 throw new RuntimeException (); 320 321 _readOffset--; 322 } 323 324 327 public final boolean waitForRead() throws IOException 328 { 329 if (_readLength <= _readOffset) { 330 if (! readBuffer()) 331 return false; 332 } 333 334 return true; 335 } 336 337 344 public long skip(long n) 345 throws IOException 346 { 347 long count = _readLength - _readOffset; 348 349 if (n < count) { 350 _readOffset += n; 351 return n; 352 } 353 354 _readLength = 0; 355 _readOffset = 0; 356 357 if (_source.hasSkip()) { 358 long skipped = _source.skip(n - count); 359 360 if (skipped < 0) 361 return count; 362 else 363 return skipped + count; 364 } 365 366 while (_readLength < _readOffset + n - count) { 367 count += _readLength - _readOffset; 368 _readOffset = 0; 369 _readLength = 0; 370 371 if (! readBuffer()) 372 return count; 373 } 374 375 _readOffset += (int) (n - count); 376 377 return n; 378 } 379 380 390 public final int read(byte []buf, int offset, int length) 391 throws IOException 392 { 393 int readOffset = _readOffset; 394 int readLength = _readLength; 395 396 if (readLength <= readOffset) { 397 if (ZERO_COPY_SIZE <= length) { 398 if (_sibling != null) 399 _sibling.flush(); 400 401 int len = _source.read(buf, offset, length); 402 403 if (len > 0) { 404 _position += len; 405 _readTime = Alarm.getCurrentTime(); 406 } 407 408 return len; 409 } 410 411 if (! readBuffer()) 412 return -1; 413 414 readOffset = _readOffset; 415 readLength = _readLength; 416 } 417 418 int sublen = readLength - readOffset; 419 if (length < sublen) 420 sublen = length; 421 422 System.arraycopy(_readBuffer, readOffset, buf, offset, sublen); 423 424 _readOffset = readOffset + sublen; 425 426 return sublen; 427 } 428 429 440 public int readAll(byte []buf, int offset, int length) throws IOException 441 { 442 int readLength = 0; 443 444 while (length > 0) { 445 int sublen = read(buf, offset, length); 446 447 if (sublen < 0) 448 return readLength == 0 ? -1 : readLength; 449 450 offset += sublen; 451 readLength += sublen; 452 length -= sublen; 453 } 454 455 return readLength == 0 ? -1 : readLength; 456 } 457 458 461 462 468 public void setEncoding(String encoding) 469 throws UnsupportedEncodingException 470 { 471 String mimeName = Encoding.getMimeName(encoding); 472 473 if (mimeName != null && mimeName.equals(_readEncodingName)) 474 return; 475 476 _readEncoding = Encoding.getReadEncoding(this, encoding); 477 _readEncodingName = mimeName; 478 } 479 480 483 public String getEncoding() 484 { 485 return _readEncodingName; 486 } 487 488 491 public final int readChar() throws IOException 492 { 493 if (_readEncoding != null) { 494 int ch = _readEncoding.read(); 495 return ch; 496 } 497 498 if (_readLength <= _readOffset) { 499 if (! readBuffer()) 500 return -1; 501 } 502 503 return _readBuffer[_readOffset++] & 0xff; 504 } 505 506 516 public final int read(char []buf, int offset, int length) throws IOException 517 { 518 if (_readEncoding != null) 519 return _readEncoding.read(buf, offset, length); 520 521 byte []readBuffer = _readBuffer; 522 if (readBuffer == null) 523 return -1; 524 525 int readOffset = _readOffset; 526 int readLength = _readLength; 527 528 int sublen = readLength - readOffset; 529 530 if (sublen <= 0) { 531 if (! readBuffer()) { 532 return -1; 533 } 534 readLength = _readLength; 535 readOffset = _readOffset; 536 sublen = readLength - readOffset; 537 } 538 539 if (length < sublen) 540 sublen = length; 541 542 for (int i = 0; i < sublen; i++) 543 buf[offset + i] = (char) (readBuffer[readOffset + i] & 0xff); 544 545 _readOffset = readOffset + sublen; 546 547 return sublen; 548 } 549 550 559 public int readAll(char []buf, int offset, int length) throws IOException 560 { 561 int readLength = 0; 562 563 while (length > 0) { 564 int sublen = read(buf, offset, length); 565 566 if (sublen <= 0) 567 return readLength > 0 ? readLength : -1; 568 569 offset += sublen; 570 readLength += sublen; 571 length -= sublen; 572 } 573 574 return readLength; 575 } 576 577 584 public int read(CharBuffer buf, int length) throws IOException 585 { 586 int len = buf.getLength(); 587 588 buf.setLength(len + length); 589 int readLength = read(buf.getBuffer(), len, length); 590 if (readLength < 0) 591 buf.setLength(len); 592 else if (readLength < length) 593 buf.setLength(len + readLength); 594 595 return length; 596 } 597 598 607 public int readAll(CharBuffer buf, int length) throws IOException 608 { 609 int len = buf.getLength(); 610 611 buf.setLength(len + length); 612 int readLength = readAll(buf.getBuffer(), len, length); 613 if (readLength < 0) 614 buf.setLength(len); 615 else if (readLength < length) 616 buf.setLength(len + readLength); 617 618 return length; 619 } 620 621 624 public final String readln() throws IOException 625 { 626 return readLine(); 627 } 628 629 632 public String readLine() throws IOException 633 { 634 CharBuffer cb = new CharBuffer(); 635 636 if (readLine(cb, true)) 637 return cb.toString(); 638 else if (cb.length() == 0) 639 return null; 640 else 641 return cb.toString(); 642 } 643 644 647 public String readLineNoChop() throws IOException 648 { 649 CharBuffer cb = new CharBuffer(); 650 651 if (readLine(cb, false)) 652 return cb.toString(); 653 else if (cb.length() == 0) 654 return null; 655 else 656 return cb.toString(); 657 } 658 659 664 public final boolean readln(CharBuffer cb) throws IOException 665 { 666 return readLine(cb, true); 667 } 668 669 675 public final boolean readLine(CharBuffer cb) 676 throws IOException 677 { 678 return readLine(cb, true); 679 } 680 681 687 public final boolean readLine(CharBuffer cb, boolean isChop) 688 throws IOException 689 { 690 if (_readEncoding != null) 691 return readlnEncoded(cb, isChop); 692 693 int capacity = cb.getCapacity(); 694 int offset = cb.getLength(); 695 char []buf = cb.getBuffer(); 696 697 byte []readBuffer = _readBuffer; 698 699 while (true) { 700 int readOffset = _readOffset; 701 702 int sublen = _readLength - readOffset; 703 if (capacity - offset < sublen) 704 sublen = capacity - offset; 705 706 for (; sublen > 0; sublen--) { 707 int ch = readBuffer[readOffset++] & 0xff; 708 709 if (ch != '\n') { 710 buf[offset++] = (char) ch; 711 } 712 else if (isChop) { 713 if (offset > 0 && buf[offset - 1] == '\r') 714 cb.setLength(offset - 1); 715 else 716 cb.setLength(offset); 717 718 _readOffset = readOffset; 719 720 return true; 721 } 722 else { 723 buf[offset++] = (char) '\n'; 724 725 cb.setLength(offset); 726 727 _readOffset = readOffset; 728 729 return true; 730 } 731 } 732 733 _readOffset = readOffset; 734 735 if (_readLength <= readOffset) { 736 if (! readBuffer()) { 737 cb.setLength(offset); 738 return offset > 0; 739 } 740 } 741 742 if (capacity <= offset) { 743 cb.setLength(offset + 1); 744 capacity = cb.getCapacity(); 745 buf = cb.getBuffer(); 746 } 747 } 748 } 749 750 758 public final int readLine(char []buf, int length) 759 throws IOException 760 { 761 return readLine(buf, length, true); 762 } 763 764 772 public final int readLine(char []buf, int length, boolean isChop) 773 throws IOException 774 { 775 byte []readBuffer = _readBuffer; 776 777 int offset = 0; 778 779 while (true) { 780 int readOffset = _readOffset; 781 782 int sublen = _readLength - readOffset; 783 if (sublen < length) 784 sublen = length; 785 786 for (; sublen > 0; sublen--) { 787 int ch = readBuffer[readOffset++] & 0xff; 788 789 if (ch != '\n') { 790 } 791 else if (isChop) { 792 _readOffset = readOffset; 793 794 if (offset > 0 && buf[offset - 1] == '\r') 795 return offset - 1; 796 else 797 return offset; 798 } 799 else { 800 buf[offset++] = (char) ch; 801 802 _readOffset = readOffset; 803 804 return offset + 1; 805 } 806 807 buf[offset++] = (char) ch; 808 } 809 _readOffset = readOffset; 810 811 if (readOffset <= _readLength) { 812 if (! readBuffer()) { 813 return offset; 814 } 815 } 816 817 if (length <= offset) 818 return length + 1; 819 } 820 } 821 822 private boolean readlnEncoded(CharBuffer cb, boolean isChop) 823 throws IOException 824 { 825 while (true) { 826 int ch = readChar(); 827 828 if (ch < 0) 829 return cb.length() > 0; 830 831 if (ch != '\n') { 832 } 833 else if (isChop) { 834 if (cb.length() > 0 && cb.getLastChar() == '\r') 835 cb.setLength(cb.getLength() - 1); 836 837 return true; 838 } 839 else { 840 cb.append('\n'); 841 842 return true; 843 } 844 845 cb.append((char) ch); 846 } 847 } 848 849 854 public void writeToStream(OutputStream os) throws IOException 855 { 856 if (_readLength <= _readOffset) { 857 readBuffer(); 858 } 859 860 while (_readOffset < _readLength) { 861 os.write(_readBuffer, _readOffset, _readLength - _readOffset); 862 863 readBuffer(); 864 } 865 } 866 867 873 public void writeToStream(OutputStream os, int len) throws IOException 874 { 875 while (len > 0) { 876 if (_readLength <= _readOffset) { 877 if (! readBuffer()) 878 return; 879 } 880 881 int sublen = _readLength - _readOffset; 882 if (len < sublen) 883 sublen = len; 884 885 os.write(_readBuffer, _readOffset, sublen); 886 _readOffset += sublen; 887 len -= sublen; 888 } 889 } 890 891 896 public void writeToWriter(Writer out) throws IOException 897 { 898 int ch; 899 while ((ch = readChar()) >= 0) 900 out.write((char) ch); 901 } 902 903 906 public int fillBuffer() 907 throws IOException 908 { 909 if (! readBuffer()) 910 return -1; 911 else 912 return _readLength; 913 } 914 915 918 public boolean readNonBlock() 919 throws IOException 920 { 921 if (_readOffset < _readLength) 922 return true; 923 924 if (_readBuffer == null) { 925 _readOffset = 0; 926 _readLength = 0; 927 return false; 928 } 929 930 if (_sibling != null) 931 _sibling.flush(); 932 933 _readOffset = 0; 934 _readLength = _source.readNonBlock(_readBuffer, 0, _readBuffer.length); 935 936 if (_readLength > 0) { 938 _position += _readLength; 939 _readTime = Alarm.getCurrentTime(); 940 941 return true; 942 } 943 else { 944 _readLength = 0; 945 return false; 946 } 947 } 948 949 952 public boolean fillWithTimeout(long timeout) 953 throws IOException 954 { 955 if (_readOffset < _readLength) 956 return true; 957 958 if (_readBuffer == null) { 959 _readOffset = 0; 960 _readLength = 0; 961 return false; 962 } 963 964 if (_sibling != null) 965 _sibling.flush(); 966 967 _readOffset = 0; 968 _readLength = _source.readTimeout(_readBuffer, 0, _readBuffer.length, 969 timeout); 970 971 if (_readLength > 0) { 973 _position += _readLength; 974 _readTime = Alarm.getCurrentTime(); 975 return true; 976 } 977 else { 978 _readLength = 0; 979 return false; 980 } 981 } 982 983 988 private boolean readBuffer() 989 throws IOException 990 { 991 if (_readBuffer == null) { 992 _readOffset = 0; 993 _readLength = 0; 994 return false; 995 } 996 997 if (_sibling != null) 998 _sibling.flush(); 999 1000 _readOffset = 0; 1001 _readLength = _source.read(_readBuffer, 0, _readBuffer.length); 1002 1003 if (_readLength > 0) { 1005 _position += _readLength; 1006 _readTime = Alarm.getCurrentTime(); 1007 return true; 1008 } 1009 else { 1010 _readLength = 0; 1011 return false; 1012 } 1013 } 1014 1015 private boolean readBuffer(int off) 1016 throws IOException 1017 { 1018 if (_readBuffer == null) 1019 return false; 1020 1021 if (_sibling != null) 1022 _sibling.flush(); 1023 1024 _readOffset = 0; 1025 _readLength = _source.read(_readBuffer, off, _readBuffer.length - off); 1026 1027 if (_readLength > 0) { 1029 _position += _readLength; 1030 _readTime = Alarm.getCurrentTime(); 1031 return true; 1032 } 1033 else { 1034 _readLength = 0; 1035 return false; 1036 } 1037 } 1038 1039 1045 public void setDisableClose(boolean disableClose) 1046 { 1047 _disableClose = disableClose; 1048 } 1049 1050 1053 public void setDisableCloseSource(boolean disableClose) 1054 { 1055 _isDisableCloseSource = disableClose; 1056 } 1057 1058 1061 public final void close() 1062 { 1063 try { 1064 if (_disableClose) 1065 return; 1066 1067 if (! _reuseBuffer) { 1068 if (_tempRead != null) { 1069 TempBuffer.free(_tempRead); 1070 } 1071 _tempRead = null; 1072 _readBuffer = null; 1073 } 1074 1075 if (_readEncoding != null) { 1076 Reader reader = _readEncoding; 1077 _readEncoding = null; 1078 reader.close(); 1079 } 1080 1081 if (_source != null && ! _isDisableCloseSource) { 1082 StreamImpl s = _source; 1083 _source = null; 1084 s.close(); 1085 } 1086 } catch (IOException e) { 1087 log().log(Level.FINE, e.toString(), e); 1088 } 1089 } 1090 1091 1095 public Object getAttribute(String name) 1096 throws IOException 1097 { 1098 if (_sibling != null) 1099 _sibling.flush(); 1100 1101 return _source.getAttribute(name); 1102 } 1103 1104 1107 public Iterator getAttributeNames() 1108 throws IOException 1109 { 1110 if (_sibling != null) 1111 _sibling.flush(); 1112 1113 return _source.getAttributeNames(); 1114 } 1115 1116 1120 public void setAttribute(String name, Object value) 1121 throws IOException 1122 { 1123 _source.setAttribute(name, value); 1124 } 1125 1126 1129 public void removeAttribute(String name) 1130 throws IOException 1131 { 1132 _source.removeAttribute(name); 1133 } 1134 1135 1138 public Path getPath() 1139 { 1140 return _source == null ? null : _source.getPath(); 1141 } 1142 1143 1148 public String getUserPath() 1149 { 1150 if (_source == null || _source.getPath() == null) 1151 return "stream"; 1152 else 1153 return _source.getPath().getUserPath(); 1154 } 1155 1156 1161 public String getURL() 1162 { 1163 if (_source == null || _source.getPath() == null) 1164 return "stream:"; 1165 else 1166 return _source.getPath().getURL(); 1167 } 1168 1169 1172 public void setPath(Path path) 1173 { 1174 _source.setPath(path); 1175 } 1176 1177 1180 public Reader getReader() 1181 { 1182 if (_reader == null) 1183 _reader = new StreamReader(); 1184 1185 return _reader; 1186 } 1187 1188 private static Logger log() 1189 { 1190 return Logger.getLogger(ReadStream.class.getName()); 1191 } 1192 1193 1196 public String toString() 1197 { 1198 return "ReadStream[" + _source + "]"; 1199 } 1200 1201 public class StreamReader extends Reader { 1202 public final int read() 1203 throws IOException 1204 { 1205 return ReadStream.this.readChar(); 1206 } 1207 1208 public final int read(char []cbuf, int off, int len) 1209 throws IOException 1210 { 1211 return ReadStream.this.read(cbuf, off, len); 1212 } 1213 1214 public boolean ready() 1215 throws IOException 1216 { 1217 return ReadStream.this.available() > 0; 1218 } 1219 1220 public final void close() 1221 throws IOException 1222 { 1223 } 1224 1225 public ReadStream getStream() 1226 { 1227 return ReadStream.this; 1228 } 1229 } 1230} 1231 | Popular Tags |