1 20 package org.apache.mina.common; 21 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.ObjectInputStream ; 25 import java.io.ObjectOutputStream ; 26 import java.io.ObjectStreamClass ; 27 import java.io.OutputStream ; 28 import java.nio.BufferOverflowException ; 29 import java.nio.BufferUnderflowException ; 30 import java.nio.ByteOrder ; 31 import java.nio.CharBuffer ; 32 import java.nio.DoubleBuffer ; 33 import java.nio.FloatBuffer ; 34 import java.nio.IntBuffer ; 35 import java.nio.LongBuffer ; 36 import java.nio.ShortBuffer ; 37 import java.nio.charset.CharacterCodingException ; 38 import java.nio.charset.CharsetDecoder ; 39 import java.nio.charset.CharsetEncoder ; 40 import java.nio.charset.CoderResult ; 41 42 import org.apache.mina.common.support.ByteBufferHexDumper; 43 import org.apache.mina.filter.codec.ProtocolEncoderOutput; 44 45 155 public abstract class ByteBuffer implements Comparable <ByteBuffer> { 156 private static ByteBufferAllocator allocator = new PooledByteBufferAllocator(); 157 158 private static boolean useDirectBuffers = true; 159 160 163 public static ByteBufferAllocator getAllocator() { 164 return allocator; 165 } 166 167 171 public static void setAllocator(ByteBufferAllocator newAllocator) { 172 if (newAllocator == null) { 173 throw new NullPointerException ("allocator"); 174 } 175 176 ByteBufferAllocator oldAllocator = allocator; 177 178 allocator = newAllocator; 179 180 if (null != oldAllocator) { 181 oldAllocator.dispose(); 182 } 183 } 184 185 public static boolean isUseDirectBuffers() { 186 return useDirectBuffers; 187 } 188 189 public static void setUseDirectBuffers(boolean useDirectBuffers) { 190 ByteBuffer.useDirectBuffers = useDirectBuffers; 191 } 192 193 201 public static ByteBuffer allocate(int capacity) { 202 if (useDirectBuffers) { 203 try { 204 return allocate(capacity, true); 206 } catch (OutOfMemoryError e) { 207 } 209 } 210 211 return allocate(capacity, false); 212 } 213 214 221 public static ByteBuffer allocate(int capacity, boolean direct) { 222 return allocator.allocate(capacity, direct); 223 } 224 225 228 public static ByteBuffer wrap(java.nio.ByteBuffer nioBuffer) { 229 return allocator.wrap(nioBuffer); 230 } 231 232 235 public static ByteBuffer wrap(byte[] byteArray) { 236 return wrap(java.nio.ByteBuffer.wrap(byteArray)); 237 } 238 239 245 public static ByteBuffer wrap(byte[] byteArray, int offset, int length) { 246 return wrap(java.nio.ByteBuffer.wrap(byteArray, offset, length)); 247 } 248 249 protected ByteBuffer() { 250 } 251 252 260 public abstract void acquire(); 261 262 268 public abstract void release(); 269 270 273 public abstract java.nio.ByteBuffer buf(); 274 275 278 public abstract boolean isDirect(); 279 280 283 public abstract boolean isReadOnly(); 284 285 288 public abstract int capacity(); 289 290 293 public abstract ByteBuffer capacity(int newCapacity); 294 295 298 public abstract boolean isAutoExpand(); 299 300 303 public abstract ByteBuffer setAutoExpand(boolean autoExpand); 304 305 311 public ByteBuffer expand(int expectedRemaining) { 312 return expand(position(), expectedRemaining); 313 } 314 315 322 public abstract ByteBuffer expand(int pos, int expectedRemaining); 323 324 333 public abstract boolean isPooled(); 334 335 343 public abstract void setPooled(boolean pooled); 344 345 348 public abstract int position(); 349 350 353 public abstract ByteBuffer position(int newPosition); 354 355 358 public abstract int limit(); 359 360 363 public abstract ByteBuffer limit(int newLimit); 364 365 368 public abstract ByteBuffer mark(); 369 370 374 public abstract int markValue(); 375 376 379 public abstract ByteBuffer reset(); 380 381 384 public abstract ByteBuffer clear(); 385 386 391 public ByteBuffer sweep() { 392 clear(); 393 return fillAndReset(remaining()); 394 } 395 396 401 public ByteBuffer sweep(byte value) { 402 clear(); 403 return fillAndReset(value, remaining()); 404 } 405 406 409 public abstract ByteBuffer flip(); 410 411 414 public abstract ByteBuffer rewind(); 415 416 419 public int remaining() { 420 return limit() - position(); 421 } 422 423 426 public boolean hasRemaining() { 427 return remaining() > 0; 428 } 429 430 433 public abstract ByteBuffer duplicate(); 434 435 438 public abstract ByteBuffer slice(); 439 440 443 public abstract ByteBuffer asReadOnlyBuffer(); 444 445 448 public abstract byte[] array(); 449 450 453 public abstract int arrayOffset(); 454 455 458 public abstract byte get(); 459 460 463 public short getUnsigned() { 464 return (short) (get() & 0xff); 465 } 466 467 470 public abstract ByteBuffer put(byte b); 471 472 475 public abstract byte get(int index); 476 477 480 public short getUnsigned(int index) { 481 return (short) (get(index) & 0xff); 482 } 483 484 487 public abstract ByteBuffer put(int index, byte b); 488 489 492 public abstract ByteBuffer get(byte[] dst, int offset, int length); 493 494 497 public ByteBuffer get(byte[] dst) { 498 return get(dst, 0, dst.length); 499 } 500 501 504 public abstract ByteBuffer put(java.nio.ByteBuffer src); 505 506 509 public ByteBuffer put(ByteBuffer src) { 510 return put(src.buf()); 511 } 512 513 516 public abstract ByteBuffer put(byte[] src, int offset, int length); 517 518 521 public ByteBuffer put(byte[] src) { 522 return put(src, 0, src.length); 523 } 524 525 528 public abstract ByteBuffer compact(); 529 530 public String toString() { 531 StringBuffer buf = new StringBuffer (); 532 if (isDirect()) { 533 buf.append("DirectBuffer"); 534 } else { 535 buf.append("HeapBuffer"); 536 } 537 buf.append("[pos="); 538 buf.append(position()); 539 buf.append(" lim="); 540 buf.append(limit()); 541 buf.append(" cap="); 542 buf.append(capacity()); 543 buf.append(": "); 544 buf.append(getHexDump()); 545 buf.append(']'); 546 return buf.toString(); 547 } 548 549 public int hashCode() { 550 int h = 1; 551 int p = position(); 552 for (int i = limit() - 1; i >= p; i--) { 553 h = 31 * h + get(i); 554 } 555 return h; 556 } 557 558 public boolean equals(Object o) { 559 if (!(o instanceof ByteBuffer)) { 560 return false; 561 } 562 563 ByteBuffer that = (ByteBuffer) o; 564 if (this.remaining() != that.remaining()) { 565 return false; 566 } 567 568 int p = this.position(); 569 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) { 570 byte v1 = this.get(i); 571 byte v2 = that.get(j); 572 if (v1 != v2) { 573 return false; 574 } 575 } 576 return true; 577 } 578 579 public int compareTo(ByteBuffer that) { 580 int n = this.position() + Math.min(this.remaining(), that.remaining()); 581 for (int i = this.position(), j = that.position(); i < n; i++, j++) { 582 byte v1 = this.get(i); 583 byte v2 = that.get(j); 584 if (v1 == v2) { 585 continue; 586 } 587 if (v1 < v2) { 588 return -1; 589 } 590 591 return +1; 592 } 593 return this.remaining() - that.remaining(); 594 } 595 596 599 public abstract ByteOrder order(); 600 601 604 public abstract ByteBuffer order(ByteOrder bo); 605 606 609 public abstract char getChar(); 610 611 614 public abstract ByteBuffer putChar(char value); 615 616 619 public abstract char getChar(int index); 620 621 624 public abstract ByteBuffer putChar(int index, char value); 625 626 629 public abstract CharBuffer asCharBuffer(); 630 631 634 public abstract short getShort(); 635 636 639 public int getUnsignedShort() { 640 return getShort() & 0xffff; 641 } 642 643 646 public abstract ByteBuffer putShort(short value); 647 648 651 public abstract short getShort(int index); 652 653 656 public int getUnsignedShort(int index) { 657 return getShort(index) & 0xffff; 658 } 659 660 663 public abstract ByteBuffer putShort(int index, short value); 664 665 668 public abstract ShortBuffer asShortBuffer(); 669 670 673 public abstract int getInt(); 674 675 678 public long getUnsignedInt() { 679 return getInt() & 0xffffffffL; 680 } 681 682 685 public abstract ByteBuffer putInt(int value); 686 687 690 public abstract int getInt(int index); 691 692 695 public long getUnsignedInt(int index) { 696 return getInt(index) & 0xffffffffL; 697 } 698 699 702 public abstract ByteBuffer putInt(int index, int value); 703 704 707 public abstract IntBuffer asIntBuffer(); 708 709 712 public abstract long getLong(); 713 714 717 public abstract ByteBuffer putLong(long value); 718 719 722 public abstract long getLong(int index); 723 724 727 public abstract ByteBuffer putLong(int index, long value); 728 729 732 public abstract LongBuffer asLongBuffer(); 733 734 737 public abstract float getFloat(); 738 739 742 public abstract ByteBuffer putFloat(float value); 743 744 747 public abstract float getFloat(int index); 748 749 752 public abstract ByteBuffer putFloat(int index, float value); 753 754 757 public abstract FloatBuffer asFloatBuffer(); 758 759 762 public abstract double getDouble(); 763 764 767 public abstract ByteBuffer putDouble(double value); 768 769 772 public abstract double getDouble(int index); 773 774 777 public abstract ByteBuffer putDouble(int index, double value); 778 779 782 public abstract DoubleBuffer asDoubleBuffer(); 783 784 789 public InputStream asInputStream() { 790 return new InputStream () { 791 public int available() { 792 return ByteBuffer.this.remaining(); 793 } 794 795 public synchronized void mark(int readlimit) { 796 ByteBuffer.this.mark(); 797 } 798 799 public boolean markSupported() { 800 return true; 801 } 802 803 public int read() { 804 if (ByteBuffer.this.hasRemaining()) { 805 return ByteBuffer.this.get() & 0xff; 806 } else { 807 return -1; 808 } 809 } 810 811 public int read(byte[] b, int off, int len) { 812 int remaining = ByteBuffer.this.remaining(); 813 if (remaining > 0) { 814 int readBytes = Math.min(remaining, len); 815 ByteBuffer.this.get(b, off, readBytes); 816 return readBytes; 817 } else { 818 return -1; 819 } 820 } 821 822 public synchronized void reset() { 823 ByteBuffer.this.reset(); 824 } 825 826 public long skip(long n) { 827 int bytes; 828 if (n > Integer.MAX_VALUE) { 829 bytes = ByteBuffer.this.remaining(); 830 } else { 831 bytes = Math.min(ByteBuffer.this.remaining(), (int) n); 832 } 833 ByteBuffer.this.skip(bytes); 834 return bytes; 835 } 836 }; 837 } 838 839 847 public OutputStream asOutputStream() { 848 return new OutputStream () { 849 public void write(byte[] b, int off, int len) { 850 ByteBuffer.this.put(b, off, len); 851 } 852 853 public void write(int b) { 854 ByteBuffer.this.put((byte) b); 855 } 856 }; 857 } 858 859 862 public String getHexDump() { 863 return ByteBufferHexDumper.getHexdump(this); 864 } 865 866 870 875 public String getString(CharsetDecoder decoder) 876 throws CharacterCodingException { 877 if (!hasRemaining()) { 878 return ""; 879 } 880 881 boolean utf16 = decoder.charset().name().startsWith("UTF-16"); 882 883 int oldPos = position(); 884 int oldLimit = limit(); 885 int end; 886 887 if (!utf16) { 888 while (hasRemaining()) { 889 if (get() == 0) { 890 break; 891 } 892 } 893 894 end = position(); 895 if (end == oldLimit && get(end - 1) != 0) { 896 limit(end); 897 } else { 898 limit(end - 1); 899 } 900 } else { 901 while (remaining() >= 2) { 902 boolean highZero = (get() == 0); 903 boolean lowZero = (get() == 0); 904 if (highZero && lowZero) { 905 break; 906 } 907 } 908 909 end = position(); 910 if (end == oldLimit || end == oldLimit - 1) { 911 limit(end); 912 } else { 913 limit(end - 2); 914 } 915 } 916 917 position(oldPos); 918 if (!hasRemaining()) { 919 limit(oldLimit); 920 position(end); 921 return ""; 922 } 923 decoder.reset(); 924 925 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; 926 CharBuffer out = CharBuffer.allocate(expectedLength); 927 for (;;) { 928 CoderResult cr; 929 if (hasRemaining()) { 930 cr = decoder.decode(buf(), out, true); 931 } else { 932 cr = decoder.flush(out); 933 } 934 935 if (cr.isUnderflow()) { 936 break; 937 } 938 939 if (cr.isOverflow()) { 940 CharBuffer o = CharBuffer.allocate(out.capacity() 941 + expectedLength); 942 out.flip(); 943 o.put(out); 944 out = o; 945 continue; 946 } 947 948 if (cr.isError()) { 949 limit(oldLimit); 951 position(oldPos); 952 cr.throwException(); 953 } 954 } 955 956 limit(oldLimit); 957 position(end); 958 return out.flip().toString(); 959 } 960 961 967 public String getString(int fieldSize, CharsetDecoder decoder) 968 throws CharacterCodingException { 969 checkFieldSize(fieldSize); 970 971 if (fieldSize == 0) { 972 return ""; 973 } 974 975 if (!hasRemaining()) { 976 return ""; 977 } 978 979 boolean utf16 = decoder.charset().name().startsWith("UTF-16"); 980 981 if (utf16 && ((fieldSize & 1) != 0)) { 982 throw new IllegalArgumentException ("fieldSize is not even."); 983 } 984 985 int oldPos = position(); 986 int oldLimit = limit(); 987 int end = position() + fieldSize; 988 989 if (oldLimit < end) { 990 throw new BufferUnderflowException (); 991 } 992 993 int i; 994 995 if (!utf16) { 996 for (i = 0; i < fieldSize; i++) { 997 if (get() == 0) { 998 break; 999 } 1000 } 1001 1002 if (i == fieldSize) { 1003 limit(end); 1004 } else { 1005 limit(position() - 1); 1006 } 1007 } else { 1008 for (i = 0; i < fieldSize; i += 2) { 1009 boolean highZero = (get() == 0); 1010 boolean lowZero = (get() == 0); 1011 if (highZero && lowZero) { 1012 break; 1013 } 1014 } 1015 1016 if (i == fieldSize) { 1017 limit(end); 1018 } else { 1019 limit(position() - 2); 1020 } 1021 } 1022 1023 position(oldPos); 1024 if (!hasRemaining()) { 1025 limit(oldLimit); 1026 position(end); 1027 return ""; 1028 } 1029 decoder.reset(); 1030 1031 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; 1032 CharBuffer out = CharBuffer.allocate(expectedLength); 1033 for (;;) { 1034 CoderResult cr; 1035 if (hasRemaining()) { 1036 cr = decoder.decode(buf(), out, true); 1037 } else { 1038 cr = decoder.flush(out); 1039 } 1040 1041 if (cr.isUnderflow()) { 1042 break; 1043 } 1044 1045 if (cr.isOverflow()) { 1046 CharBuffer o = CharBuffer.allocate(out.capacity() 1047 + expectedLength); 1048 out.flip(); 1049 o.put(out); 1050 out = o; 1051 continue; 1052 } 1053 1054 if (cr.isError()) { 1055 limit(oldLimit); 1057 position(oldPos); 1058 cr.throwException(); 1059 } 1060 } 1061 1062 limit(oldLimit); 1063 position(end); 1064 return out.flip().toString(); 1065 } 1066 1067 1074 public ByteBuffer putString(CharSequence val, CharsetEncoder encoder) 1075 throws CharacterCodingException { 1076 if (val.length() == 0) { 1077 return this; 1078 } 1079 1080 CharBuffer in = CharBuffer.wrap(val); 1081 encoder.reset(); 1082 1083 int expandedState = 0; 1084 1085 for (;;) { 1086 CoderResult cr; 1087 if (in.hasRemaining()) { 1088 cr = encoder.encode(in, buf(), true); 1089 } else { 1090 cr = encoder.flush(buf()); 1091 } 1092 1093 if (cr.isUnderflow()) { 1094 break; 1095 } 1096 if (cr.isOverflow()) { 1097 if (isAutoExpand()) { 1098 switch (expandedState) { 1099 case 0: 1100 autoExpand((int) Math.ceil(in.remaining() 1101 * encoder.averageBytesPerChar())); 1102 expandedState++; 1103 break; 1104 case 1: 1105 autoExpand((int) Math.ceil(in.remaining() 1106 * encoder.maxBytesPerChar())); 1107 expandedState++; 1108 break; 1109 default: 1110 throw new RuntimeException ("Expanded by " 1111 + (int) Math.ceil(in.remaining() 1112 * encoder.maxBytesPerChar()) 1113 + " but that wasn't enough for '" + val + "'"); 1114 } 1115 continue; 1116 } 1117 } else { 1118 expandedState = 0; 1119 } 1120 cr.throwException(); 1121 } 1122 return this; 1123 } 1124 1125 1139 public ByteBuffer putString(CharSequence val, int fieldSize, 1140 CharsetEncoder encoder) throws CharacterCodingException { 1141 checkFieldSize(fieldSize); 1142 1143 if (fieldSize == 0) 1144 return this; 1145 1146 autoExpand(fieldSize); 1147 1148 boolean utf16 = encoder.charset().name().startsWith("UTF-16"); 1149 1150 if (utf16 && ((fieldSize & 1) != 0)) { 1151 throw new IllegalArgumentException ("fieldSize is not even."); 1152 } 1153 1154 int oldLimit = limit(); 1155 int end = position() + fieldSize; 1156 1157 if (oldLimit < end) { 1158 throw new BufferOverflowException (); 1159 } 1160 1161 if (val.length() == 0) { 1162 if (!utf16) { 1163 put((byte) 0x00); 1164 } else { 1165 put((byte) 0x00); 1166 put((byte) 0x00); 1167 } 1168 position(end); 1169 return this; 1170 } 1171 1172 CharBuffer in = CharBuffer.wrap(val); 1173 limit(end); 1174 encoder.reset(); 1175 1176 for (;;) { 1177 CoderResult cr; 1178 if (in.hasRemaining()) { 1179 cr = encoder.encode(in, buf(), true); 1180 } else { 1181 cr = encoder.flush(buf()); 1182 } 1183 1184 if (cr.isUnderflow() || cr.isOverflow()) { 1185 break; 1186 } 1187 cr.throwException(); 1188 } 1189 1190 limit(oldLimit); 1191 1192 if (position() < end) { 1193 if (!utf16) { 1194 put((byte) 0x00); 1195 } else { 1196 put((byte) 0x00); 1197 put((byte) 0x00); 1198 } 1199 } 1200 1201 position(end); 1202 return this; 1203 } 1204 1205 1210 public String getPrefixedString(CharsetDecoder decoder) 1211 throws CharacterCodingException { 1212 return getPrefixedString(2, decoder); 1213 } 1214 1215 1221 public String getPrefixedString(int prefixLength, CharsetDecoder decoder) 1222 throws CharacterCodingException { 1223 if (!prefixedDataAvailable(prefixLength)) { 1224 throw new BufferUnderflowException (); 1225 } 1226 1227 int fieldSize = 0; 1228 1229 switch (prefixLength) { 1230 case 1: 1231 fieldSize = getUnsigned(); 1232 break; 1233 case 2: 1234 fieldSize = getUnsignedShort(); 1235 break; 1236 case 4: 1237 fieldSize = getInt(); 1238 break; 1239 } 1240 1241 if (fieldSize == 0) { 1242 return ""; 1243 } 1244 1245 boolean utf16 = decoder.charset().name().startsWith("UTF-16"); 1246 1247 if (utf16 && ((fieldSize & 1) != 0)) { 1248 throw new BufferDataException( 1249 "fieldSize is not even for a UTF-16 string."); 1250 } 1251 1252 int oldLimit = limit(); 1253 int end = position() + fieldSize; 1254 1255 if (oldLimit < end) { 1256 throw new BufferUnderflowException (); 1257 } 1258 1259 limit(end); 1260 decoder.reset(); 1261 1262 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; 1263 CharBuffer out = CharBuffer.allocate(expectedLength); 1264 for (;;) { 1265 CoderResult cr; 1266 if (hasRemaining()) { 1267 cr = decoder.decode(buf(), out, true); 1268 } else { 1269 cr = decoder.flush(out); 1270 } 1271 1272 if (cr.isUnderflow()) { 1273 break; 1274 } 1275 1276 if (cr.isOverflow()) { 1277 CharBuffer o = CharBuffer.allocate(out.capacity() 1278 + expectedLength); 1279 out.flip(); 1280 o.put(out); 1281 out = o; 1282 continue; 1283 } 1284 1285 cr.throwException(); 1286 } 1287 1288 limit(oldLimit); 1289 position(end); 1290 return out.flip().toString(); 1291 } 1292 1293 1301 public ByteBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) 1302 throws CharacterCodingException { 1303 return putPrefixedString(in, 2, 0, encoder); 1304 } 1305 1306 1316 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength, 1317 CharsetEncoder encoder) throws CharacterCodingException { 1318 return putPrefixedString(in, prefixLength, 0, encoder); 1319 } 1320 1321 1332 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength, 1333 int padding, CharsetEncoder encoder) 1334 throws CharacterCodingException { 1335 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder); 1336 } 1337 1338 1349 public ByteBuffer putPrefixedString(CharSequence val, int prefixLength, 1350 int padding, byte padValue, CharsetEncoder encoder) 1351 throws CharacterCodingException { 1352 int maxLength; 1353 switch (prefixLength) { 1354 case 1: 1355 maxLength = 255; 1356 break; 1357 case 2: 1358 maxLength = 65535; 1359 break; 1360 case 4: 1361 maxLength = Integer.MAX_VALUE; 1362 break; 1363 default: 1364 throw new IllegalArgumentException ("prefixLength: " + prefixLength); 1365 } 1366 1367 if (val.length() > maxLength) { 1368 throw new IllegalArgumentException ( 1369 "The specified string is too long."); 1370 } 1371 if (val.length() == 0) { 1372 switch (prefixLength) { 1373 case 1: 1374 put((byte) 0); 1375 break; 1376 case 2: 1377 putShort((short) 0); 1378 break; 1379 case 4: 1380 putInt(0); 1381 break; 1382 } 1383 return this; 1384 } 1385 1386 int padMask; 1387 switch (padding) { 1388 case 0: 1389 case 1: 1390 padMask = 0; 1391 break; 1392 case 2: 1393 padMask = 1; 1394 break; 1395 case 4: 1396 padMask = 3; 1397 break; 1398 default: 1399 throw new IllegalArgumentException ("padding: " + padding); 1400 } 1401 1402 CharBuffer in = CharBuffer.wrap(val); 1403 int expectedLength = (int) (in.remaining() * encoder 1404 .averageBytesPerChar()) + 1; 1405 1406 skip(prefixLength); int oldPos = position(); 1408 encoder.reset(); 1409 1410 for (;;) { 1411 CoderResult cr; 1412 if (in.hasRemaining()) { 1413 cr = encoder.encode(in, buf(), true); 1414 } else { 1415 cr = encoder.flush(buf()); 1416 } 1417 1418 if (position() - oldPos > maxLength) { 1419 throw new IllegalArgumentException ( 1420 "The specified string is too long."); 1421 } 1422 1423 if (cr.isUnderflow()) { 1424 break; 1425 } 1426 if (cr.isOverflow() && isAutoExpand()) { 1427 autoExpand(expectedLength); 1428 continue; 1429 } 1430 cr.throwException(); 1431 } 1432 1433 fill(padValue, padding - ((position() - oldPos) & padMask)); 1435 int length = position() - oldPos; 1436 switch (prefixLength) { 1437 case 1: 1438 put(oldPos - 1, (byte) length); 1439 break; 1440 case 2: 1441 putShort(oldPos - 2, (short) length); 1442 break; 1443 case 4: 1444 putInt(oldPos - 4, length); 1445 break; 1446 } 1447 return this; 1448 } 1449 1450 1454 public Object getObject() throws ClassNotFoundException { 1455 return getObject(Thread.currentThread().getContextClassLoader()); 1456 } 1457 1458 1461 public Object getObject(final ClassLoader classLoader) 1462 throws ClassNotFoundException { 1463 if (!prefixedDataAvailable(4)) { 1464 throw new BufferUnderflowException (); 1465 } 1466 1467 int length = getInt(); 1468 if (length <= 4) { 1469 throw new BufferDataException( 1470 "Object length should be greater than 4: " + length); 1471 } 1472 1473 int oldLimit = limit(); 1474 limit(position() + length); 1475 try { 1476 ObjectInputStream in = new ObjectInputStream (asInputStream()) { 1477 protected ObjectStreamClass readClassDescriptor() 1478 throws IOException , ClassNotFoundException { 1479 String className = readUTF(); 1480 Class <?> clazz = Class 1481 .forName(className, true, classLoader); 1482 return ObjectStreamClass.lookup(clazz); 1483 } 1484 }; 1485 return in.readObject(); 1486 } catch (IOException e) { 1487 throw new BufferDataException(e); 1488 } finally { 1489 limit(oldLimit); 1490 } 1491 } 1492 1493 1496 public ByteBuffer putObject(Object o) { 1497 int oldPos = position(); 1498 skip(4); try { 1500 ObjectOutputStream out = new ObjectOutputStream (asOutputStream()) { 1501 protected void writeClassDescriptor(ObjectStreamClass desc) 1502 throws IOException { 1503 writeUTF(desc.getName()); 1504 } 1505 }; 1506 out.writeObject(o); 1507 out.flush(); 1508 } catch (IOException e) { 1509 throw new BufferDataException(e); 1510 } 1511 1512 int newPos = position(); 1514 position(oldPos); 1515 putInt(newPos - oldPos - 4); 1516 position(newPos); 1517 return this; 1518 } 1519 1520 1535 public boolean prefixedDataAvailable(int prefixLength) { 1536 return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE); 1537 } 1538 1539 1550 public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) { 1551 if (remaining() < prefixLength) { 1552 return false; 1553 } 1554 1555 int dataLength; 1556 switch (prefixLength) { 1557 case 1: 1558 dataLength = getUnsigned(position()); 1559 break; 1560 case 2: 1561 dataLength = getUnsignedShort(position()); 1562 break; 1563 case 4: 1564 dataLength = getInt(position()); 1565 break; 1566 default: 1567 throw new IllegalArgumentException ("prefixLength: " + prefixLength); 1568 } 1569 1570 if (dataLength < 0 || dataLength > maxDataLength) { 1571 throw new BufferDataException("dataLength: " + dataLength); 1572 } 1573 1574 return remaining() - prefixLength >= dataLength; 1575 } 1576 1577 1581 1585 public ByteBuffer skip(int size) { 1586 autoExpand(size); 1587 return position(position() + size); 1588 } 1589 1590 1594 public ByteBuffer fill(byte value, int size) { 1595 autoExpand(size); 1596 int q = size >>> 3; 1597 int r = size & 7; 1598 1599 if (q > 0) { 1600 int intValue = value | (value << 8) | (value << 16) | (value << 24); 1601 long longValue = intValue; 1602 longValue <<= 32; 1603 longValue |= intValue; 1604 1605 for (int i = q; i > 0; i--) { 1606 putLong(longValue); 1607 } 1608 } 1609 1610 q = r >>> 2; 1611 r = r & 3; 1612 1613 if (q > 0) { 1614 int intValue = value | (value << 8) | (value << 16) | (value << 24); 1615 putInt(intValue); 1616 } 1617 1618 q = r >> 1; 1619 r = r & 1; 1620 1621 if (q > 0) { 1622 short shortValue = (short) (value | (value << 8)); 1623 putShort(shortValue); 1624 } 1625 1626 if (r > 0) { 1627 put(value); 1628 } 1629 1630 return this; 1631 } 1632 1633 1637 public ByteBuffer fillAndReset(byte value, int size) { 1638 autoExpand(size); 1639 int pos = position(); 1640 try { 1641 fill(value, size); 1642 } finally { 1643 position(pos); 1644 } 1645 return this; 1646 } 1647 1648 1652 public ByteBuffer fill(int size) { 1653 autoExpand(size); 1654 int q = size >>> 3; 1655 int r = size & 7; 1656 1657 for (int i = q; i > 0; i--) { 1658 putLong(0L); 1659 } 1660 1661 q = r >>> 2; 1662 r = r & 3; 1663 1664 if (q > 0) { 1665 putInt(0); 1666 } 1667 1668 q = r >> 1; 1669 r = r & 1; 1670 1671 if (q > 0) { 1672 putShort((short) 0); 1673 } 1674 1675 if (r > 0) { 1676 put((byte) 0); 1677 } 1678 1679 return this; 1680 } 1681 1682 1686 public ByteBuffer fillAndReset(int size) { 1687 autoExpand(size); 1688 int pos = position(); 1689 try { 1690 fill(size); 1691 } finally { 1692 position(pos); 1693 } 1694 1695 return this; 1696 } 1697 1698 1702 protected ByteBuffer autoExpand(int expectedRemaining) { 1703 if (isAutoExpand()) { 1704 expand(expectedRemaining); 1705 } 1706 return this; 1707 } 1708 1709 1713 protected ByteBuffer autoExpand(int pos, int expectedRemaining) { 1714 if (isAutoExpand()) { 1715 expand(pos, expectedRemaining); 1716 } 1717 return this; 1718 } 1719 1720 private static void checkFieldSize(int fieldSize) { 1721 if (fieldSize < 0) { 1722 throw new IllegalArgumentException ("fieldSize cannot be negative: " 1723 + fieldSize); 1724 } 1725 } 1726} 1727 | Popular Tags |