1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.common;
21
22 import java.io.EOFException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.ObjectStreamClass;
28 import java.io.OutputStream;
29 import java.io.StreamCorruptedException;
30 import java.nio.BufferOverflowException;
31 import java.nio.BufferUnderflowException;
32 import java.nio.ByteOrder;
33 import java.nio.CharBuffer;
34 import java.nio.DoubleBuffer;
35 import java.nio.FloatBuffer;
36 import java.nio.IntBuffer;
37 import java.nio.LongBuffer;
38 import java.nio.ShortBuffer;
39 import java.nio.charset.CharacterCodingException;
40 import java.nio.charset.CharsetDecoder;
41 import java.nio.charset.CharsetEncoder;
42 import java.nio.charset.CoderResult;
43 import java.util.HashSet;
44 import java.util.Set;
45
46 import org.apache.mina.common.support.ByteBufferHexDumper;
47 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 public abstract class ByteBuffer implements Comparable<ByteBuffer> {
159 private static ByteBufferAllocator allocator = new PooledByteBufferAllocator();
160
161 private static boolean useDirectBuffers = true;
162
163
164
165
166 public static ByteBufferAllocator getAllocator() {
167 return allocator;
168 }
169
170
171
172
173
174 public static void setAllocator(ByteBufferAllocator newAllocator) {
175 if (newAllocator == null) {
176 throw new NullPointerException("allocator");
177 }
178
179 ByteBufferAllocator oldAllocator = allocator;
180
181 allocator = newAllocator;
182
183 if (null != oldAllocator) {
184 oldAllocator.dispose();
185 }
186 }
187
188 public static boolean isUseDirectBuffers() {
189 return useDirectBuffers;
190 }
191
192 public static void setUseDirectBuffers(boolean useDirectBuffers) {
193 ByteBuffer.useDirectBuffers = useDirectBuffers;
194 }
195
196
197
198
199
200
201
202
203
204 public static ByteBuffer allocate(int capacity) {
205 if (useDirectBuffers) {
206 try {
207
208 return allocate(capacity, true);
209 } catch (OutOfMemoryError e) {
210
211 }
212 }
213
214 return allocate(capacity, false);
215 }
216
217
218
219
220
221
222
223
224 public static ByteBuffer allocate(int capacity, boolean direct) {
225 return allocator.allocate(capacity, direct);
226 }
227
228
229
230
231 public static ByteBuffer wrap(java.nio.ByteBuffer nioBuffer) {
232 return allocator.wrap(nioBuffer);
233 }
234
235
236
237
238 public static ByteBuffer wrap(byte[] byteArray) {
239 return wrap(java.nio.ByteBuffer.wrap(byteArray));
240 }
241
242
243
244
245
246
247
248 public static ByteBuffer wrap(byte[] byteArray, int offset, int length) {
249 return wrap(java.nio.ByteBuffer.wrap(byteArray, offset, length));
250 }
251
252 private static final Set<String> primitiveTypeNames = new HashSet<String>();
253
254 static {
255 primitiveTypeNames.add("void");
256 primitiveTypeNames.add("boolean");
257 primitiveTypeNames.add("byte");
258 primitiveTypeNames.add("char");
259 primitiveTypeNames.add("short");
260 primitiveTypeNames.add("int");
261 primitiveTypeNames.add("long");
262 primitiveTypeNames.add("float");
263 primitiveTypeNames.add("double");
264 }
265
266 protected ByteBuffer() {
267 }
268
269
270
271
272
273
274
275
276
277 public abstract void acquire();
278
279
280
281
282
283
284
285 public abstract void release();
286
287
288
289
290 public abstract java.nio.ByteBuffer buf();
291
292
293
294
295 public abstract boolean isDirect();
296
297
298
299
300 public abstract boolean isReadOnly();
301
302
303
304
305 public abstract int capacity();
306
307
308
309
310 public abstract ByteBuffer capacity(int newCapacity);
311
312
313
314
315 public abstract boolean isAutoExpand();
316
317
318
319
320 public abstract ByteBuffer setAutoExpand(boolean autoExpand);
321
322
323
324
325
326
327
328 public ByteBuffer expand(int expectedRemaining) {
329 return expand(position(), expectedRemaining);
330 }
331
332
333
334
335
336
337
338
339 public abstract ByteBuffer expand(int pos, int expectedRemaining);
340
341
342
343
344
345
346
347
348
349
350 public abstract boolean isPooled();
351
352
353
354
355
356
357
358
359
360 public abstract void setPooled(boolean pooled);
361
362
363
364
365 public abstract int position();
366
367
368
369
370 public abstract ByteBuffer position(int newPosition);
371
372
373
374
375 public abstract int limit();
376
377
378
379
380 public abstract ByteBuffer limit(int newLimit);
381
382
383
384
385 public abstract ByteBuffer mark();
386
387
388
389
390
391 public abstract int markValue();
392
393
394
395
396 public abstract ByteBuffer reset();
397
398
399
400
401 public abstract ByteBuffer clear();
402
403
404
405
406
407
408 public ByteBuffer sweep() {
409 clear();
410 return fillAndReset(remaining());
411 }
412
413
414
415
416
417
418 public ByteBuffer sweep(byte value) {
419 clear();
420 return fillAndReset(value, remaining());
421 }
422
423
424
425
426 public abstract ByteBuffer flip();
427
428
429
430
431 public abstract ByteBuffer rewind();
432
433
434
435
436 public int remaining() {
437 return limit() - position();
438 }
439
440
441
442
443 public boolean hasRemaining() {
444 return remaining() > 0;
445 }
446
447
448
449
450 public abstract ByteBuffer duplicate();
451
452
453
454
455 public abstract ByteBuffer slice();
456
457
458
459
460 public abstract ByteBuffer asReadOnlyBuffer();
461
462
463
464
465 public abstract byte[] array();
466
467
468
469
470 public abstract int arrayOffset();
471
472
473
474
475 public abstract byte get();
476
477
478
479
480 public short getUnsigned() {
481 return (short) (get() & 0xff);
482 }
483
484
485
486
487 public abstract ByteBuffer put(byte b);
488
489
490
491
492 public abstract byte get(int index);
493
494
495
496
497 public short getUnsigned(int index) {
498 return (short) (get(index) & 0xff);
499 }
500
501
502
503
504 public abstract ByteBuffer put(int index, byte b);
505
506
507
508
509 public abstract ByteBuffer get(byte[] dst, int offset, int length);
510
511
512
513
514 public ByteBuffer get(byte[] dst) {
515 return get(dst, 0, dst.length);
516 }
517
518
519
520
521 public abstract ByteBuffer put(java.nio.ByteBuffer src);
522
523
524
525
526 public ByteBuffer put(ByteBuffer src) {
527 return put(src.buf());
528 }
529
530
531
532
533 public abstract ByteBuffer put(byte[] src, int offset, int length);
534
535
536
537
538 public ByteBuffer put(byte[] src) {
539 return put(src, 0, src.length);
540 }
541
542
543
544
545 public abstract ByteBuffer compact();
546
547 @Override
548 public String toString() {
549 StringBuffer buf = new StringBuffer();
550 if (isDirect()) {
551 buf.append("DirectBuffer");
552 } else {
553 buf.append("HeapBuffer");
554 }
555 buf.append("[pos=");
556 buf.append(position());
557 buf.append(" lim=");
558 buf.append(limit());
559 buf.append(" cap=");
560 buf.append(capacity());
561 buf.append(": ");
562 buf.append(getHexDump());
563 buf.append(']');
564 return buf.toString();
565 }
566
567 @Override
568 public int hashCode() {
569 int h = 1;
570 int p = position();
571 for (int i = limit() - 1; i >= p; i--) {
572 h = 31 * h + get(i);
573 }
574 return h;
575 }
576
577 @Override
578 public boolean equals(Object o) {
579 if (!(o instanceof ByteBuffer)) {
580 return false;
581 }
582
583 ByteBuffer that = (ByteBuffer) o;
584 if (this.remaining() != that.remaining()) {
585 return false;
586 }
587
588 int p = this.position();
589 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
590 byte v1 = this.get(i);
591 byte v2 = that.get(j);
592 if (v1 != v2) {
593 return false;
594 }
595 }
596 return true;
597 }
598
599 public int compareTo(ByteBuffer that) {
600 int n = this.position() + Math.min(this.remaining(), that.remaining());
601 for (int i = this.position(), j = that.position(); i < n; i++, j++) {
602 byte v1 = this.get(i);
603 byte v2 = that.get(j);
604 if (v1 == v2) {
605 continue;
606 }
607 if (v1 < v2) {
608 return -1;
609 }
610
611 return +1;
612 }
613 return this.remaining() - that.remaining();
614 }
615
616
617
618
619 public abstract ByteOrder order();
620
621
622
623
624 public abstract ByteBuffer order(ByteOrder bo);
625
626
627
628
629 public abstract char getChar();
630
631
632
633
634 public abstract ByteBuffer putChar(char value);
635
636
637
638
639 public abstract char getChar(int index);
640
641
642
643
644 public abstract ByteBuffer putChar(int index, char value);
645
646
647
648
649 public abstract CharBuffer asCharBuffer();
650
651
652
653
654 public abstract short getShort();
655
656
657
658
659 public int getUnsignedShort() {
660 return getShort() & 0xffff;
661 }
662
663
664
665
666 public abstract ByteBuffer putShort(short value);
667
668
669
670
671 public abstract short getShort(int index);
672
673
674
675
676 public int getUnsignedShort(int index) {
677 return getShort(index) & 0xffff;
678 }
679
680
681
682
683 public abstract ByteBuffer putShort(int index, short value);
684
685
686
687
688 public abstract ShortBuffer asShortBuffer();
689
690
691
692
693 public abstract int getInt();
694
695
696
697
698 public long getUnsignedInt() {
699 return getInt() & 0xffffffffL;
700 }
701
702
703
704
705 public abstract ByteBuffer putInt(int value);
706
707
708
709
710 public abstract int getInt(int index);
711
712
713
714
715 public long getUnsignedInt(int index) {
716 return getInt(index) & 0xffffffffL;
717 }
718
719
720
721
722 public abstract ByteBuffer putInt(int index, int value);
723
724
725
726
727 public abstract IntBuffer asIntBuffer();
728
729
730
731
732 public abstract long getLong();
733
734
735
736
737 public abstract ByteBuffer putLong(long value);
738
739
740
741
742 public abstract long getLong(int index);
743
744
745
746
747 public abstract ByteBuffer putLong(int index, long value);
748
749
750
751
752 public abstract LongBuffer asLongBuffer();
753
754
755
756
757 public abstract float getFloat();
758
759
760
761
762 public abstract ByteBuffer putFloat(float value);
763
764
765
766
767 public abstract float getFloat(int index);
768
769
770
771
772 public abstract ByteBuffer putFloat(int index, float value);
773
774
775
776
777 public abstract FloatBuffer asFloatBuffer();
778
779
780
781
782 public abstract double getDouble();
783
784
785
786
787 public abstract ByteBuffer putDouble(double value);
788
789
790
791
792 public abstract double getDouble(int index);
793
794
795
796
797 public abstract ByteBuffer putDouble(int index, double value);
798
799
800
801
802 public abstract DoubleBuffer asDoubleBuffer();
803
804
805
806
807
808
809 public InputStream asInputStream() {
810 return new InputStream() {
811 @Override
812 public int available() {
813 return ByteBuffer.this.remaining();
814 }
815
816 @Override
817 public synchronized void mark(int readlimit) {
818 ByteBuffer.this.mark();
819 }
820
821 @Override
822 public boolean markSupported() {
823 return true;
824 }
825
826 @Override
827 public int read() {
828 if (ByteBuffer.this.hasRemaining()) {
829 return ByteBuffer.this.get() & 0xff;
830 } else {
831 return -1;
832 }
833 }
834
835 @Override
836 public int read(byte[] b, int off, int len) {
837 int remaining = ByteBuffer.this.remaining();
838 if (remaining > 0) {
839 int readBytes = Math.min(remaining, len);
840 ByteBuffer.this.get(b, off, readBytes);
841 return readBytes;
842 } else {
843 return -1;
844 }
845 }
846
847 @Override
848 public synchronized void reset() {
849 ByteBuffer.this.reset();
850 }
851
852 @Override
853 public long skip(long n) {
854 int bytes;
855 if (n > Integer.MAX_VALUE) {
856 bytes = ByteBuffer.this.remaining();
857 } else {
858 bytes = Math.min(ByteBuffer.this.remaining(), (int) n);
859 }
860 ByteBuffer.this.skip(bytes);
861 return bytes;
862 }
863 };
864 }
865
866
867
868
869
870
871
872
873
874 public OutputStream asOutputStream() {
875 return new OutputStream() {
876 @Override
877 public void write(byte[] b, int off, int len) {
878 ByteBuffer.this.put(b, off, len);
879 }
880
881 @Override
882 public void write(int b) {
883 ByteBuffer.this.put((byte) b);
884 }
885 };
886 }
887
888
889
890
891 public String getHexDump() {
892 return ByteBufferHexDumper.getHexdump(this);
893 }
894
895
896
897
898
899
900
901
902
903
904 public String getString(CharsetDecoder decoder)
905 throws CharacterCodingException {
906 if (!hasRemaining()) {
907 return "";
908 }
909
910 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
911
912 int oldPos = position();
913 int oldLimit = limit();
914 int end;
915
916 if (!utf16) {
917 while (hasRemaining()) {
918 if (get() == 0) {
919 break;
920 }
921 }
922
923 end = position();
924 if (end == oldLimit && get(end - 1) != 0) {
925 limit(end);
926 } else {
927 limit(end - 1);
928 }
929 } else {
930 while (remaining() >= 2) {
931 boolean highZero = (get() == 0);
932 boolean lowZero = (get() == 0);
933 if (highZero && lowZero) {
934 break;
935 }
936 }
937
938 end = position();
939 if (end == oldLimit || end == oldLimit - 1) {
940 limit(end);
941 } else {
942 limit(end - 2);
943 }
944 }
945
946 position(oldPos);
947 if (!hasRemaining()) {
948 limit(oldLimit);
949 position(end);
950 return "";
951 }
952 decoder.reset();
953
954 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
955 CharBuffer out = CharBuffer.allocate(expectedLength);
956 for (;;) {
957 CoderResult cr;
958 if (hasRemaining()) {
959 cr = decoder.decode(buf(), out, true);
960 } else {
961 cr = decoder.flush(out);
962 }
963
964 if (cr.isUnderflow()) {
965 break;
966 }
967
968 if (cr.isOverflow()) {
969 CharBuffer o = CharBuffer.allocate(out.capacity()
970 + expectedLength);
971 out.flip();
972 o.put(out);
973 out = o;
974 continue;
975 }
976
977 if (cr.isError()) {
978
979 limit(oldLimit);
980 position(oldPos);
981 cr.throwException();
982 }
983 }
984
985 limit(oldLimit);
986 position(end);
987 return out.flip().toString();
988 }
989
990
991
992
993
994
995
996 public String getString(int fieldSize, CharsetDecoder decoder)
997 throws CharacterCodingException {
998 checkFieldSize(fieldSize);
999
1000 if (fieldSize == 0) {
1001 return "";
1002 }
1003
1004 if (!hasRemaining()) {
1005 return "";
1006 }
1007
1008 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1009
1010 if (utf16 && ((fieldSize & 1) != 0)) {
1011 throw new IllegalArgumentException("fieldSize is not even.");
1012 }
1013
1014 int oldPos = position();
1015 int oldLimit = limit();
1016 int end = position() + fieldSize;
1017
1018 if (oldLimit < end) {
1019 throw new BufferUnderflowException();
1020 }
1021
1022 int i;
1023
1024 if (!utf16) {
1025 for (i = 0; i < fieldSize; i++) {
1026 if (get() == 0) {
1027 break;
1028 }
1029 }
1030
1031 if (i == fieldSize) {
1032 limit(end);
1033 } else {
1034 limit(position() - 1);
1035 }
1036 } else {
1037 for (i = 0; i < fieldSize; i += 2) {
1038 boolean highZero = (get() == 0);
1039 boolean lowZero = (get() == 0);
1040 if (highZero && lowZero) {
1041 break;
1042 }
1043 }
1044
1045 if (i == fieldSize) {
1046 limit(end);
1047 } else {
1048 limit(position() - 2);
1049 }
1050 }
1051
1052 position(oldPos);
1053 if (!hasRemaining()) {
1054 limit(oldLimit);
1055 position(end);
1056 return "";
1057 }
1058 decoder.reset();
1059
1060 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1061 CharBuffer out = CharBuffer.allocate(expectedLength);
1062 for (;;) {
1063 CoderResult cr;
1064 if (hasRemaining()) {
1065 cr = decoder.decode(buf(), out, true);
1066 } else {
1067 cr = decoder.flush(out);
1068 }
1069
1070 if (cr.isUnderflow()) {
1071 break;
1072 }
1073
1074 if (cr.isOverflow()) {
1075 CharBuffer o = CharBuffer.allocate(out.capacity()
1076 + expectedLength);
1077 out.flip();
1078 o.put(out);
1079 out = o;
1080 continue;
1081 }
1082
1083 if (cr.isError()) {
1084
1085 limit(oldLimit);
1086 position(oldPos);
1087 cr.throwException();
1088 }
1089 }
1090
1091 limit(oldLimit);
1092 position(end);
1093 return out.flip().toString();
1094 }
1095
1096
1097
1098
1099
1100
1101
1102
1103 public ByteBuffer putString(CharSequence val, CharsetEncoder encoder)
1104 throws CharacterCodingException {
1105 if (val.length() == 0) {
1106 return this;
1107 }
1108
1109 CharBuffer in = CharBuffer.wrap(val);
1110 encoder.reset();
1111
1112 int expandedState = 0;
1113
1114 for (;;) {
1115 CoderResult cr;
1116 if (in.hasRemaining()) {
1117 cr = encoder.encode(in, buf(), true);
1118 } else {
1119 cr = encoder.flush(buf());
1120 }
1121
1122 if (cr.isUnderflow()) {
1123 break;
1124 }
1125 if (cr.isOverflow()) {
1126 if (isAutoExpand()) {
1127 switch (expandedState) {
1128 case 0:
1129 autoExpand((int) Math.ceil(in.remaining()
1130 * encoder.averageBytesPerChar()));
1131 expandedState++;
1132 break;
1133 case 1:
1134 autoExpand((int) Math.ceil(in.remaining()
1135 * encoder.maxBytesPerChar()));
1136 expandedState++;
1137 break;
1138 default:
1139 throw new RuntimeException("Expanded by "
1140 + (int) Math.ceil(in.remaining()
1141 * encoder.maxBytesPerChar())
1142 + " but that wasn't enough for '" + val + "'");
1143 }
1144 continue;
1145 }
1146 } else {
1147 expandedState = 0;
1148 }
1149 cr.throwException();
1150 }
1151 return this;
1152 }
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 public ByteBuffer putString(CharSequence val, int fieldSize,
1169 CharsetEncoder encoder) throws CharacterCodingException {
1170 checkFieldSize(fieldSize);
1171
1172 if (fieldSize == 0)
1173 return this;
1174
1175 autoExpand(fieldSize);
1176
1177 boolean utf16 = encoder.charset().name().startsWith("UTF-16");
1178
1179 if (utf16 && ((fieldSize & 1) != 0)) {
1180 throw new IllegalArgumentException("fieldSize is not even.");
1181 }
1182
1183 int oldLimit = limit();
1184 int end = position() + fieldSize;
1185
1186 if (oldLimit < end) {
1187 throw new BufferOverflowException();
1188 }
1189
1190 if (val.length() == 0) {
1191 if (!utf16) {
1192 put((byte) 0x00);
1193 } else {
1194 put((byte) 0x00);
1195 put((byte) 0x00);
1196 }
1197 position(end);
1198 return this;
1199 }
1200
1201 CharBuffer in = CharBuffer.wrap(val);
1202 limit(end);
1203 encoder.reset();
1204
1205 for (;;) {
1206 CoderResult cr;
1207 if (in.hasRemaining()) {
1208 cr = encoder.encode(in, buf(), true);
1209 } else {
1210 cr = encoder.flush(buf());
1211 }
1212
1213 if (cr.isUnderflow() || cr.isOverflow()) {
1214 break;
1215 }
1216 cr.throwException();
1217 }
1218
1219 limit(oldLimit);
1220
1221 if (position() < end) {
1222 if (!utf16) {
1223 put((byte) 0x00);
1224 } else {
1225 put((byte) 0x00);
1226 put((byte) 0x00);
1227 }
1228 }
1229
1230 position(end);
1231 return this;
1232 }
1233
1234
1235
1236
1237
1238
1239 public String getPrefixedString(CharsetDecoder decoder)
1240 throws CharacterCodingException {
1241 return getPrefixedString(2, decoder);
1242 }
1243
1244
1245
1246
1247
1248
1249
1250 public String getPrefixedString(int prefixLength, CharsetDecoder decoder)
1251 throws CharacterCodingException {
1252 if (!prefixedDataAvailable(prefixLength)) {
1253 throw new BufferUnderflowException();
1254 }
1255
1256 int fieldSize = 0;
1257
1258 switch (prefixLength) {
1259 case 1:
1260 fieldSize = getUnsigned();
1261 break;
1262 case 2:
1263 fieldSize = getUnsignedShort();
1264 break;
1265 case 4:
1266 fieldSize = getInt();
1267 break;
1268 }
1269
1270 if (fieldSize == 0) {
1271 return "";
1272 }
1273
1274 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1275
1276 if (utf16 && ((fieldSize & 1) != 0)) {
1277 throw new BufferDataException(
1278 "fieldSize is not even for a UTF-16 string.");
1279 }
1280
1281 int oldLimit = limit();
1282 int end = position() + fieldSize;
1283
1284 if (oldLimit < end) {
1285 throw new BufferUnderflowException();
1286 }
1287
1288 limit(end);
1289 decoder.reset();
1290
1291 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1292 CharBuffer out = CharBuffer.allocate(expectedLength);
1293 for (;;) {
1294 CoderResult cr;
1295 if (hasRemaining()) {
1296 cr = decoder.decode(buf(), out, true);
1297 } else {
1298 cr = decoder.flush(out);
1299 }
1300
1301 if (cr.isUnderflow()) {
1302 break;
1303 }
1304
1305 if (cr.isOverflow()) {
1306 CharBuffer o = CharBuffer.allocate(out.capacity()
1307 + expectedLength);
1308 out.flip();
1309 o.put(out);
1310 out = o;
1311 continue;
1312 }
1313
1314 cr.throwException();
1315 }
1316
1317 limit(oldLimit);
1318 position(end);
1319 return out.flip().toString();
1320 }
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330 public ByteBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder)
1331 throws CharacterCodingException {
1332 return putPrefixedString(in, 2, 0, encoder);
1333 }
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength,
1346 CharsetEncoder encoder) throws CharacterCodingException {
1347 return putPrefixedString(in, prefixLength, 0, encoder);
1348 }
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength,
1362 int padding, CharsetEncoder encoder)
1363 throws CharacterCodingException {
1364 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
1365 }
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378 public ByteBuffer putPrefixedString(CharSequence val, int prefixLength,
1379 int padding, byte padValue, CharsetEncoder encoder)
1380 throws CharacterCodingException {
1381 int maxLength;
1382 switch (prefixLength) {
1383 case 1:
1384 maxLength = 255;
1385 break;
1386 case 2:
1387 maxLength = 65535;
1388 break;
1389 case 4:
1390 maxLength = Integer.MAX_VALUE;
1391 break;
1392 default:
1393 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1394 }
1395
1396 if (val.length() > maxLength) {
1397 throw new IllegalArgumentException(
1398 "The specified string is too long.");
1399 }
1400 if (val.length() == 0) {
1401 switch (prefixLength) {
1402 case 1:
1403 put((byte) 0);
1404 break;
1405 case 2:
1406 putShort((short) 0);
1407 break;
1408 case 4:
1409 putInt(0);
1410 break;
1411 }
1412 return this;
1413 }
1414
1415 int padMask;
1416 switch (padding) {
1417 case 0:
1418 case 1:
1419 padMask = 0;
1420 break;
1421 case 2:
1422 padMask = 1;
1423 break;
1424 case 4:
1425 padMask = 3;
1426 break;
1427 default:
1428 throw new IllegalArgumentException("padding: " + padding);
1429 }
1430
1431 CharBuffer in = CharBuffer.wrap(val);
1432 int expectedLength = (int) (in.remaining() * encoder
1433 .averageBytesPerChar()) + 1;
1434
1435 skip(prefixLength);
1436 int oldPos = position();
1437 encoder.reset();
1438
1439 for (;;) {
1440 CoderResult cr;
1441 if (in.hasRemaining()) {
1442 cr = encoder.encode(in, buf(), true);
1443 } else {
1444 cr = encoder.flush(buf());
1445 }
1446
1447 if (position() - oldPos > maxLength) {
1448 throw new IllegalArgumentException(
1449 "The specified string is too long.");
1450 }
1451
1452 if (cr.isUnderflow()) {
1453 break;
1454 }
1455 if (cr.isOverflow() && isAutoExpand()) {
1456 autoExpand(expectedLength);
1457 continue;
1458 }
1459 cr.throwException();
1460 }
1461
1462
1463 fill(padValue, padding - ((position() - oldPos) & padMask));
1464 int length = position() - oldPos;
1465 switch (prefixLength) {
1466 case 1:
1467 put(oldPos - 1, (byte) length);
1468 break;
1469 case 2:
1470 putShort(oldPos - 2, (short) length);
1471 break;
1472 case 4:
1473 putInt(oldPos - 4, length);
1474 break;
1475 }
1476 return this;
1477 }
1478
1479
1480
1481
1482
1483 public Object getObject() throws ClassNotFoundException {
1484 return getObject(Thread.currentThread().getContextClassLoader());
1485 }
1486
1487
1488
1489
1490 public Object getObject(final ClassLoader classLoader)
1491 throws ClassNotFoundException {
1492 if (!prefixedDataAvailable(4)) {
1493 throw new BufferUnderflowException();
1494 }
1495
1496 int length = getInt();
1497 if (length <= 4) {
1498 throw new BufferDataException(
1499 "Object length should be greater than 4: " + length);
1500 }
1501
1502 int oldLimit = limit();
1503 limit(position() + length);
1504 try {
1505 ObjectInputStream in = new ObjectInputStream(asInputStream()) {
1506 @Override
1507 protected ObjectStreamClass readClassDescriptor()
1508 throws IOException, ClassNotFoundException {
1509 int type = read();
1510 if (type < 0) {
1511 throw new EOFException();
1512 }
1513 switch (type) {
1514 case 0:
1515 return super.readClassDescriptor();
1516 case 1:
1517 String className = readUTF();
1518 Class<?> clazz =
1519 Class.forName(className, true, classLoader);
1520 return ObjectStreamClass.lookup(clazz);
1521 default:
1522 throw new StreamCorruptedException(
1523 "Unexpected class descriptor type: " + type);
1524 }
1525 }
1526
1527 @Override
1528 protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
1529 String name = desc.getName();
1530 try {
1531 return Class.forName(name, false, classLoader);
1532 } catch (ClassNotFoundException ex) {
1533 return super.resolveClass(desc);
1534 }
1535 }
1536 };
1537 return in.readObject();
1538 } catch (IOException e) {
1539 throw new BufferDataException(e);
1540 } finally {
1541 limit(oldLimit);
1542 }
1543 }
1544
1545
1546
1547
1548 public ByteBuffer putObject(Object o) {
1549 int oldPos = position();
1550 skip(4);
1551 try {
1552 ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
1553 @Override
1554 protected void writeClassDescriptor(ObjectStreamClass desc)
1555 throws IOException {
1556 String className = desc.getName();
1557 if (primitiveTypeNames.contains(className)) {
1558 write(0);
1559 super.writeClassDescriptor(desc);
1560 } else {
1561 write(1);
1562 writeUTF(desc.getName());
1563 }
1564 }
1565 };
1566 out.writeObject(o);
1567 out.flush();
1568 } catch (IOException e) {
1569 throw new BufferDataException(e);
1570 }
1571
1572
1573 int newPos = position();
1574 position(oldPos);
1575 putInt(newPos - oldPos - 4);
1576 position(newPos);
1577 return this;
1578 }
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595 public boolean prefixedDataAvailable(int prefixLength) {
1596 return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
1597 }
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610 public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
1611 if (remaining() < prefixLength) {
1612 return false;
1613 }
1614
1615 int dataLength;
1616 switch (prefixLength) {
1617 case 1:
1618 dataLength = getUnsigned(position());
1619 break;
1620 case 2:
1621 dataLength = getUnsignedShort(position());
1622 break;
1623 case 4:
1624 dataLength = getInt(position());
1625 break;
1626 default:
1627 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1628 }
1629
1630 if (dataLength < 0 || dataLength > maxDataLength) {
1631 throw new BufferDataException("dataLength: " + dataLength);
1632 }
1633
1634 return remaining() - prefixLength >= dataLength;
1635 }
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645 public ByteBuffer skip(int size) {
1646 autoExpand(size);
1647 return position(position() + size);
1648 }
1649
1650
1651
1652
1653
1654 public ByteBuffer fill(byte value, int size) {
1655 autoExpand(size);
1656 int q = size >>> 3;
1657 int r = size & 7;
1658
1659 if (q > 0) {
1660 int intValue = value | (value << 8) | (value << 16) | (value << 24);
1661 long longValue = intValue;
1662 longValue <<= 32;
1663 longValue |= intValue;
1664
1665 for (int i = q; i > 0; i--) {
1666 putLong(longValue);
1667 }
1668 }
1669
1670 q = r >>> 2;
1671 r = r & 3;
1672
1673 if (q > 0) {
1674 int intValue = value | (value << 8) | (value << 16) | (value << 24);
1675 putInt(intValue);
1676 }
1677
1678 q = r >> 1;
1679 r = r & 1;
1680
1681 if (q > 0) {
1682 short shortValue = (short) (value | (value << 8));
1683 putShort(shortValue);
1684 }
1685
1686 if (r > 0) {
1687 put(value);
1688 }
1689
1690 return this;
1691 }
1692
1693
1694
1695
1696
1697 public ByteBuffer fillAndReset(byte value, int size) {
1698 autoExpand(size);
1699 int pos = position();
1700 try {
1701 fill(value, size);
1702 } finally {
1703 position(pos);
1704 }
1705 return this;
1706 }
1707
1708
1709
1710
1711
1712 public ByteBuffer fill(int size) {
1713 autoExpand(size);
1714 int q = size >>> 3;
1715 int r = size & 7;
1716
1717 for (int i = q; i > 0; i--) {
1718 putLong(0L);
1719 }
1720
1721 q = r >>> 2;
1722 r = r & 3;
1723
1724 if (q > 0) {
1725 putInt(0);
1726 }
1727
1728 q = r >> 1;
1729 r = r & 1;
1730
1731 if (q > 0) {
1732 putShort((short) 0);
1733 }
1734
1735 if (r > 0) {
1736 put((byte) 0);
1737 }
1738
1739 return this;
1740 }
1741
1742
1743
1744
1745
1746 public ByteBuffer fillAndReset(int size) {
1747 autoExpand(size);
1748 int pos = position();
1749 try {
1750 fill(size);
1751 } finally {
1752 position(pos);
1753 }
1754
1755 return this;
1756 }
1757
1758
1759
1760
1761
1762 protected ByteBuffer autoExpand(int expectedRemaining) {
1763 if (isAutoExpand()) {
1764 expand(expectedRemaining);
1765 }
1766 return this;
1767 }
1768
1769
1770
1771
1772
1773 protected ByteBuffer autoExpand(int pos, int expectedRemaining) {
1774 if (isAutoExpand()) {
1775 expand(pos, expectedRemaining);
1776 }
1777 return this;
1778 }
1779
1780 private static void checkFieldSize(int fieldSize) {
1781 if (fieldSize < 0) {
1782 throw new IllegalArgumentException("fieldSize cannot be negative: "
1783 + fieldSize);
1784 }
1785 }
1786 }