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