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<ByteBuffer> {
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(ByteBuffer that) {
580 int n = this.position() + Math.min(this.remaining(), that.remaining());
581 for (int i = this.position(), j = that.position(); i < n; i++, j++) {
582 byte v1 = this.get(i);
583 byte v2 = that.get(j);
584 if (v1 == v2) {
585 continue;
586 }
587 if (v1 < v2) {
588 return -1;
589 }
590
591 return +1;
592 }
593 return this.remaining() - that.remaining();
594 }
595
596
597
598
599 public abstract ByteOrder order();
600
601
602
603
604 public abstract ByteBuffer order(ByteOrder bo);
605
606
607
608
609 public abstract char getChar();
610
611
612
613
614 public abstract ByteBuffer putChar(char value);
615
616
617
618
619 public abstract char getChar(int index);
620
621
622
623
624 public abstract ByteBuffer putChar(int index, char value);
625
626
627
628
629 public abstract CharBuffer asCharBuffer();
630
631
632
633
634 public abstract short getShort();
635
636
637
638
639 public int getUnsignedShort() {
640 return getShort() & 0xffff;
641 }
642
643
644
645
646 public abstract ByteBuffer putShort(short value);
647
648
649
650
651 public abstract short getShort(int index);
652
653
654
655
656 public int getUnsignedShort(int index) {
657 return getShort(index) & 0xffff;
658 }
659
660
661
662
663 public abstract ByteBuffer putShort(int index, short value);
664
665
666
667
668 public abstract ShortBuffer asShortBuffer();
669
670
671
672
673 public abstract int getInt();
674
675
676
677
678 public long getUnsignedInt() {
679 return getInt() & 0xffffffffL;
680 }
681
682
683
684
685 public abstract ByteBuffer putInt(int value);
686
687
688
689
690 public abstract int getInt(int index);
691
692
693
694
695 public long getUnsignedInt(int index) {
696 return getInt(index) & 0xffffffffL;
697 }
698
699
700
701
702 public abstract ByteBuffer putInt(int index, int value);
703
704
705
706
707 public abstract IntBuffer asIntBuffer();
708
709
710
711
712 public abstract long getLong();
713
714
715
716
717 public abstract ByteBuffer putLong(long value);
718
719
720
721
722 public abstract long getLong(int index);
723
724
725
726
727 public abstract ByteBuffer putLong(int index, long value);
728
729
730
731
732 public abstract LongBuffer asLongBuffer();
733
734
735
736
737 public abstract float getFloat();
738
739
740
741
742 public abstract ByteBuffer putFloat(float value);
743
744
745
746
747 public abstract float getFloat(int index);
748
749
750
751
752 public abstract ByteBuffer putFloat(int index, float value);
753
754
755
756
757 public abstract FloatBuffer asFloatBuffer();
758
759
760
761
762 public abstract double getDouble();
763
764
765
766
767 public abstract ByteBuffer putDouble(double value);
768
769
770
771
772 public abstract double getDouble(int index);
773
774
775
776
777 public abstract ByteBuffer putDouble(int index, double value);
778
779
780
781
782 public abstract DoubleBuffer asDoubleBuffer();
783
784
785
786
787
788
789 public InputStream asInputStream() {
790 return new InputStream() {
791 public int available() {
792 return ByteBuffer.this.remaining();
793 }
794
795 public synchronized void mark(int readlimit) {
796 ByteBuffer.this.mark();
797 }
798
799 public boolean markSupported() {
800 return true;
801 }
802
803 public int read() {
804 if (ByteBuffer.this.hasRemaining()) {
805 return ByteBuffer.this.get() & 0xff;
806 } else {
807 return -1;
808 }
809 }
810
811 public int read(byte[] b, int off, int len) {
812 int remaining = ByteBuffer.this.remaining();
813 if (remaining > 0) {
814 int readBytes = Math.min(remaining, len);
815 ByteBuffer.this.get(b, off, readBytes);
816 return readBytes;
817 } else {
818 return -1;
819 }
820 }
821
822 public synchronized void reset() {
823 ByteBuffer.this.reset();
824 }
825
826 public long skip(long n) {
827 int bytes;
828 if (n > Integer.MAX_VALUE) {
829 bytes = ByteBuffer.this.remaining();
830 } else {
831 bytes = Math.min(ByteBuffer.this.remaining(), (int) n);
832 }
833 ByteBuffer.this.skip(bytes);
834 return bytes;
835 }
836 };
837 }
838
839
840
841
842
843
844
845
846
847 public OutputStream asOutputStream() {
848 return new OutputStream() {
849 public void write(byte[] b, int off, int len) {
850 ByteBuffer.this.put(b, off, len);
851 }
852
853 public void write(int b) {
854 ByteBuffer.this.put((byte) b);
855 }
856 };
857 }
858
859
860
861
862 public String getHexDump() {
863 return ByteBufferHexDumper.getHexdump(this);
864 }
865
866
867
868
869
870
871
872
873
874
875 public String getString(CharsetDecoder decoder)
876 throws CharacterCodingException {
877 if (!hasRemaining()) {
878 return "";
879 }
880
881 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
882
883 int oldPos = position();
884 int oldLimit = limit();
885 int end;
886
887 if (!utf16) {
888 while (hasRemaining()) {
889 if (get() == 0) {
890 break;
891 }
892 }
893
894 end = position();
895 if (end == oldLimit && get(end - 1) != 0) {
896 limit(end);
897 } else {
898 limit(end - 1);
899 }
900 } else {
901 while (remaining() >= 2) {
902 boolean highZero = (get() == 0);
903 boolean lowZero = (get() == 0);
904 if (highZero && lowZero) {
905 break;
906 }
907 }
908
909 end = position();
910 if (end == oldLimit || end == oldLimit - 1) {
911 limit(end);
912 } else {
913 limit(end - 2);
914 }
915 }
916
917 position(oldPos);
918 if (!hasRemaining()) {
919 limit(oldLimit);
920 position(end);
921 return "";
922 }
923 decoder.reset();
924
925 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
926 CharBuffer out = CharBuffer.allocate(expectedLength);
927 for (;;) {
928 CoderResult cr;
929 if (hasRemaining()) {
930 cr = decoder.decode(buf(), out, true);
931 } else {
932 cr = decoder.flush(out);
933 }
934
935 if (cr.isUnderflow()) {
936 break;
937 }
938
939 if (cr.isOverflow()) {
940 CharBuffer o = CharBuffer.allocate(out.capacity()
941 + expectedLength);
942 out.flip();
943 o.put(out);
944 out = o;
945 continue;
946 }
947
948 if (cr.isError()) {
949
950 limit(oldLimit);
951 position(oldPos);
952 cr.throwException();
953 }
954 }
955
956 limit(oldLimit);
957 position(end);
958 return out.flip().toString();
959 }
960
961
962
963
964
965
966
967 public String getString(int fieldSize, CharsetDecoder decoder)
968 throws CharacterCodingException {
969 checkFieldSize(fieldSize);
970
971 if (fieldSize == 0) {
972 return "";
973 }
974
975 if (!hasRemaining()) {
976 return "";
977 }
978
979 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
980
981 if (utf16 && ((fieldSize & 1) != 0)) {
982 throw new IllegalArgumentException("fieldSize is not even.");
983 }
984
985 int oldPos = position();
986 int oldLimit = limit();
987 int end = position() + fieldSize;
988
989 if (oldLimit < end) {
990 throw new BufferUnderflowException();
991 }
992
993 int i;
994
995 if (!utf16) {
996 for (i = 0; i < fieldSize; i++) {
997 if (get() == 0) {
998 break;
999 }
1000 }
1001
1002 if (i == fieldSize) {
1003 limit(end);
1004 } else {
1005 limit(position() - 1);
1006 }
1007 } else {
1008 for (i = 0; i < fieldSize; i += 2) {
1009 boolean highZero = (get() == 0);
1010 boolean lowZero = (get() == 0);
1011 if (highZero && lowZero) {
1012 break;
1013 }
1014 }
1015
1016 if (i == fieldSize) {
1017 limit(end);
1018 } else {
1019 limit(position() - 2);
1020 }
1021 }
1022
1023 position(oldPos);
1024 if (!hasRemaining()) {
1025 limit(oldLimit);
1026 position(end);
1027 return "";
1028 }
1029 decoder.reset();
1030
1031 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1032 CharBuffer out = CharBuffer.allocate(expectedLength);
1033 for (;;) {
1034 CoderResult cr;
1035 if (hasRemaining()) {
1036 cr = decoder.decode(buf(), out, true);
1037 } else {
1038 cr = decoder.flush(out);
1039 }
1040
1041 if (cr.isUnderflow()) {
1042 break;
1043 }
1044
1045 if (cr.isOverflow()) {
1046 CharBuffer o = CharBuffer.allocate(out.capacity()
1047 + expectedLength);
1048 out.flip();
1049 o.put(out);
1050 out = o;
1051 continue;
1052 }
1053
1054 if (cr.isError()) {
1055
1056 limit(oldLimit);
1057 position(oldPos);
1058 cr.throwException();
1059 }
1060 }
1061
1062 limit(oldLimit);
1063 position(end);
1064 return out.flip().toString();
1065 }
1066
1067
1068
1069
1070
1071
1072
1073
1074 public ByteBuffer putString(CharSequence val, CharsetEncoder encoder)
1075 throws CharacterCodingException {
1076 if (val.length() == 0) {
1077 return this;
1078 }
1079
1080 CharBuffer in = CharBuffer.wrap(val);
1081 encoder.reset();
1082
1083 int expandedState = 0;
1084
1085 for (;;) {
1086 CoderResult cr;
1087 if (in.hasRemaining()) {
1088 cr = encoder.encode(in, buf(), true);
1089 } else {
1090 cr = encoder.flush(buf());
1091 }
1092
1093 if (cr.isUnderflow()) {
1094 break;
1095 }
1096 if (cr.isOverflow()) {
1097 if (isAutoExpand()) {
1098 switch (expandedState) {
1099 case 0:
1100 autoExpand((int) Math.ceil(in.remaining()
1101 * encoder.averageBytesPerChar()));
1102 expandedState++;
1103 break;
1104 case 1:
1105 autoExpand((int) Math.ceil(in.remaining()
1106 * encoder.maxBytesPerChar()));
1107 expandedState++;
1108 break;
1109 default:
1110 throw new RuntimeException("Expanded by "
1111 + (int) Math.ceil(in.remaining()
1112 * encoder.maxBytesPerChar())
1113 + " but that wasn't enough for '" + val + "'");
1114 }
1115 continue;
1116 }
1117 } else {
1118 expandedState = 0;
1119 }
1120 cr.throwException();
1121 }
1122 return this;
1123 }
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139 public ByteBuffer putString(CharSequence val, int fieldSize,
1140 CharsetEncoder encoder) throws CharacterCodingException {
1141 checkFieldSize(fieldSize);
1142
1143 if (fieldSize == 0)
1144 return this;
1145
1146 autoExpand(fieldSize);
1147
1148 boolean utf16 = encoder.charset().name().startsWith("UTF-16");
1149
1150 if (utf16 && ((fieldSize & 1) != 0)) {
1151 throw new IllegalArgumentException("fieldSize is not even.");
1152 }
1153
1154 int oldLimit = limit();
1155 int end = position() + fieldSize;
1156
1157 if (oldLimit < end) {
1158 throw new BufferOverflowException();
1159 }
1160
1161 if (val.length() == 0) {
1162 if (!utf16) {
1163 put((byte) 0x00);
1164 } else {
1165 put((byte) 0x00);
1166 put((byte) 0x00);
1167 }
1168 position(end);
1169 return this;
1170 }
1171
1172 CharBuffer in = CharBuffer.wrap(val);
1173 limit(end);
1174 encoder.reset();
1175
1176 for (;;) {
1177 CoderResult cr;
1178 if (in.hasRemaining()) {
1179 cr = encoder.encode(in, buf(), true);
1180 } else {
1181 cr = encoder.flush(buf());
1182 }
1183
1184 if (cr.isUnderflow() || cr.isOverflow()) {
1185 break;
1186 }
1187 cr.throwException();
1188 }
1189
1190 limit(oldLimit);
1191
1192 if (position() < end) {
1193 if (!utf16) {
1194 put((byte) 0x00);
1195 } else {
1196 put((byte) 0x00);
1197 put((byte) 0x00);
1198 }
1199 }
1200
1201 position(end);
1202 return this;
1203 }
1204
1205
1206
1207
1208
1209
1210 public String getPrefixedString(CharsetDecoder decoder)
1211 throws CharacterCodingException {
1212 return getPrefixedString(2, decoder);
1213 }
1214
1215
1216
1217
1218
1219
1220
1221 public String getPrefixedString(int prefixLength, CharsetDecoder decoder)
1222 throws CharacterCodingException {
1223 if (!prefixedDataAvailable(prefixLength)) {
1224 throw new BufferUnderflowException();
1225 }
1226
1227 int fieldSize = 0;
1228
1229 switch (prefixLength) {
1230 case 1:
1231 fieldSize = getUnsigned();
1232 break;
1233 case 2:
1234 fieldSize = getUnsignedShort();
1235 break;
1236 case 4:
1237 fieldSize = getInt();
1238 break;
1239 }
1240
1241 if (fieldSize == 0) {
1242 return "";
1243 }
1244
1245 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1246
1247 if (utf16 && ((fieldSize & 1) != 0)) {
1248 throw new BufferDataException(
1249 "fieldSize is not even for a UTF-16 string.");
1250 }
1251
1252 int oldLimit = limit();
1253 int end = position() + fieldSize;
1254
1255 if (oldLimit < end) {
1256 throw new BufferUnderflowException();
1257 }
1258
1259 limit(end);
1260 decoder.reset();
1261
1262 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1263 CharBuffer out = CharBuffer.allocate(expectedLength);
1264 for (;;) {
1265 CoderResult cr;
1266 if (hasRemaining()) {
1267 cr = decoder.decode(buf(), out, true);
1268 } else {
1269 cr = decoder.flush(out);
1270 }
1271
1272 if (cr.isUnderflow()) {
1273 break;
1274 }
1275
1276 if (cr.isOverflow()) {
1277 CharBuffer o = CharBuffer.allocate(out.capacity()
1278 + expectedLength);
1279 out.flip();
1280 o.put(out);
1281 out = o;
1282 continue;
1283 }
1284
1285 cr.throwException();
1286 }
1287
1288 limit(oldLimit);
1289 position(end);
1290 return out.flip().toString();
1291 }
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 public ByteBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder)
1302 throws CharacterCodingException {
1303 return putPrefixedString(in, 2, 0, encoder);
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength,
1317 CharsetEncoder encoder) throws CharacterCodingException {
1318 return putPrefixedString(in, prefixLength, 0, encoder);
1319 }
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332 public ByteBuffer putPrefixedString(CharSequence in, int prefixLength,
1333 int padding, CharsetEncoder encoder)
1334 throws CharacterCodingException {
1335 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
1336 }
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349 public ByteBuffer putPrefixedString(CharSequence val, int prefixLength,
1350 int padding, byte padValue, CharsetEncoder encoder)
1351 throws CharacterCodingException {
1352 int maxLength;
1353 switch (prefixLength) {
1354 case 1:
1355 maxLength = 255;
1356 break;
1357 case 2:
1358 maxLength = 65535;
1359 break;
1360 case 4:
1361 maxLength = Integer.MAX_VALUE;
1362 break;
1363 default:
1364 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1365 }
1366
1367 if (val.length() > maxLength) {
1368 throw new IllegalArgumentException(
1369 "The specified string is too long.");
1370 }
1371 if (val.length() == 0) {
1372 switch (prefixLength) {
1373 case 1:
1374 put((byte) 0);
1375 break;
1376 case 2:
1377 putShort((short) 0);
1378 break;
1379 case 4:
1380 putInt(0);
1381 break;
1382 }
1383 return this;
1384 }
1385
1386 int padMask;
1387 switch (padding) {
1388 case 0:
1389 case 1:
1390 padMask = 0;
1391 break;
1392 case 2:
1393 padMask = 1;
1394 break;
1395 case 4:
1396 padMask = 3;
1397 break;
1398 default:
1399 throw new IllegalArgumentException("padding: " + padding);
1400 }
1401
1402 CharBuffer in = CharBuffer.wrap(val);
1403 int expectedLength = (int) (in.remaining() * encoder
1404 .averageBytesPerChar()) + 1;
1405
1406 skip(prefixLength);
1407 int oldPos = position();
1408 encoder.reset();
1409
1410 for (;;) {
1411 CoderResult cr;
1412 if (in.hasRemaining()) {
1413 cr = encoder.encode(in, buf(), true);
1414 } else {
1415 cr = encoder.flush(buf());
1416 }
1417
1418 if (position() - oldPos > maxLength) {
1419 throw new IllegalArgumentException(
1420 "The specified string is too long.");
1421 }
1422
1423 if (cr.isUnderflow()) {
1424 break;
1425 }
1426 if (cr.isOverflow() && isAutoExpand()) {
1427 autoExpand(expectedLength);
1428 continue;
1429 }
1430 cr.throwException();
1431 }
1432
1433
1434 fill(padValue, padding - ((position() - oldPos) & padMask));
1435 int length = position() - oldPos;
1436 switch (prefixLength) {
1437 case 1:
1438 put(oldPos - 1, (byte) length);
1439 break;
1440 case 2:
1441 putShort(oldPos - 2, (short) length);
1442 break;
1443 case 4:
1444 putInt(oldPos - 4, length);
1445 break;
1446 }
1447 return this;
1448 }
1449
1450
1451
1452
1453
1454 public Object getObject() throws ClassNotFoundException {
1455 return getObject(Thread.currentThread().getContextClassLoader());
1456 }
1457
1458
1459
1460
1461 public Object getObject(final ClassLoader classLoader)
1462 throws ClassNotFoundException {
1463 if (!prefixedDataAvailable(4)) {
1464 throw new BufferUnderflowException();
1465 }
1466
1467 int length = getInt();
1468 if (length <= 4) {
1469 throw new BufferDataException(
1470 "Object length should be greater than 4: " + length);
1471 }
1472
1473 int oldLimit = limit();
1474 limit(position() + length);
1475 try {
1476 ObjectInputStream in = new ObjectInputStream(asInputStream()) {
1477 protected ObjectStreamClass readClassDescriptor()
1478 throws IOException, ClassNotFoundException {
1479 String className = readUTF();
1480 Class<?> clazz = Class
1481 .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 }