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 {
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 primitiveTypeNames = new HashSet();
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 public String toString() {
548 StringBuffer buf = new StringBuffer();
549 if (isDirect()) {
550 buf.append("DirectBuffer");
551 } else {
552 buf.append("HeapBuffer");
553 }
554 buf.append("[pos=");
555 buf.append(position());
556 buf.append(" lim=");
557 buf.append(limit());
558 buf.append(" cap=");
559 buf.append(capacity());
560 buf.append(": ");
561 buf.append(getHexDump());
562 buf.append(']');
563 return buf.toString();
564 }
565
566 public int hashCode() {
567 int h = 1;
568 int p = position();
569 for (int i = limit() - 1; i >= p; i--) {
570 h = 31 * h + get(i);
571 }
572 return h;
573 }
574
575 public boolean equals(Object o) {
576 if (!(o instanceof ByteBuffer)) {
577 return false;
578 }
579
580 ByteBuffer that = (ByteBuffer) o;
581 if (this.remaining() != that.remaining()) {
582 return false;
583 }
584
585 int p = this.position();
586 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
587 byte v1 = this.get(i);
588 byte v2 = that.get(j);
589 if (v1 != v2) {
590 return false;
591 }
592 }
593 return true;
594 }
595
596 public int compareTo(Object o) {
597 ByteBuffer that = (ByteBuffer) o;
598 int n = this.position() + Math.min(this.remaining(), that.remaining());
599 for (int i = this.position(), j = that.position(); i < n; i++, j++) {
600 byte v1 = this.get(i);
601 byte v2 = that.get(j);
602 if (v1 == v2) {
603 continue;
604 }
605 if (v1 < v2) {
606 return -1;
607 }
608
609 return +1;
610 }
611 return this.remaining() - that.remaining();
612 }
613
614
615
616
617 public abstract ByteOrder order();
618
619
620
621
622 public abstract ByteBuffer order(ByteOrder bo);
623
624
625
626
627 public abstract char getChar();
628
629
630
631
632 public abstract ByteBuffer putChar(char value);
633
634
635
636
637 public abstract char getChar(int index);
638
639
640
641
642 public abstract ByteBuffer putChar(int index, char value);
643
644
645
646
647 public abstract CharBuffer asCharBuffer();
648
649
650
651
652 public abstract short getShort();
653
654
655
656
657 public int getUnsignedShort() {
658 return getShort() & 0xffff;
659 }
660
661
662
663
664 public abstract ByteBuffer putShort(short value);
665
666
667
668
669 public abstract short getShort(int index);
670
671
672
673
674 public int getUnsignedShort(int index) {
675 return getShort(index) & 0xffff;
676 }
677
678
679
680
681 public abstract ByteBuffer putShort(int index, short value);
682
683
684
685
686 public abstract ShortBuffer asShortBuffer();
687
688
689
690
691 public abstract int getInt();
692
693
694
695
696 public long getUnsignedInt() {
697 return getInt() & 0xffffffffL;
698 }
699
700
701
702
703 public abstract ByteBuffer putInt(int value);
704
705
706
707
708 public abstract int getInt(int index);
709
710
711
712
713 public long getUnsignedInt(int index) {
714 return getInt(index) & 0xffffffffL;
715 }
716
717
718
719
720 public abstract ByteBuffer putInt(int index, int value);
721
722
723
724
725 public abstract IntBuffer asIntBuffer();
726
727
728
729
730 public abstract long getLong();
731
732
733
734
735 public abstract ByteBuffer putLong(long value);
736
737
738
739
740 public abstract long getLong(int index);
741
742
743
744
745 public abstract ByteBuffer putLong(int index, long value);
746
747
748
749
750 public abstract LongBuffer asLongBuffer();
751
752
753
754
755 public abstract float getFloat();
756
757
758
759
760 public abstract ByteBuffer putFloat(float value);
761
762
763
764
765 public abstract float getFloat(int index);
766
767
768
769
770 public abstract ByteBuffer putFloat(int index, float value);
771
772
773
774
775 public abstract FloatBuffer asFloatBuffer();
776
777
778
779
780 public abstract double getDouble();
781
782
783
784
785 public abstract ByteBuffer putDouble(double value);
786
787
788
789
790 public abstract double getDouble(int index);
791
792
793
794
795 public abstract ByteBuffer putDouble(int index, double value);
796
797
798
799
800 public abstract DoubleBuffer asDoubleBuffer();
801
802
803
804
805
806
807 public InputStream asInputStream() {
808 return new InputStream() {
809 public int available() {
810 return ByteBuffer.this.remaining();
811 }
812
813 public synchronized void mark(int readlimit) {
814 ByteBuffer.this.mark();
815 }
816
817 public boolean markSupported() {
818 return true;
819 }
820
821 public int read() {
822 if (ByteBuffer.this.hasRemaining()) {
823 return ByteBuffer.this.get() & 0xff;
824 } else {
825 return -1;
826 }
827 }
828
829 public int read(byte[] b, int off, int len) {
830 int remaining = ByteBuffer.this.remaining();
831 if (remaining > 0) {
832 int readBytes = Math.min(remaining, len);
833 ByteBuffer.this.get(b, off, readBytes);
834 return readBytes;
835 } else {
836 return -1;
837 }
838 }
839
840 public synchronized void reset() {
841 ByteBuffer.this.reset();
842 }
843
844 public long skip(long n) {
845 int bytes;
846 if (n > Integer.MAX_VALUE) {
847 bytes = ByteBuffer.this.remaining();
848 } else {
849 bytes = Math.min(ByteBuffer.this.remaining(), (int) n);
850 }
851 ByteBuffer.this.skip(bytes);
852 return bytes;
853 }
854 };
855 }
856
857
858
859
860
861
862
863
864
865 public OutputStream asOutputStream() {
866 return new OutputStream() {
867 public void write(byte[] b, int off, int len) {
868 ByteBuffer.this.put(b, off, len);
869 }
870
871 public void write(int b) {
872 ByteBuffer.this.put((byte) b);
873 }
874 };
875 }
876
877
878
879
880 public String getHexDump() {
881 return ByteBufferHexDumper.getHexdump(this);
882 }
883
884
885
886
887
888
889
890
891
892
893 public String getString(CharsetDecoder decoder)
894 throws CharacterCodingException {
895 if (!hasRemaining()) {
896 return "";
897 }
898
899 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
900
901 int oldPos = position();
902 int oldLimit = limit();
903 int end;
904
905 if (!utf16) {
906 while (hasRemaining()) {
907 if (get() == 0) {
908 break;
909 }
910 }
911
912 end = position();
913 if (end == oldLimit && get(end - 1) != 0) {
914 limit(end);
915 } else {
916 limit(end - 1);
917 }
918 } else {
919 while (remaining() >= 2) {
920 boolean highZero = (get() == 0);
921 boolean lowZero = (get() == 0);
922 if (highZero && lowZero) {
923 break;
924 }
925 }
926
927 end = position();
928 if (end == oldLimit || end == oldLimit - 1) {
929 limit(end);
930 } else {
931 limit(end - 2);
932 }
933 }
934
935 position(oldPos);
936 if (!hasRemaining()) {
937 limit(oldLimit);
938 position(end);
939 return "";
940 }
941 decoder.reset();
942
943 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
944 CharBuffer out = CharBuffer.allocate(expectedLength);
945 for (;;) {
946 CoderResult cr;
947 if (hasRemaining()) {
948 cr = decoder.decode(buf(), out, true);
949 } else {
950 cr = decoder.flush(out);
951 }
952
953 if (cr.isUnderflow()) {
954 break;
955 }
956
957 if (cr.isOverflow()) {
958 CharBuffer o = CharBuffer.allocate(out.capacity()
959 + expectedLength);
960 out.flip();
961 o.put(out);
962 out = o;
963 continue;
964 }
965
966 if (cr.isError()) {
967
968 limit(oldLimit);
969 position(oldPos);
970 cr.throwException();
971 }
972 }
973
974 limit(oldLimit);
975 position(end);
976 return out.flip().toString();
977 }
978
979
980
981
982
983
984
985 public String getString(int fieldSize, CharsetDecoder decoder)
986 throws CharacterCodingException {
987 checkFieldSize(fieldSize);
988
989 if (fieldSize == 0) {
990 return "";
991 }
992
993 if (!hasRemaining()) {
994 return "";
995 }
996
997 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
998
999 if (utf16 && ((fieldSize & 1) != 0)) {
1000 throw new IllegalArgumentException("fieldSize is not even.");
1001 }
1002
1003 int oldPos = position();
1004 int oldLimit = limit();
1005 int end = position() + fieldSize;
1006
1007 if (oldLimit < end) {
1008 throw new BufferUnderflowException();
1009 }
1010
1011 int i;
1012
1013 if (!utf16) {
1014 for (i = 0; i < fieldSize; i++) {
1015 if (get() == 0) {
1016 break;
1017 }
1018 }
1019
1020 if (i == fieldSize) {
1021 limit(end);
1022 } else {
1023 limit(position() - 1);
1024 }
1025 } else {
1026 for (i = 0; i < fieldSize; i += 2) {
1027 boolean highZero = (get() == 0);
1028 boolean lowZero = (get() == 0);
1029 if (highZero && lowZero) {
1030 break;
1031 }
1032 }
1033
1034 if (i == fieldSize) {
1035 limit(end);
1036 } else {
1037 limit(position() - 2);
1038 }
1039 }
1040
1041 position(oldPos);
1042 if (!hasRemaining()) {
1043 limit(oldLimit);
1044 position(end);
1045 return "";
1046 }
1047 decoder.reset();
1048
1049 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1050 CharBuffer out = CharBuffer.allocate(expectedLength);
1051 for (;;) {
1052 CoderResult cr;
1053 if (hasRemaining()) {
1054 cr = decoder.decode(buf(), out, true);
1055 } else {
1056 cr = decoder.flush(out);
1057 }
1058
1059 if (cr.isUnderflow()) {
1060 break;
1061 }
1062
1063 if (cr.isOverflow()) {
1064 CharBuffer o = CharBuffer.allocate(out.capacity()
1065 + expectedLength);
1066 out.flip();
1067 o.put(out);
1068 out = o;
1069 continue;
1070 }
1071
1072 if (cr.isError()) {
1073
1074 limit(oldLimit);
1075 position(oldPos);
1076 cr.throwException();
1077 }
1078 }
1079
1080 limit(oldLimit);
1081 position(end);
1082 return out.flip().toString();
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092 public ByteBuffer putString(CharSequence val, CharsetEncoder encoder)
1093 throws CharacterCodingException {
1094 if (val.length() == 0) {
1095 return this;
1096 }
1097
1098 CharBuffer in = CharBuffer.wrap(val);
1099 encoder.reset();
1100
1101 int expandedState = 0;
1102
1103 for (;;) {
1104 CoderResult cr;
1105 if (in.hasRemaining()) {
1106 cr = encoder.encode(in, buf(), true);
1107 } else {
1108 cr = encoder.flush(buf());
1109 }
1110
1111 if (cr.isUnderflow()) {
1112 break;
1113 }
1114 if (cr.isOverflow()) {
1115 if (isAutoExpand()) {
1116 switch (expandedState) {
1117 case 0:
1118 autoExpand((int) Math.ceil(in.remaining()
1119 * encoder.averageBytesPerChar()));
1120 expandedState++;
1121 break;
1122 case 1:
1123 autoExpand((int) Math.ceil(in.remaining()
1124 * encoder.maxBytesPerChar()));
1125 expandedState++;
1126 break;
1127 default:
1128 throw new RuntimeException("Expanded by "
1129 + (int) Math.ceil(in.remaining()
1130 * encoder.maxBytesPerChar())
1131 + " but that wasn't enough for '" + val + "'");
1132 }
1133 continue;
1134 }
1135 } else {
1136 expandedState = 0;
1137 }
1138 cr.throwException();
1139 }
1140 return this;
1141 }
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 public ByteBuffer putString(CharSequence val, int fieldSize,
1158 CharsetEncoder encoder) throws CharacterCodingException {
1159 checkFieldSize(fieldSize);
1160
1161 if (fieldSize == 0)
1162 return this;
1163
1164 autoExpand(fieldSize);
1165
1166 boolean utf16 = encoder.charset().name().startsWith("UTF-16");
1167
1168 if (utf16 && ((fieldSize & 1) != 0)) {
1169 throw new IllegalArgumentException("fieldSize is not even.");
1170 }
1171
1172 int oldLimit = limit();
1173 int end = position() + fieldSize;
1174
1175 if (oldLimit < end) {
1176 throw new BufferOverflowException();
1177 }
1178
1179 if (val.length() == 0) {
1180 if (!utf16) {
1181 put((byte) 0x00);
1182 } else {
1183 put((byte) 0x00);
1184 put((byte) 0x00);
1185 }
1186 position(end);
1187 return this;
1188 }
1189
1190 CharBuffer in = CharBuffer.wrap(val);
1191 limit(end);
1192 encoder.reset();
1193
1194 for (;;) {
1195 CoderResult cr;
1196 if (in.hasRemaining()) {
1197 cr = encoder.encode(in, buf(), true);
1198 } else {
1199 cr = encoder.flush(buf());
1200 }
1201
1202 if (cr.isUnderflow() || cr.isOverflow()) {
1203 break;
1204 }
1205 cr.throwException();
1206 }
1207
1208 limit(oldLimit);
1209
1210 if (position() < end) {
1211 if (!utf16) {
1212 put((byte) 0x00);
1213 } else {
1214 put((byte) 0x00);
1215 put((byte) 0x00);
1216 }
1217 }
1218
1219 position(end);
1220 return this;
1221 }
1222
1223
1224
1225
1226
1227
1228 public String getPrefixedString(CharsetDecoder decoder)
1229 throws CharacterCodingException {
1230 return getPrefixedString(2, decoder);
1231 }
1232
1233
1234
1235
1236
1237
1238
1239 public String getPrefixedString(int prefixLength, CharsetDecoder decoder)
1240 throws CharacterCodingException {
1241 if (!prefixedDataAvailable(prefixLength)) {
1242 throw new BufferUnderflowException();
1243 }
1244
1245 int fieldSize = 0;
1246
1247 switch (prefixLength) {
1248 case 1:
1249 fieldSize = getUnsigned();
1250 break;
1251 case 2:
1252 fieldSize = getUnsignedShort();
1253 break;
1254 case 4:
1255 fieldSize = getInt();
1256 break;
1257 }
1258
1259 if (fieldSize == 0) {
1260 return "";
1261 }
1262
1263 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1264
1265 if (utf16 && ((fieldSize & 1) != 0)) {
1266 throw new BufferDataException(
1267 "fieldSize is not even for a UTF-16 string.");
1268 }
1269
1270 int oldLimit = limit();
1271 int end = position() + fieldSize;
1272
1273 if (oldLimit < end) {
1274 throw new BufferUnderflowException();
1275 }
1276
1277 limit(end);
1278 decoder.reset();
1279
1280 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1281 CharBuffer out = CharBuffer.allocate(expectedLength);
1282 for (;;) {
1283 CoderResult cr;
1284 if (hasRemaining()) {
1285 cr = decoder.decode(buf(), out, true);
1286 } else {
1287 cr = decoder.flush(out);
1288 }
1289
1290 if (cr.isUnderflow()) {
1291 break;
1292 }
1293
1294 if (cr.isOverflow()) {
1295 CharBuffer o = CharBuffer.allocate(out.capacity()
1296 + expectedLength);
1297 out.flip();
1298 o.put(out);
1299 out = o;
1300 continue;
1301 }
1302
1303 cr.throwException();
1304 }
1305
1306 limit(oldLimit);
1307 position(end);
1308 return out.flip().toString();
1309 }
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319 public ByteBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder)
1320 throws CharacterCodingException {
1321 return putPrefixedString(in, 2, 0, encoder);
1322 }
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength,
1335 CharsetEncoder encoder) throws CharacterCodingException {
1336 return putPrefixedString(in, prefixLength, 0, encoder);
1337 }
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength,
1351 int padding, CharsetEncoder encoder)
1352 throws CharacterCodingException {
1353 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
1354 }
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367 public ByteBuffer putPrefixedString(CharSequence val, int prefixLength,
1368 int padding, byte padValue, CharsetEncoder encoder)
1369 throws CharacterCodingException {
1370 int maxLength;
1371 switch (prefixLength) {
1372 case 1:
1373 maxLength = 255;
1374 break;
1375 case 2:
1376 maxLength = 65535;
1377 break;
1378 case 4:
1379 maxLength = Integer.MAX_VALUE;
1380 break;
1381 default:
1382 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1383 }
1384
1385 if (val.length() > maxLength) {
1386 throw new IllegalArgumentException(
1387 "The specified string is too long.");
1388 }
1389 if (val.length() == 0) {
1390 switch (prefixLength) {
1391 case 1:
1392 put((byte) 0);
1393 break;
1394 case 2:
1395 putShort((short) 0);
1396 break;
1397 case 4:
1398 putInt(0);
1399 break;
1400 }
1401 return this;
1402 }
1403
1404 int padMask;
1405 switch (padding) {
1406 case 0:
1407 case 1:
1408 padMask = 0;
1409 break;
1410 case 2:
1411 padMask = 1;
1412 break;
1413 case 4:
1414 padMask = 3;
1415 break;
1416 default:
1417 throw new IllegalArgumentException("padding: " + padding);
1418 }
1419
1420 CharBuffer in = CharBuffer.wrap(val);
1421 int expectedLength = (int) (in.remaining() * encoder
1422 .averageBytesPerChar()) + 1;
1423
1424 skip(prefixLength);
1425 int oldPos = position();
1426 encoder.reset();
1427
1428 for (;;) {
1429 CoderResult cr;
1430 if (in.hasRemaining()) {
1431 cr = encoder.encode(in, buf(), true);
1432 } else {
1433 cr = encoder.flush(buf());
1434 }
1435
1436 if (position() - oldPos > maxLength) {
1437 throw new IllegalArgumentException(
1438 "The specified string is too long.");
1439 }
1440
1441 if (cr.isUnderflow()) {
1442 break;
1443 }
1444 if (cr.isOverflow() && isAutoExpand()) {
1445 autoExpand(expectedLength);
1446 continue;
1447 }
1448 cr.throwException();
1449 }
1450
1451
1452 fill(padValue, padding - ((position() - oldPos) & padMask));
1453 int length = position() - oldPos;
1454 switch (prefixLength) {
1455 case 1:
1456 put(oldPos - 1, (byte) length);
1457 break;
1458 case 2:
1459 putShort(oldPos - 2, (short) length);
1460 break;
1461 case 4:
1462 putInt(oldPos - 4, length);
1463 break;
1464 }
1465 return this;
1466 }
1467
1468
1469
1470
1471
1472 public Object getObject() throws ClassNotFoundException {
1473 return getObject(Thread.currentThread().getContextClassLoader());
1474 }
1475
1476
1477
1478
1479 public Object getObject(final ClassLoader classLoader)
1480 throws ClassNotFoundException {
1481 if (!prefixedDataAvailable(4)) {
1482 throw new BufferUnderflowException();
1483 }
1484
1485 int length = getInt();
1486 if (length <= 4) {
1487 throw new BufferDataException(
1488 "Object length should be greater than 4: " + length);
1489 }
1490
1491 int oldLimit = limit();
1492 limit(position() + length);
1493 try {
1494 ObjectInputStream in = new ObjectInputStream(asInputStream()) {
1495 protected ObjectStreamClass readClassDescriptor()
1496 throws IOException, ClassNotFoundException {
1497 int type = read();
1498 if (type < 0) {
1499 throw new EOFException();
1500 }
1501 switch (type) {
1502 case 0:
1503 return super.readClassDescriptor();
1504 case 1:
1505 String className = readUTF();
1506 Class clazz =
1507 Class.forName(className, true, classLoader);
1508 return ObjectStreamClass.lookup(clazz);
1509 default:
1510 throw new StreamCorruptedException(
1511 "Unexpected class descriptor type: " + type);
1512 }
1513 }
1514
1515 protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
1516 String name = desc.getName();
1517 try {
1518 return Class.forName(name, false, classLoader);
1519 } catch (ClassNotFoundException ex) {
1520 return super.resolveClass(desc);
1521 }
1522 }
1523 };
1524 return in.readObject();
1525 } catch (IOException e) {
1526 throw new BufferDataException(e);
1527 } finally {
1528 limit(oldLimit);
1529 }
1530 }
1531
1532
1533
1534
1535 public ByteBuffer putObject(Object o) {
1536 int oldPos = position();
1537 skip(4);
1538 try {
1539 ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
1540 protected void writeClassDescriptor(ObjectStreamClass desc)
1541 throws IOException {
1542 String className = desc.getName();
1543 if (primitiveTypeNames.contains(className)) {
1544 write(0);
1545 super.writeClassDescriptor(desc);
1546 } else {
1547 write(1);
1548 writeUTF(desc.getName());
1549 }
1550 }
1551 };
1552 out.writeObject(o);
1553 out.flush();
1554 } catch (IOException e) {
1555 throw new BufferDataException(e);
1556 }
1557
1558
1559 int newPos = position();
1560 position(oldPos);
1561 putInt(newPos - oldPos - 4);
1562 position(newPos);
1563 return this;
1564 }
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581 public boolean prefixedDataAvailable(int prefixLength) {
1582 return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
1583 }
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596 public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
1597 if (remaining() < prefixLength) {
1598 return false;
1599 }
1600
1601 int dataLength;
1602 switch (prefixLength) {
1603 case 1:
1604 dataLength = getUnsigned(position());
1605 break;
1606 case 2:
1607 dataLength = getUnsignedShort(position());
1608 break;
1609 case 4:
1610 dataLength = getInt(position());
1611 break;
1612 default:
1613 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1614 }
1615
1616 if (dataLength < 0 || dataLength > maxDataLength) {
1617 throw new BufferDataException("dataLength: " + dataLength);
1618 }
1619
1620 return remaining() - prefixLength >= dataLength;
1621 }
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631 public ByteBuffer skip(int size) {
1632 autoExpand(size);
1633 return position(position() + size);
1634 }
1635
1636
1637
1638
1639
1640 public ByteBuffer fill(byte value, int size) {
1641 autoExpand(size);
1642 int q = size >>> 3;
1643 int r = size & 7;
1644
1645 if (q > 0) {
1646 int intValue = value | (value << 8) | (value << 16) | (value << 24);
1647 long longValue = intValue;
1648 longValue <<= 32;
1649 longValue |= intValue;
1650
1651 for (int i = q; i > 0; i--) {
1652 putLong(longValue);
1653 }
1654 }
1655
1656 q = r >>> 2;
1657 r = r & 3;
1658
1659 if (q > 0) {
1660 int intValue = value | (value << 8) | (value << 16) | (value << 24);
1661 putInt(intValue);
1662 }
1663
1664 q = r >> 1;
1665 r = r & 1;
1666
1667 if (q > 0) {
1668 short shortValue = (short) (value | (value << 8));
1669 putShort(shortValue);
1670 }
1671
1672 if (r > 0) {
1673 put(value);
1674 }
1675
1676 return this;
1677 }
1678
1679
1680
1681
1682
1683 public ByteBuffer fillAndReset(byte value, int size) {
1684 autoExpand(size);
1685 int pos = position();
1686 try {
1687 fill(value, size);
1688 } finally {
1689 position(pos);
1690 }
1691 return this;
1692 }
1693
1694
1695
1696
1697
1698 public ByteBuffer fill(int size) {
1699 autoExpand(size);
1700 int q = size >>> 3;
1701 int r = size & 7;
1702
1703 for (int i = q; i > 0; i--) {
1704 putLong(0L);
1705 }
1706
1707 q = r >>> 2;
1708 r = r & 3;
1709
1710 if (q > 0) {
1711 putInt(0);
1712 }
1713
1714 q = r >> 1;
1715 r = r & 1;
1716
1717 if (q > 0) {
1718 putShort((short) 0);
1719 }
1720
1721 if (r > 0) {
1722 put((byte) 0);
1723 }
1724
1725 return this;
1726 }
1727
1728
1729
1730
1731
1732 public ByteBuffer fillAndReset(int size) {
1733 autoExpand(size);
1734 int pos = position();
1735 try {
1736 fill(size);
1737 } finally {
1738 position(pos);
1739 }
1740
1741 return this;
1742 }
1743
1744
1745
1746
1747
1748 protected ByteBuffer autoExpand(int expectedRemaining) {
1749 if (isAutoExpand()) {
1750 expand(expectedRemaining);
1751 }
1752 return this;
1753 }
1754
1755
1756
1757
1758
1759 protected ByteBuffer autoExpand(int pos, int expectedRemaining) {
1760 if (isAutoExpand()) {
1761 expand(pos, expectedRemaining);
1762 }
1763 return this;
1764 }
1765
1766 private static void checkFieldSize(int fieldSize) {
1767 if (fieldSize < 0) {
1768 throw new IllegalArgumentException("fieldSize cannot be negative: "
1769 + fieldSize);
1770 }
1771 }
1772 }