KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > mina > common > ByteBuffer


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  *
19  */

20 package org.apache.mina.common;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.ObjectInputStream JavaDoc;
25 import java.io.ObjectOutputStream JavaDoc;
26 import java.io.ObjectStreamClass JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.nio.BufferOverflowException JavaDoc;
29 import java.nio.BufferUnderflowException JavaDoc;
30 import java.nio.ByteOrder JavaDoc;
31 import java.nio.CharBuffer JavaDoc;
32 import java.nio.DoubleBuffer JavaDoc;
33 import java.nio.FloatBuffer JavaDoc;
34 import java.nio.IntBuffer JavaDoc;
35 import java.nio.LongBuffer JavaDoc;
36 import java.nio.ShortBuffer JavaDoc;
37 import java.nio.charset.CharacterCodingException JavaDoc;
38 import java.nio.charset.CharsetDecoder JavaDoc;
39 import java.nio.charset.CharsetEncoder JavaDoc;
40 import java.nio.charset.CoderResult JavaDoc;
41
42 import org.apache.mina.common.support.ByteBufferHexDumper;
43 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
44
45 /**
46  * A byte buffer used by MINA applications.
47  * <p>
48  * This is a replacement for {@link java.nio.ByteBuffer}. Please refer to
49  * {@link java.nio.ByteBuffer} and {@link java.nio.Buffer} documentation for
50  * usage. MINA does not use NIO {@link java.nio.ByteBuffer} directly for two
51  * reasons:
52  * <ul>
53  * <li>It doesn't provide useful getters and putters such as
54  * <code>fill</code>, <code>get/putString</code>, and
55  * <code>get/putAsciiInt()</code> enough.</li>
56  * <li>It is hard to distinguish if the buffer is created from MINA buffer
57  * pool or not. MINA have to return used buffers back to pool.</li>
58  * <li>It is difficult to write variable-length data due to its fixed
59  * capacity</li>
60  * </ul>
61  * </p>
62  *
63  * <h2>Allocation</h2>
64  * <p>
65  * You can get a heap buffer from buffer pool:
66  * <pre>
67  * ByteBuffer buf = ByteBuffer.allocate(1024, false);
68  * </pre>
69  * you can also get a direct buffer from buffer pool:
70  * <pre>
71  * ByteBuffer buf = ByteBuffer.allocate(1024, true);
72  * </pre>
73  * or you can let MINA choose:
74  * <pre>
75  * ByteBuffer buf = ByteBuffer.allocate(1024);
76  * </pre>
77  * </p>
78  *
79  * <h2>Acquire/Release</h2>
80  * <p>
81  * <b>Please note that you never need to release the allocated buffer</b>
82  * because MINA will release it automatically when:
83  * <ul>
84  * <li>You pass the buffer by calling {@link IoSession#write(Object)}.</li>
85  * <li>You pass the buffer by calling {@link IoFilter.NextFilter#filterWrite(IoSession,IoFilter.WriteRequest)}.</li>
86  * <li>You pass the buffer by calling {@link ProtocolEncoderOutput#write(ByteBuffer)}.</li>
87  * </ul>
88  * And, you don't need to release any {@link ByteBuffer} which is passed as a parameter
89  * of {@link IoHandler#messageReceived(IoSession, Object)} method. They are released
90  * automatically when the method returns.
91  * <p>
92  * You have to release buffers manually by calling {@link #release()} when:
93  * <ul>
94  * <li>You allocated a buffer, but didn't pass the buffer to any of two methods above.</li>
95  * <li>You called {@link #acquire()} to prevent the buffer from being released.</li>
96  * </ul>
97  * </p>
98  *
99  * <h2>Wrapping existing NIO buffers and arrays</h2>
100  * <p>
101  * This class provides a few <tt>wrap(...)</tt> methods that wraps
102  * any NIO buffers and byte arrays. Wrapped MINA buffers are not returned
103  * to the buffer pool by default to prevent unexpected memory leakage by default.
104  * In case you want to make it pooled, you can call {@link #setPooled(boolean)}
105  * with <tt>true</tt> flag to enable pooling.
106  *
107  * <h2>AutoExpand</h2>
108  * <p>
109  * Writing variable-length data using NIO <tt>ByteBuffers</tt> is not really
110  * easy, and it is because its size is fixed. MINA <tt>ByteBuffer</tt>
111  * introduces <tt>autoExpand</tt> property. If <tt>autoExpand</tt> property
112  * is true, you never get {@link BufferOverflowException} or
113  * {@link IndexOutOfBoundsException} (except when index is negative).
114  * It automatically expands its capacity and limit value. For example:
115  * <pre>
116  * String greeting = messageBundle.getMessage( "hello" );
117  * ByteBuffer buf = ByteBuffer.allocate( 16 );
118  * // Turn on autoExpand (it is off by default)
119  * buf.setAutoExpand( true );
120  * buf.putString( greeting, utf8encoder );
121  * </pre>
122  * NIO <tt>ByteBuffer</tt> is reallocated by MINA <tt>ByteBuffer</tt> behind
123  * the scene if the encoded data is larger than 16 bytes. Its capacity will
124  * increase by two times, and its limit will increase to the last position
125  * the string is written.
126  * </p>
127  *
128  * <h2>Derived Buffers</h2>
129  * <p>
130  * Derived buffers are the buffers which were created by
131  * {@link #duplicate()}, {@link #slice()}, or {@link #asReadOnlyBuffer()}.
132  * They are useful especially when you broadcast the same messages to
133  * multiple {@link IoSession}s. Please note that the derived buffers are
134  * neither pooled nor auto-expandable. Trying to expand a derived buffer will
135  * raise {@link IllegalStateException}.
136  * </p>
137  *
138  * <h2>Changing Buffer Allocation and Management Policy</h2>
139  * <p>
140  * MINA provides a {@link ByteBufferAllocator} interface to let you override
141  * the default buffer management behavior. There are two allocators provided
142  * out-of-the-box:
143  * <ul>
144  * <li>{@link PooledByteBufferAllocator} (Default)</li>
145  * <li>{@link SimpleByteBufferAllocator}</li>
146  * </ul>
147  * You can change the allocator by calling {@link #setAllocator(ByteBufferAllocator)}.
148  * </p>
149  *
150  * @author The Apache Directory Project (mina-dev@directory.apache.org)
151  * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13 7월 2007) $
152  * @noinspection StaticNonFinalField
153  * @see ByteBufferAllocator
154  */

