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