1 29 30 package com.caucho.vfs; 31 32 import com.caucho.util.CharSegment; 33 import com.caucho.vfs.i18n.EncodingWriter; 34 35 import java.io.IOException ; 36 import java.io.InputStream ; 37 import java.io.PrintWriter ; 38 import java.io.Reader ; 39 import java.io.UnsupportedEncodingException ; 40 import java.io.Writer ; 41 import java.util.Iterator ; 42 import java.util.Locale ; 43 44 57 public class WriteStream extends OutputStreamWithBuffer { 58 private static byte []lfBytes = new byte[] {'\n'}; 59 private static byte []crBytes = new byte[] {'\r'}; 60 private static byte []crlfBytes = new byte[] {'\r', '\n'}; 61 62 private static String _sysNewline; 63 private static byte []_sysNewlineBytes; 64 65 static { 66 _sysNewline = Path.getNewlineString(); 67 _sysNewlineBytes = _sysNewline.getBytes(); 68 } 69 70 private TempBuffer _tempWrite; 71 private byte []_writeBuffer; 72 private int _writeLength; 73 74 private StreamImpl _source; 75 76 private char []chars; 77 private byte []_bytes; 78 79 private EncodingWriter _writeEncoding; 80 private String _writeEncodingName; 81 82 private boolean _implicitFlush = false; 83 private boolean flushOnNewline; 84 private boolean _disableClose; 85 private boolean _isDisableCloseSource; 86 private boolean _disableFlush; 87 private boolean reuseBuffer; 88 89 private StreamWriter _writer; 90 private StreamPrintWriter _printWriter; 91 92 private String newline = "\n"; 93 private byte []newlineBytes = lfBytes; 94 95 98 public WriteStream() 99 { 100 } 101 102 107 public WriteStream(StreamImpl source) 108 { 109 init(source); 110 } 111 112 117 public void init(StreamImpl source) 118 { 119 _disableClose = false; 120 _isDisableCloseSource = false; 121 122 if (this._source != null && this._source != source) { 123 try { 124 close(); 125 } catch (IOException e) { 126 } 127 } 128 129 if (source == null) 130 throw new IllegalArgumentException (); 131 132 if (_tempWrite == null) { 133 _tempWrite = TempBuffer.allocate(); 134 _writeBuffer = _tempWrite._buf; 135 } 136 137 this._source = source; 138 139 _writeLength = 0; 140 flushOnNewline = source.getFlushOnNewline(); 141 newline = _sysNewline; 145 newlineBytes = _sysNewlineBytes; 146 147 _writeEncoding = null; 148 _writeEncodingName = "ISO-8859-1"; 149 } 150 151 156 public StreamImpl getSource() 157 { 158 return _source; 159 } 160 161 166 public void pushFilter(StreamFilter filter) 167 { 168 filter.init(_source); 169 _source = filter; 170 } 171 172 183 public boolean canWrite() 184 { 185 return _source != null && _source.canWrite(); 186 } 187 188 191 public void clearWrite() 192 { 193 if (_source != null) 194 _source.clearWrite(); 195 } 196 197 public void setReuseBuffer(boolean reuse) 198 { 199 this.reuseBuffer = reuse; 200 } 201 202 205 public byte []getBuffer() 206 { 207 return _writeBuffer; 208 } 209 210 213 public int getBufferOffset() 214 { 215 return _writeLength; 216 } 217 218 221 public void setBufferOffset(int offset) 222 { 223 _writeLength = offset; 224 } 225 226 229 public int getBufferSize() 230 { 231 return _writeBuffer.length; 232 } 233 234 237 public int getRemaining() 238 { 239 if (_source == null) 240 return 0; 241 else 242 return _writeBuffer.length - _writeLength; 243 } 244 245 public void setImplicitFlush(boolean implicitFlush) 246 { 247 _implicitFlush = implicitFlush; 248 } 249 250 253 public void write(int ch) throws IOException 254 { 255 if (_source == null) 256 return; 257 258 int len = _writeLength; 259 if (_writeBuffer.length <= len) { 260 _writeLength = 0; 261 _source.write(_writeBuffer, 0, len, false); 262 } 263 264 _writeBuffer[_writeLength++] = (byte) ch; 265 266 if (_implicitFlush) 267 flush(); 268 } 269 270 273 public void write(byte []buf, int offset, int length) throws IOException 274 { 275 byte []buffer = _writeBuffer; 276 277 if (_source == null) 278 return; 279 280 int bufferLength = buffer.length; 281 int writeLength = _writeLength; 282 283 if (bufferLength <= length && 284 _source.write(buffer, 0, writeLength, 285 buf, offset, length, false)) { 286 _writeLength = 0; 287 return; 288 } 289 290 while (length > 0) { 291 int sublen = bufferLength - writeLength; 292 293 if (length < sublen) 294 sublen = length; 295 296 System.arraycopy(buf, offset, buffer, writeLength, sublen); 297 298 writeLength += sublen; 299 offset += sublen; 300 length -= sublen; 301 302 if (bufferLength <= writeLength) { 303 int len = writeLength; 304 writeLength = 0; 305 _source.write(buffer, 0, len, false); 306 } 307 } 308 309 _writeLength = writeLength; 310 311 if (_implicitFlush) 312 flush(); 313 } 314 315 318 public byte []nextBuffer(int offset) throws IOException 319 { 320 _writeLength = 0; 321 _source.write(_writeBuffer, 0, offset, false); 322 323 if (_implicitFlush) 324 flush(); 325 326 return _writeBuffer; 327 } 328 329 332 public void write(byte []buf) throws IOException 333 { 334 write(buf, 0, buf.length); 335 } 336 337 340 public void flush() throws IOException 341 { 342 if (_disableFlush || _source == null) 343 return; 344 345 int len = _writeLength; 346 if (len > 0) { 347 _writeLength = 0; 348 _source.write(_writeBuffer, 0, len, false); 349 } 350 351 if (_source != null) 352 _source.flush(); 353 } 354 355 358 public void flushToDisk() throws IOException 359 { 360 StreamImpl source = _source; 361 362 if (_disableFlush || source == null) 363 return; 364 365 int len = _writeLength; 366 if (len > 0) { 367 _writeLength = 0; 368 source.write(_writeBuffer, 0, len, false); 369 } 370 371 source.flushToDisk(); 372 } 373 374 377 public void flushBuffer() throws IOException 378 { 379 if (_disableFlush || _source == null) 380 return; 381 382 int len = _writeLength; 383 if (len > 0) { 384 _writeLength = 0; 385 _source.write(_writeBuffer, 0, len, false); 386 _source.flushBuffer(); 387 } 388 } 389 390 393 public void seekStart(long offset) 394 throws IOException 395 { 396 flushBuffer(); 397 398 StreamImpl source = _source; 399 400 if (source != null) 401 source.seekStart(offset); 402 } 403 404 407 public void seekEnd(long offset) 408 throws IOException 409 { 410 flushBuffer(); 411 412 StreamImpl source = _source; 413 414 if (source != null) 415 source.seekEnd(offset); 416 } 417 418 421 422 426 public void setEncoding(String encoding) 427 throws UnsupportedEncodingException 428 { 429 if (_source instanceof ReaderWriterStream) 430 encoding = "UTF-8"; 431 432 String mimeName = Encoding.getMimeName(encoding); 433 434 if (mimeName != null && mimeName.equals(_writeEncodingName)) 435 return; 436 437 if (_source != null) 438 _source.setWriteEncoding(encoding); 439 440 _writeEncoding = Encoding.getWriteEncoding(encoding); 441 _writeEncodingName = mimeName; 442 } 443 444 public void setLocale(Locale locale) 445 throws UnsupportedEncodingException 446 { 447 if (_writeEncoding == null && locale != null) 448 setEncoding(Encoding.getMimeName(locale)); 449 } 450 451 454 public String getEncoding() 455 { 456 if (_source instanceof ReaderWriterStream) 457 return ((ReaderWriterStream) _source).getEncoding(); 458 else 459 return _writeEncodingName; 460 } 461 462 public String getJavaEncoding() 463 { 464 return Encoding.getJavaName(getEncoding()); 465 } 466 467 474 public void setFlushOnNewline(boolean flushOnNewline) 475 { 476 this.flushOnNewline = flushOnNewline; 477 } 478 479 482 public String getNewlineString() 483 { 484 return newline; 485 } 486 487 490 public void setNewlineString(String newline) 491 { 492 if (newline != null) { 493 if (this.newline == newline || newline.equals(this.newline)) { 494 } 495 else if (newline == "\n" || newline.equals("\n")) { 496 this.newlineBytes = lfBytes; 497 } 498 else if (newline == "\r\n" || newline.equals("\r\n")) { 499 this.newlineBytes = crlfBytes; 500 } 501 else if (newline == "\r" || newline.equals("\r")) { 502 this.newlineBytes = crBytes; 503 } 504 else { 505 this.newlineBytes = newline.getBytes(); 506 } 507 this.newline = newline; 508 } 509 } 510 511 518 public final void print(char []buffer, int offset, int length) 519 throws IOException 520 { 521 byte []writeBuffer = this._writeBuffer; 522 523 if (_source == null) 524 return; 525 526 if (_writeEncoding != null) { 527 _disableFlush = true; 528 _writeEncoding.write(this, buffer, offset, length); 529 _disableFlush = false; 530 return; 531 } 532 533 while (length > 0) { 534 int writeLength = _writeLength; 535 int sublen = writeBuffer.length - writeLength; 536 537 if (sublen <= 0) { 538 _source.write(writeBuffer, 0, writeLength, false); 539 writeLength = 0; 540 sublen = writeBuffer.length - writeLength; 541 } 542 if (length < sublen) 543 sublen = length; 544 545 for (int i = sublen - 1; i >= 0; i--) 546 writeBuffer[writeLength + i] = (byte) buffer[offset + i]; 547 548 _writeLength = writeLength + sublen; 549 offset += sublen; 550 length -= sublen; 551 } 552 553 if (_implicitFlush) 554 flush(); 555 } 556 557 562 public final void print(char ch) 563 throws IOException 564 { 565 if (_writeEncoding != null) { 566 _disableFlush = true; 567 _writeEncoding.write(this, ch); 568 _disableFlush = false; 569 return; 570 } 571 572 write((byte) ch); 573 } 574 575 580 public final void print(char []buffer) 581 throws IOException 582 { 583 print(buffer, 0, buffer.length); 584 } 585 586 591 public final void print(CharSegment segment) 592 throws IOException 593 { 594 print(segment.getBuffer(), segment.getOffset(), segment.getLength()); 595 } 596 597 600 public final void print(String string) throws IOException 601 { 602 if (string == null) 603 string = "null"; 604 605 int length = string.length(); 606 int offset = 0; 607 while (length > 0) { 608 int sublen = length < 1024 ? length : 1024; 609 610 if (chars == null || chars.length < sublen) 611 chars = new char[sublen < 32 ? 32 : sublen]; 612 613 string.getChars(offset, offset + sublen, chars, 0); 614 615 print(chars, 0, sublen); 616 617 length -= sublen; 618 offset += sublen; 619 } 620 } 621 622 629 public final void print(String string, int offset, int length) 630 throws IOException 631 { 632 if (string == null) 633 string = "null"; 634 635 while (length > 0) { 636 int sublen = length < 1024 ? length : 1024; 637 638 if (chars == null || chars.length < sublen) 639 chars = new char[sublen < 32 ? 32 : sublen]; 640 641 string.getChars(offset, offset + sublen, chars, 0); 642 643 print(chars, 0, sublen); 644 645 length -= sublen; 646 offset += sublen; 647 } 648 } 649 650 653 public final void print(boolean b) throws IOException 654 { 655 print(b ? "true" : "false"); 656 } 657 658 661 public final void print(int i) throws IOException 662 { 663 if (i == 0x80000000) { 664 print("-2147483648"); 665 return; 666 } 667 668 if (i < 0) { 669 write('-'); 670 i = -i; 671 } else if (i < 9) { 672 write('0' + i); 673 return; 674 } 675 676 int length = 0; 677 int exp = 10; 678 679 if (i >= 1000000000) 680 length = 9; 681 else { 682 for (; i >= exp; length++) 683 exp = 10 * exp; 684 } 685 686 byte []buffer = _writeBuffer; 687 int writeLength = this._writeLength; 688 689 if (writeLength + length < buffer.length) { 690 writeLength += length; 691 this._writeLength = writeLength + 1; 692 693 for (int j = 0; j <= length; j++) { 694 buffer[writeLength - j] = (byte) (i % 10 + '0'); 695 i = i / 10; 696 } 697 return; 698 } 699 700 if (_bytes == null) 701 _bytes = new byte[32]; 702 703 int j = 31; 704 705 while (i > 0) { 706 _bytes[--j] = (byte) ((i % 10) + '0'); 707 i /= 10; 708 } 709 710 write(_bytes, j, 31 - j); 711 } 712 713 716 public final void print(long i) throws IOException 717 { 718 if (i == 0x8000000000000000L) { 719 print("-9223372036854775808"); 720 return; 721 } 722 723 if (_bytes == null) 724 _bytes = new byte[32]; 725 726 if (i < 0) { 727 write('-'); 728 i = -i; 729 } else if (i == 0) { 730 write('0'); 731 return; 732 } 733 734 int j = 31; 735 736 while (i > 0) { 737 _bytes[--j] = (byte) ((i % 10) + '0'); 738 i /= 10; 739 } 740 741 write(_bytes, j, 31 - j); 742 } 743 744 747 public final void print(float f) throws IOException 748 { 749 print(String.valueOf(f)); 750 } 751 752 755 public final void print(double d) throws IOException 756 { 757 print(String.valueOf(d)); 758 } 759 760 763 public final void print(Object o) throws IOException 764 { 765 if (o == null) 766 print("null"); 767 else if (o instanceof VfsWriteObject) 768 ((VfsWriteObject) o).print(this); 769 else 770 print(o.toString()); 771 } 772 773 776 public final void println() throws IOException 777 { 778 write(newlineBytes, 0, newlineBytes.length); 779 if (flushOnNewline) 780 flush(); 781 } 782 783 786 public final void println(char []buf, int offset, int length) 787 throws IOException 788 { 789 print(buf, offset, length); 790 write(newlineBytes, 0, newlineBytes.length); 791 if (flushOnNewline) 792 flush(); 793 } 794 795 798 public final void println(String string) throws IOException 799 { 800 print(string); 801 write(newlineBytes, 0, newlineBytes.length); 802 if (flushOnNewline) 803 flush(); 804 } 805 806 809 public final void println(boolean b) throws IOException 810 { 811 println(b ? "true" : "false"); 812 } 813 814 817 public final void println(char ch) throws IOException 818 { 819 write(ch); 820 write(newlineBytes, 0, newlineBytes.length); 821 if (flushOnNewline) 822 flush(); 823 } 824 825 828 public final void println(int i) throws IOException 829 { 830 print(i); 831 write(newlineBytes, 0, newlineBytes.length); 832 if (flushOnNewline) 833 flush(); 834 } 835 836 839 public final void println(long l) throws IOException 840 { 841 print(l); 842 write(newlineBytes, 0, newlineBytes.length); 843 if (flushOnNewline) 844 flush(); 845 } 846 847 850 public final void println(float f) throws IOException 851 { 852 println(String.valueOf(f)); 853 } 854 855 858 public final void println(double d) throws IOException 859 { 860 println(String.valueOf(d)); 861 } 862 863 866 public final void println(Object o) throws IOException 867 { 868 if (o == null) 869 println("null"); 870 else 871 println(o.toString()); 872 } 873 874 877 public PrintWriter getPrintWriter() 878 { 879 883 884 if (_printWriter == null) 885 _printWriter = new StreamPrintWriter(this); 886 890 891 return _printWriter; 892 } 893 894 898 public final void log(String string) 899 { 900 try { 901 synchronized (this) { 902 println(string); 903 flush(); 904 } 905 } catch (Exception e) { 906 } 907 } 908 909 public final void log(Throwable exn) 910 { 911 try { 912 PrintWriter out = getPrintWriter(); 913 synchronized (this) { 914 if (exn != null) { 915 exn.printStackTrace(out); 916 flush(); 917 } 918 } 919 } catch (Throwable e) { 920 e.printStackTrace(); 921 } 922 } 923 924 930 public long writeStream(InputStream source) throws IOException 931 { 932 if (source == null) 933 return 0; 934 935 int len; 936 int length = _writeBuffer.length; 937 long outputLength = 0; 938 939 if (_writeLength >= length) { 940 int tmplen = _writeLength; 941 _writeLength = 0; 942 _source.write(_writeBuffer, 0, tmplen, false); 943 outputLength += tmplen; 944 } 945 946 while ((len = source.read(_writeBuffer, 947 _writeLength, 948 length - _writeLength)) >= 0) { 949 _writeLength += len; 950 outputLength += len; 951 952 if (length <= _writeLength) { 953 int tmplen = _writeLength; 954 _writeLength = 0; 955 _source.write(_writeBuffer, 0, tmplen, false); 956 } 957 } 958 959 if (flushOnNewline || _implicitFlush) 960 flush(); 961 962 return outputLength; 963 } 964 965 971 public void writeStream(Reader reader) throws IOException 972 { 973 if (reader == null) 974 return; 975 976 if (chars == null) 977 chars = new char[256]; 978 979 int len; 980 while ((len = reader.read(chars, 0, chars.length)) > 0) { 981 print(chars, 0, len); 982 } 983 } 984 985 991 public void writeStream(InputStream source, int totalLength) 992 throws IOException 993 { 994 if (source == null) 995 return; 996 997 int len; 998 int length = _writeBuffer.length; 999 1000 if (_writeLength >= length) { 1001 int tmplen = _writeLength; 1002 _writeLength = 0; 1003 this._source.write(_writeBuffer, 0, tmplen, false); 1004 } 1005 1006 while (totalLength > 0) { 1007 int sublen = length - _writeLength; 1008 1009 if (sublen > totalLength) 1010 sublen = totalLength; 1011 1012 sublen = source.read(_writeBuffer, _writeLength, sublen); 1013 if (sublen < 0) 1014 break; 1015 1016 _writeLength += sublen; 1017 totalLength -= sublen; 1018 if (_writeLength >= length) { 1019 int tmplen = _writeLength; 1020 _writeLength = 0; 1021 _source.write(_writeBuffer, 0, tmplen, false); 1022 } 1023 } 1024 1025 if (flushOnNewline || _implicitFlush) 1026 flush(); 1027 } 1028 1029 1030 1036 public void writeStream(StreamImpl source) throws IOException 1037 { 1038 if (source == null) 1039 return; 1040 1041 int len; 1042 int length = _writeBuffer.length; 1043 1044 if (_writeLength >= length) { 1045 int tmplen = _writeLength; 1046 _writeLength = 0; 1047 this._source.write(_writeBuffer, 0, tmplen, false); 1048 } 1049 1050 while ((len = source.read(_writeBuffer, 1051 _writeLength, 1052 length - _writeLength)) >= 0) { 1053 _writeLength += len; 1054 if (_writeLength >= length) { 1055 int tmplen = _writeLength; 1056 _writeLength = 0; 1057 this._source.write(_writeBuffer, 0, tmplen, false); 1058 } 1059 } 1060 1061 if (flushOnNewline || _implicitFlush) 1062 flush(); 1063 } 1064 1065 1070 public void writeFile(Path path) throws IOException 1071 { 1072 StreamImpl is = path.openReadImpl(); 1073 1074 try { 1075 if (is != null) 1076 writeStream(is); 1077 } finally { 1078 if (is != null) 1079 is.close(); 1080 } 1081 } 1082 1083 1089 public void setDisableClose(boolean disableClose) 1090 { 1091 this._disableClose = disableClose; 1092 } 1093 1094 public boolean getDisableClose() 1095 { 1096 return _disableClose; 1097 } 1098 1099 1102 public void setDisableCloseSource(boolean disableClose) 1103 { 1104 _isDisableCloseSource = disableClose; 1105 } 1106 1107 1110 public final boolean isClosed() 1111 { 1112 return _source != null; 1113 } 1114 1115 1118 public final void close() throws IOException 1119 { 1120 StreamImpl s = _source; 1121 1122 try { 1123 int len = _writeLength; 1124 if (len > 0) { 1125 _writeLength = 0; 1126 if (s != null) 1127 s.write(_writeBuffer, 0, len, true); 1128 } 1129 } finally { 1130 if (_disableClose) { 1131 return; 1132 } 1133 1134 _source = null; 1135 1136 if (_writeEncoding != null) 1137 _writeEncoding = null; 1138 1139 if (! reuseBuffer) { 1140 if (_tempWrite != null) 1141 TempBuffer.free(_tempWrite); 1142 _tempWrite = null; 1143 _writeBuffer = null; 1144 } 1145 1146 if (s != null && ! _isDisableCloseSource) 1147 s.closeWrite(); 1148 } 1149 } 1150 1151 1154 public final void free() 1155 { 1156 _source = null; 1157 if (_tempWrite != null) 1158 TempBuffer.free(_tempWrite); 1159 _tempWrite = null; 1160 _writeBuffer = null; 1161 } 1162 1163 1164 1168 public Object getAttribute(String name) 1169 throws IOException 1170 { 1171 return _source.getAttribute(name); 1172 } 1173 1174 1178 public void setAttribute(String name, Object value) 1179 throws IOException 1180 { 1181 _source.setAttribute(name, value); 1182 } 1183 1184 1187 public void removeAttribute(String name) 1188 throws IOException 1189 { 1190 _source.removeAttribute(name); 1191 } 1192 1193 1196 public Iterator getAttributeNames() 1197 throws IOException 1198 { 1199 return _source.getAttributeNames(); 1200 } 1201 1202 1205 public Path getPath() 1206 { 1207 if (_source != null) 1208 return _source.getPath(); 1209 else 1210 return null; 1211 } 1212 1213 1218 public String getUserPath() 1219 { 1220 return _source.getPath().getUserPath(); 1221 } 1222 1223 1226 public void setPath(Path path) 1227 { 1228 _source.setPath(path); 1229 } 1230 1231 1234 public static void setSystemNewline(String newline) 1235 { 1236 _sysNewline = newline; 1237 _sysNewlineBytes = _sysNewline.getBytes(); 1238 } 1239 1240 private class StreamWriter extends Writer 1241 implements EnclosedWriteStream, FlushBuffer { 1242 public final void write(char ch) 1243 throws IOException 1244 { 1245 WriteStream.this.print(ch); 1246 } 1247 1248 public final void write(char []buffer, int offset, int length) 1249 throws IOException 1250 { 1251 WriteStream.this.print(buffer, offset, length); 1252 } 1253 1254 public final void write(char []buffer) 1255 throws IOException 1256 { 1257 WriteStream.this.print(buffer, 0, buffer.length); 1258 } 1259 1260 public final void write(String string) 1261 throws IOException 1262 { 1263 WriteStream.this.print(string); 1264 } 1265 1266 public final void write(String string, int off, int len) 1267 throws IOException 1268 { 1269 WriteStream.this.print(string, off, len); 1270 } 1271 1272 public final void flush() 1273 throws IOException 1274 { 1275 WriteStream.this.flush(); 1276 } 1277 1278 public final void flushBuffer() 1279 throws IOException 1280 { 1281 WriteStream.this.flushBuffer(); 1282 } 1283 1284 public final void close() 1285 throws IOException 1286 { 1287 } 1290 1291 public WriteStream getWriteStream() 1292 { 1293 return WriteStream.this; 1294 } 1295 } 1296} 1297 | Popular Tags |