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