155 public abstract class ByteBuffer implements Comparable JavaDoc<ByteBuffer> {
156     private static ByteBufferAllocator allocator = new PooledByteBufferAllocator();
157
158     private static boolean useDirectBuffers = true;
159
160     /**
161      * Returns the current allocator which manages the allocated buffers.
162      */

163     public static ByteBufferAllocator getAllocator() {
164         return allocator;
165     }
166
167     /**
168      * Changes the current allocator with the specified one to manage
169      * the allocated buffers from now.
170      */

171     public static void setAllocator(ByteBufferAllocator newAllocator) {
172         if (newAllocator == null) {
173             throw new NullPointerException JavaDoc("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      * Returns the direct or heap buffer which is capable of the specified
195      * size. This method tries to allocate direct buffer first, and then
196      * tries heap buffer if direct buffer memory is exhausted. Please use
197      * {@link #allocate(int, boolean)} to allocate buffers of specific type.
198      *
199      * @param capacity the capacity of the buffer
200      */

201     public static ByteBuffer allocate(int capacity) {
202         if (useDirectBuffers) {
203             try {
204                 // first try to allocate direct buffer
205
return allocate(capacity, true);
206             } catch (OutOfMemoryError JavaDoc e) {
207                 // fall through to heap buffer
208
}
209         }
210
211         return allocate(capacity, false);
212     }
213
214     /**
215      * Returns the buffer which is capable of the specified size.
216      *
217      * @param capacity the capacity of the buffer
218      * @param direct <tt>true</tt> to get a direct buffer,
219      * <tt>false</tt> to get a heap buffer.
220      */

221     public static ByteBuffer allocate(int capacity, boolean direct) {
222         return allocator.allocate(capacity, direct);
223     }
224
225     /**
226      * Wraps the specified NIO {@link java.nio.ByteBuffer} into MINA buffer.
227      */

228     public static ByteBuffer wrap(java.nio.ByteBuffer JavaDoc nioBuffer) {
229         return allocator.wrap(nioBuffer);
230     }
231
232     /**
233      * Wraps the specified byte array into MINA heap buffer.
234      */

235     public static ByteBuffer wrap(byte[] byteArray) {
236         return wrap(java.nio.ByteBuffer.wrap(byteArray));
237     }
238
239     /**
240      * Wraps the specified byte array into MINA heap buffer.
241      * Please note that MINA buffers are going to be pooled, and
242      * therefore there can be waste of memory if you wrap
243      * your byte array specifying <tt>offset</tt> and <tt>length</tt>.
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      * Increases the internal reference count of this buffer to defer
254      * automatic release. You have to invoke {@link #release()} as many
255      * as you invoked this method to release this buffer.
256      *
257      * @throws IllegalStateException if you attempt to acquire already
258      * released buffer.
259      */

260     public abstract void acquire();
261
262     /**
263      * Releases the specified buffer to buffer pool.
264      *
265      * @throws IllegalStateException if you attempt to release already
266      * released buffer.
267      */

268     public abstract void release();
269
270     /**
271      * Returns the underlying NIO buffer instance.
272      */

273     public abstract java.nio.ByteBuffer JavaDoc buf();
274
275     /**
276      * @see java.nio.ByteBuffer#isDirect()
277      */

278     public abstract boolean isDirect();
279
280     /**
281      * @see java.nio.ByteBuffer#isReadOnly()
282      */

283     public abstract boolean isReadOnly();
284
285     /**
286      * @see java.nio.ByteBuffer#capacity()
287      */

288     public abstract int capacity();
289
290     /**
291      * Changes the capacity of this buffer.
292      */

293     public abstract ByteBuffer capacity(int newCapacity);
294
295     /**
296      * Returns <tt>true</tt> if and only if <tt>autoExpand</tt> is turned on.
297      */

298     public abstract boolean isAutoExpand();
299
300     /**
301      * Turns on or off <tt>autoExpand</tt>.
302      */

303     public abstract ByteBuffer setAutoExpand(boolean autoExpand);
304
305     /**
306      * Changes the capacity and limit of this buffer so this buffer get
307      * the specified <tt>expectedRemaining</tt> room from the current position.
308      * This method works even if you didn't set <tt>autoExpand</tt> to
309      * <tt>true</tt>.
310      */

311     public ByteBuffer expand(int expectedRemaining) {
312         return expand(position(), expectedRemaining);
313     }
314
315     /**
316      * Changes the capacity and limit of this buffer so this buffer get
317      * the specified <tt>expectedRemaining</tt> room from the specified
318      * <tt>pos</tt>.
319      * This method works even if you didn't set <tt>autoExpand</tt> to
320      * <tt>true</tt>.
321      */

322     public abstract ByteBuffer expand(int pos, int expectedRemaining);
323
324     /**
325      * Returns <tt>true</tt> if and only if this buffer is returned back
326      * to the buffer pool when released.
327      * <p>
328      * The default value of this property is <tt>true</tt> if and only if you
329      * allocated this buffer using {@link #allocate(int)} or {@link #allocate(int, boolean)},
330      * or <tt>false</tt> otherwise. (i.e. {@link #wrap(byte[])}, {@link #wrap(byte[], int, int)},
331      * and {@link #wrap(java.nio.ByteBuffer)})
332      */

333     public abstract boolean isPooled();
334
335     /**
336      * Sets whether this buffer is returned back to the buffer pool when released.
337      * <p>
338      * The default value of this property is <tt>true</tt> if and only if you
339      * allocated this buffer using {@link #allocate(int)} or {@link #allocate(int, boolean)},
340      * or <tt>false</tt> otherwise. (i.e. {@link #wrap(byte[])}, {@link #wrap(byte[], int, int)},
341      * and {@link #wrap(java.nio.ByteBuffer)})
342      */

343     public abstract void setPooled(boolean pooled);
344
345     /**
346      * @see java.nio.Buffer#position()
347      */

348     public abstract int position();
349
350     /**
351      * @see java.nio.Buffer#position(int)
352      */

353     public abstract ByteBuffer position(int newPosition);
354
355     /**
356      * @see java.nio.Buffer#limit()
357      */

358     public abstract int limit();
359
360     /**
361      * @see java.nio.Buffer#limit(int)
362      */

363     public abstract ByteBuffer limit(int newLimit);
364
365     /**
366      * @see java.nio.Buffer#mark()
367      */

368     public abstract ByteBuffer mark();
369
370     /**
371      * Returns the position of the current mark. This method returns <tt>-1</tt> if no
372      * mark is set.
373      */

374     public abstract int markValue();
375
376     /**
377      * @see java.nio.Buffer#reset()
378      */

379     public abstract ByteBuffer reset();
380
381     /**
382      * @see java.nio.Buffer#clear()
383      */

384     public abstract ByteBuffer clear();
385
386     /**
387      * Clears this buffer and fills its content with <tt>NUL</tt>.
388      * The position is set to zero, the limit is set to the capacity,
389      * and the mark is discarded.
390      */

391     public ByteBuffer sweep() {
392         clear();
393         return fillAndReset(remaining());
394     }
395
396     /**
397      * Clears this buffer and fills its content with <tt>value</tt>.
398      * The position is set to zero, the limit is set to the capacity,
399      * and the mark is discarded.
400      */

401     public ByteBuffer sweep(byte value) {
402         clear();
403         return fillAndReset(value, remaining());
404     }
405
406     /**
407      * @see java.nio.Buffer#flip()
408      */

409     public abstract ByteBuffer flip();
410
411     /**
412      * @see java.nio.Buffer#rewind()
413      */

414     public abstract ByteBuffer rewind();
415
416     /**
417      * @see java.nio.Buffer#remaining()
418      */

419     public int remaining() {
420         return limit() - position();
421     }
422
423     /**
424      * @see java.nio.Buffer#hasRemaining()
425      */

426     public boolean hasRemaining() {
427         return remaining() > 0;
428     }
429
430     /**
431      * @see java.nio.ByteBuffer#duplicate()
432      */

433     public abstract ByteBuffer duplicate();
434
435     /**
436      * @see java.nio.ByteBuffer#slice()
437      */

438     public abstract ByteBuffer slice();
439
440     /**
441      * @see java.nio.ByteBuffer#asReadOnlyBuffer()
442      */

443     public abstract ByteBuffer asReadOnlyBuffer();
444
445     /**
446      * @see java.nio.ByteBuffer#array()
447      */

448     public abstract byte[] array();
449
450     /**
451      * @see java.nio.ByteBuffer#arrayOffset()
452      */

453     public abstract int arrayOffset();
454
455     /**
456      * @see java.nio.ByteBuffer#get()
457      */

458     public abstract byte get();
459
460     /**
461      * Reads one unsigned byte as a short integer.
462      */

463     public short getUnsigned() {
464         return (short) (get() & 0xff);
465     }
466
467     /**
468      * @see java.nio.ByteBuffer#put(byte)
469      */

470     public abstract ByteBuffer put(byte b);
471
472     /**
473      * @see java.nio.ByteBuffer#get(int)
474      */

475     public abstract byte get(int index);
476
477     /**
478      * Reads one byte as an unsigned short integer.
479      */

480     public short getUnsigned(int index) {
481         return (short) (get(index) & 0xff);
482     }
483
484     /**
485      * @see java.nio.ByteBuffer#put(int, byte)
486      */

487     public abstract ByteBuffer put(int index, byte b);
488
489     /**
490      * @see java.nio.ByteBuffer#get(byte[], int, int)
491      */

492     public abstract ByteBuffer get(byte[] dst, int offset, int length);
493
494     /**
495      * @see java.nio.ByteBuffer#get(byte[])
496      */

497     public ByteBuffer get(byte[] dst) {
498         return get(dst, 0, dst.length);
499     }
500
501     /**
502      * Writes the content of the specified <tt>src</tt> into this buffer.
503      */

504     public abstract ByteBuffer put(java.nio.ByteBuffer JavaDoc src);
505
506     /**
507      * Writes the content of the specified <tt>src</tt> into this buffer.
508      */

509     public ByteBuffer put(ByteBuffer src) {
510         return put(src.buf());
511     }
512
513     /**
514      * @see java.nio.ByteBuffer#put(byte[], int, int)
515      */

516     public abstract ByteBuffer put(byte[] src, int offset, int length);
517
518     /**
519      * @see java.nio.ByteBuffer#put(byte[])
520      */

521     public ByteBuffer put(byte[] src) {
522         return put(src, 0, src.length);
523     }
524
525     /**
526      * @see java.nio.ByteBuffer#compact()
527      */

528     public abstract ByteBuffer compact();
529
530     public String JavaDoc toString() {
531         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
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 JavaDoc 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      * @see java.nio.ByteBuffer#order()
598      */

599     public abstract ByteOrder JavaDoc order();
600
601     /**
602      * @see java.nio.ByteBuffer#order(ByteOrder)
603      */

604     public abstract ByteBuffer order(ByteOrder JavaDoc bo);
605
606     /**
607      * @see java.nio.ByteBuffer#getChar()
608      */

609     public abstract char getChar();
610
611     /**
612      * @see java.nio.ByteBuffer#putChar(char)
613      */

614     public abstract ByteBuffer putChar(char value);
615
616     /**
617      * @see java.nio.ByteBuffer#getChar(int)
618      */

619     public abstract char getChar(int index);
620
621     /**
622      * @see java.nio.ByteBuffer#putChar(int, char)
623      */

624     public abstract ByteBuffer putChar(int index, char value);
625
626     /**
627      * @see java.nio.ByteBuffer#asCharBuffer()
628      */

629     public abstract CharBuffer JavaDoc asCharBuffer();
630
631     /**
632      * @see java.nio.ByteBuffer#getShort()
633      */

634     public abstract short getShort();
635
636     /**
637      * Reads two bytes unsigned integer.
638      */

639     public int getUnsignedShort() {
640         return getShort() & 0xffff;
641     }
642
643     /**
644      * @see java.nio.ByteBuffer#putShort(short)
645      */

646     public abstract ByteBuffer putShort(short value);
647
648     /**
649      * @see java.nio.ByteBuffer#getShort()
650      */

651     public abstract short getShort(int index);
652
653     /**
654      * Reads two bytes unsigned integer.
655      */

656     public int getUnsignedShort(int index) {
657         return getShort(index) & 0xffff;
658     }
659
660     /**
661      * @see java.nio.ByteBuffer#putShort(int, short)
662      */

663     public abstract ByteBuffer putShort(int index, short value);
664
665     /**
666      * @see java.nio.ByteBuffer#asShortBuffer()
667      */

668     public abstract ShortBuffer JavaDoc asShortBuffer();
669
670     /**
671      * @see java.nio.ByteBuffer#getInt()
672      */

673     public abstract int getInt();
674
675     /**
676      * Reads four bytes unsigned integer.
677      */

678     public long getUnsignedInt() {
679         return getInt() & 0xffffffffL;
680     }
681
682     /**
683      * @see java.nio.ByteBuffer#putInt(int)
684      */

685     public abstract ByteBuffer putInt(int value);
686
687     /**
688      * @see java.nio.ByteBuffer#getInt(int)
689      */

690     public abstract int getInt(int index);
691
692     /**
693      * Reads four bytes unsigned integer.
694      */

695     public long getUnsignedInt(int index) {
696         return getInt(index) & 0xffffffffL;
697     }
698
699     /**
700      * @see java.nio.ByteBuffer#putInt(int, int)
701      */

702     public abstract ByteBuffer putInt(int index, int value);
703
704     /**
705      * @see java.nio.ByteBuffer#asIntBuffer()
706      */

707     public abstract IntBuffer JavaDoc asIntBuffer();
708
709     /**
710      * @see java.nio.ByteBuffer#getLong()
711      */

712     public abstract long getLong();
713
714     /**
715      * @see java.nio.ByteBuffer#putLong(int, long)
716      */

717     public abstract ByteBuffer putLong(long value);
718
719     /**
720      * @see java.nio.ByteBuffer#getLong(int)
721      */

722     public abstract long getLong(int index);
723
724     /**
725      * @see java.nio.ByteBuffer#putLong(int, long)
726      */

727     public abstract ByteBuffer putLong(int index, long value);
728
729     /**
730      * @see java.nio.ByteBuffer#asLongBuffer()
731      */

732     public abstract LongBuffer JavaDoc asLongBuffer();
733
734     /**
735      * @see java.nio.ByteBuffer#getFloat()
736      */

737     public abstract float getFloat();
738
739     /**
740      * @see java.nio.ByteBuffer#putFloat(float)
741      */

742     public abstract ByteBuffer putFloat(float value);
743
744     /**
745      * @see java.nio.ByteBuffer#getFloat(int)
746      */

747     public abstract float getFloat(int index);
748
749     /**
750      * @see java.nio.ByteBuffer#putFloat(int, float)
751      */

752     public abstract ByteBuffer putFloat(int index, float value);
753
754     /**
755      * @see java.nio.ByteBuffer#asFloatBuffer()
756      */

757     public abstract FloatBuffer JavaDoc asFloatBuffer();
758
759     /**
760      * @see java.nio.ByteBuffer#getDouble()
761      */

762     public abstract double getDouble();
763
764     /**
765      * @see java.nio.ByteBuffer#putDouble(double)
766      */

767     public abstract ByteBuffer putDouble(double value);
768
769     /**
770      * @see java.nio.ByteBuffer#getDouble(int)
771      */

772     public abstract double getDouble(int index);
773
774     /**
775      * @see java.nio.ByteBuffer#putDouble(int, double)
776      */

777     public abstract ByteBuffer putDouble(int index, double value);
778
779     /**
780      * @see java.nio.ByteBuffer#asDoubleBuffer()
781      */

782     public abstract DoubleBuffer JavaDoc asDoubleBuffer();
783
784     /**
785      * Returns an {@link InputStream} that reads the data from this buffer.
786      * {@link InputStream#read()} returns <tt>-1</tt> if the buffer position
787      * reaches to the limit.
788      */

789     public InputStream JavaDoc asInputStream() {
790         return new InputStream JavaDoc() {
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      * Returns an {@link OutputStream} that appends the data into this buffer.
841      * Please note that the {@link OutputStream#write(int)} will throw a
842      * {@link BufferOverflowException} instead of an {@link IOException}
843      * in case of buffer overflow. Please set <tt>autoExpand</tt> property by
844      * calling {@link #setAutoExpand(boolean)} to prevent the unexpected runtime
845      * exception.
846      */

847     public OutputStream JavaDoc asOutputStream() {
848         return new OutputStream JavaDoc() {
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      * Returns hexdump of this buffer.
861      */

862     public String JavaDoc getHexDump() {
863         return ByteBufferHexDumper.getHexdump(this);
864     }
865
866     ////////////////////////////////
867
// String getters and putters //
868
////////////////////////////////
869

870     /**
871      * Reads a <code>NUL</code>-terminated string from this buffer using the
872      * specified <code>decoder</code> and returns it. This method reads
873      * until the limit of this buffer if no <tt>NUL</tt> is found.
874      */

875     public String JavaDoc getString(CharsetDecoder JavaDoc decoder)
876             throws CharacterCodingException JavaDoc {
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 JavaDoc out = CharBuffer.allocate(expectedLength);
927         for (;;) {
928             CoderResult JavaDoc 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 JavaDoc 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                 // Revert the buffer back to the previous state.
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      * Reads a <code>NUL</code>-terminated string from this buffer using the
963      * specified <code>decoder</code> and returns it.
964      *
965      * @param fieldSize the maximum number of bytes to read
966      */

967     public String JavaDoc getString(int fieldSize, CharsetDecoder JavaDoc decoder)
968             throws CharacterCodingException JavaDoc {
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 JavaDoc("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 JavaDoc();
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 JavaDoc out = CharBuffer.allocate(expectedLength);
1033        for (;;) {
1034            CoderResult JavaDoc 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 JavaDoc 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                // Revert the buffer back to the previous state.
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     * Writes the content of <code>in</code> into this buffer using the
1069     * specified <code>encoder</code>. This method doesn't terminate
1070     * string with <tt>NUL</tt>. You have to do it by yourself.
1071     *
1072     * @throws BufferOverflowException if the specified string doesn't fit
1073     */

1074    public ByteBuffer putString(CharSequence JavaDoc val, CharsetEncoder JavaDoc encoder)
1075            throws CharacterCodingException JavaDoc {
1076        if (val.length() == 0) {
1077            return this;
1078        }
1079
1080        CharBuffer JavaDoc in = CharBuffer.wrap(val);
1081        encoder.reset();
1082
1083        int expandedState = 0;
1084
1085        for (;;) {
1086            CoderResult JavaDoc 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 JavaDoc("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     * Writes the content of <code>in</code> into this buffer as a
1127     * <code>NUL</code>-terminated string using the specified
1128     * <code>encoder</code>.
1129     * <p>
1130     * If the charset name of the encoder is UTF-16, you cannot specify
1131     * odd <code>fieldSize</code>, and this method will append two
1132     * <code>NUL</code>s as a terminator.
1133     * <p>
1134     * Please note that this method doesn't terminate with <code>NUL</code>
1135     * if the input string is longer than <tt>fieldSize</tt>.
1136     *
1137     * @param fieldSize the maximum number of bytes to write
1138     */

1139    public ByteBuffer putString(CharSequence JavaDoc val, int fieldSize,
1140            CharsetEncoder JavaDoc encoder) throws CharacterCodingException JavaDoc {
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 JavaDoc("fieldSize is not even.");
1152        }
1153
1154        int oldLimit = limit();
1155        int end = position() + fieldSize;
1156
1157        if (oldLimit < end) {
1158            throw new BufferOverflowException JavaDoc();
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 JavaDoc in = CharBuffer.wrap(val);
1173        limit(end);
1174        encoder.reset();
1175
1176        for (;;) {
1177            CoderResult JavaDoc 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     * Reads a string which has a 16-bit length field before the actual
1207     * encoded string, using the specified <code>decoder</code> and returns it.
1208     * This method is a shortcut for <tt>getPrefixedString(2, decoder)</tt>.
1209     */

1210    public String JavaDoc getPrefixedString(CharsetDecoder JavaDoc decoder)
1211            throws CharacterCodingException JavaDoc {
1212        return getPrefixedString(2, decoder);
1213    }
1214
1215    /**
1216     * Reads a string which has a length field before the actual
1217     * encoded string, using the specified <code>decoder</code> and returns it.
1218     *
1219     * @param prefixLength the length of the length field (1, 2, or 4)
1220     */

1221    public String JavaDoc getPrefixedString(int prefixLength, CharsetDecoder JavaDoc decoder)
1222            throws CharacterCodingException JavaDoc {
1223        if (!prefixedDataAvailable(prefixLength)) {
1224            throw new BufferUnderflowException JavaDoc();
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 JavaDoc();
1257        }
1258
1259        limit(end);
1260        decoder.reset();
1261
1262        int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1263        CharBuffer JavaDoc out = CharBuffer.allocate(expectedLength);
1264        for (;;) {
1265            CoderResult JavaDoc 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 JavaDoc 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     * Writes the content of <code>in</code> into this buffer as a
1295     * string which has a 16-bit length field before the actual
1296     * encoded string, using the specified <code>encoder</code>.
1297     * This method is a shortcut for <tt>putPrefixedString(in, 2, 0, encoder)</tt>.
1298     *
1299     * @throws BufferOverflowException if the specified string doesn't fit
1300     */

1301    public ByteBuffer putPrefixedString(CharSequence JavaDoc in, CharsetEncoder JavaDoc encoder)
1302            throws CharacterCodingException JavaDoc {
1303        return putPrefixedString(in, 2, 0, encoder);
1304    }
1305
1306    /**
1307     * Writes the content of <code>in</code> into this buffer as a
1308     * string which has a 16-bit length field before the actual
1309     * encoded string, using the specified <code>encoder</code>.
1310     * This method is a shortcut for <tt>putPrefixedString(in, prefixLength, 0, encoder)</tt>.
1311     *
1312     * @param prefixLength the length of the length field (1, 2, or 4)
1313     *
1314     * @throws BufferOverflowException if the specified string doesn't fit
1315     */

1316    public ByteBuffer putPrefixedString(CharSequence JavaDoc in, int prefixLength,
1317            CharsetEncoder JavaDoc encoder) throws CharacterCodingException JavaDoc {
1318        return putPrefixedString(in, prefixLength, 0, encoder);
1319    }
1320
1321    /**
1322     * Writes the content of <code>in</code> into this buffer as a
1323     * string which has a 16-bit length field before the actual
1324     * encoded string, using the specified <code>encoder</code>.
1325     * This method is a shortcut for <tt>putPrefixedString(in, prefixLength, padding, ( byte ) 0, encoder)</tt>.
1326     *
1327     * @param prefixLength the length of the length field (1, 2, or 4)
1328     * @param padding the number of padded <tt>NUL</tt>s (1 (or 0), 2, or 4)
1329     *
1330     * @throws BufferOverflowException if the specified string doesn't fit
1331     */

1332    public ByteBuffer putPrefixedString(CharSequence JavaDoc in, int prefixLength,
1333            int padding, CharsetEncoder JavaDoc encoder)
1334            throws CharacterCodingException JavaDoc {
1335        return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
1336    }
1337
1338    /**
1339     * Writes the content of <code>in</code> into this buffer as a
1340     * string which has a 16-bit length field before the actual
1341     * encoded string, using the specified <code>encoder</code>.
1342     *
1343     * @param prefixLength the length of the length field (1, 2, or 4)
1344     * @param padding the number of padded bytes (1 (or 0), 2, or 4)
1345     * @param padValue the value of padded bytes
1346     *
1347     * @throws BufferOverflowException if the specified string doesn't fit
1348     */

1349    public ByteBuffer putPrefixedString(CharSequence JavaDoc val, int prefixLength,
1350            int padding, byte padValue, CharsetEncoder JavaDoc encoder)
1351            throws CharacterCodingException JavaDoc {
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 JavaDoc("prefixLength: " + prefixLength);
1365        }
1366
1367        if (val.length() > maxLength) {
1368            throw new IllegalArgumentException JavaDoc(
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 JavaDoc("padding: " + padding);
1400        }
1401
1402        CharBuffer JavaDoc in = CharBuffer.wrap(val);
1403        int expectedLength = (int) (in.remaining() * encoder
1404                .averageBytesPerChar()) + 1;
1405
1406        skip(prefixLength); // make a room for the length field
1407
int oldPos = position();
1408        encoder.reset();
1409
1410        for (;;) {
1411            CoderResult JavaDoc 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 JavaDoc(
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        // Write the length field
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     * Reads a Java object from the buffer using the context {@link ClassLoader}
1452     * of the current thread.
1453     */

1454    public Object JavaDoc getObject() throws ClassNotFoundException JavaDoc {
1455        return getObject(Thread.currentThread().getContextClassLoader());
1456    }
1457
1458    /**
1459     * Reads a Java object from the buffer using the specified <tt>classLoader</tt>.
1460     */

1461    public Object JavaDoc getObject(final ClassLoader JavaDoc classLoader)
1462            throws ClassNotFoundException JavaDoc {
1463        if (!prefixedDataAvailable(4)) {
1464            throw new BufferUnderflowException JavaDoc();
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 JavaDoc in = new ObjectInputStream JavaDoc(asInputStream()) {
1477                protected ObjectStreamClass JavaDoc readClassDescriptor()
1478                        throws IOException JavaDoc, ClassNotFoundException JavaDoc {
1479                    String JavaDoc className = readUTF();
1480                    Class JavaDoc<?> clazz = Class
1481                            .forName(className, true, classLoader);
1482                    return ObjectStreamClass.lookup(clazz);
1483                }
1484            };
1485            return in.readObject();
1486        } catch (IOException JavaDoc e) {
1487            throw new BufferDataException(e);
1488        } finally {
1489            limit(oldLimit);
1490        }
1491    }
1492
1493    /**
1494     * Writes the specified Java object to the buffer.
1495     */

1496    public ByteBuffer putObject(Object JavaDoc o) {
1497        int oldPos = position();
1498        skip(4); // Make a room for the length field.
1499
try {
1500            ObjectOutputStream JavaDoc out = new ObjectOutputStream JavaDoc(asOutputStream()) {
1501                protected void writeClassDescriptor(ObjectStreamClass JavaDoc desc)
1502                        throws IOException JavaDoc {
1503                    writeUTF(desc.getName());
1504                }
1505            };
1506            out.writeObject(o);
1507            out.flush();
1508        } catch (IOException JavaDoc e) {
1509            throw new BufferDataException(e);
1510        }
1511
1512        // Fill the length field
1513
int newPos = position();
1514        position(oldPos);
1515        putInt(newPos - oldPos - 4);
1516        position(newPos);
1517        return this;
1518    }
1519
1520    /**
1521     * Returns <tt>true</tt> if this buffer contains a data which has a data
1522     * length as a prefix and the buffer has remaining data as enough as
1523     * specified in the data length field. This method is identical with
1524     * <tt>prefixedDataAvailable( prefixLength, Integer.MAX_VALUE )</tt>.
1525     * Please not that using this method can allow DoS (Denial of Service)
1526     * attack in case the remote peer sends too big data length value.
1527     * It is recommended to use {@link #prefixedDataAvailable(int, int)}
1528     * instead.
1529     *
1530     * @param prefixLength the length of the prefix field (1, 2, or 4)
1531     *
1532     * @throws IllegalArgumentException if prefixLength is wrong
1533     * @throws BufferDataException if data length is negative
1534     */

1535    public boolean prefixedDataAvailable(int prefixLength) {
1536        return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
1537    }
1538
1539    /**
1540     * Returns <tt>true</tt> if this buffer contains a data which has a data
1541     * length as a prefix and the buffer has remaining data as enough as
1542     * specified in the data length field.
1543     *
1544     * @param prefixLength the length of the prefix field (1, 2, or 4)
1545     * @param maxDataLength the allowed maximum of the read data length
1546     *
1547     * @throws IllegalArgumentException if prefixLength is wrong
1548     * @throws BufferDataException if data length is negative or greater then <tt>maxDataLength</tt>
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 JavaDoc("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
// Skip or fill methods //
1579
//////////////////////////
1580

1581    /**
1582     * Forwards the position of this buffer as the specified <code>size</code>
1583     * bytes.
1584     */

1585    public ByteBuffer skip(int size) {
1586        autoExpand(size);
1587        return position(position() + size);
1588    }
1589
1590    /**
1591     * Fills this buffer with the specified value.
1592     * This method moves buffer position forward.
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     * Fills this buffer with the specified value.
1635     * This method does not change buffer position.
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     * Fills this buffer with <code>NUL (0x00)</code>.
1650     * This method moves buffer position forward.
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     * Fills this buffer with <code>NUL (0x00)</code>.
1684     * This method does not change buffer position.
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     * This method forwards the call to {@link #expand(int)} only when
1700     * <tt>autoExpand</tt> property is <tt>true</tt>.
1701     */

1702    protected ByteBuffer autoExpand(int expectedRemaining) {
1703        if (isAutoExpand()) {
1704            expand(expectedRemaining);
1705        }
1706        return this;
1707    }
1708
1709    /**
1710     * This method forwards the call to {@link #expand(int)} only when
1711     * <tt>autoExpand</tt> property is <tt>true</tt>.
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 JavaDoc("fieldSize cannot be negative: "
1723                    + fieldSize);
1724        }
1725    }
1726}
1727
Popular Tags