Skip to content

Commit 51e4a0a

Browse files
committed
MessageBuffer: exception and validation fixes with docs
1 parent 131eda0 commit 51e4a0a

File tree

1 file changed

+101
-15
lines changed

1 file changed

+101
-15
lines changed

msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java

Lines changed: 101 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.lang.reflect.Constructor;
2121
import java.lang.reflect.Field;
22+
import java.lang.reflect.InvocationTargetException;
2223
import java.nio.BufferOverflowException;
2324
import java.nio.ByteBuffer;
2425
import java.nio.ByteOrder;
@@ -182,24 +183,76 @@ public class MessageBuffer
182183
*/
183184
protected final ByteBuffer reference;
184185

185-
public static MessageBuffer allocate(int length)
186+
/**
187+
* Allocates a new MessageBuffer backed by a byte array.
188+
*
189+
* @throws IllegalArgumentException If the capacity is a negative integer
190+
*
191+
*/
192+
public static MessageBuffer allocate(int size)
186193
{
187-
return wrap(new byte[length]);
194+
if (size < 0) {
195+
throw new IllegalArgumentException("size must not be negative");
196+
}
197+
return wrap(new byte[size]);
188198
}
189199

200+
/**
201+
* Wraps a ByteBuffer into a MessageBuffer.
202+
*
203+
* The new MessageBuffer will be backed by the given byte array. Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa.
204+
*
205+
* The new buffer's size will be array.length. hasArray() will return true.
206+
*
207+
* @param array the byte array that will gack this MessageBuffer
208+
* @return
209+
*
210+
*/
190211
public static MessageBuffer wrap(byte[] array)
191212
{
192213
return newMessageBuffer(array, 0, array.length);
193214
}
194215

216+
/**
217+
* Wraps a ByteBuffer into a MessageBuffer.
218+
*
219+
* The new MessageBuffer will be backed by the given byte array. Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa.
220+
*
221+
* The new buffer's size will be length. hasArray() will return true.
222+
*
223+
* @param array the byte array that will gack this MessageBuffer
224+
* @param offset The offset of the subarray to be used; must be non-negative and no larger than array.length
225+
* @param length The length of the subarray to be used; must be non-negative and no larger than array.length - offset
226+
* @return
227+
*
228+
*/
195229
public static MessageBuffer wrap(byte[] array, int offset, int length)
196230
{
197231
return newMessageBuffer(array, offset, length);
198232
}
199233

234+
/**
235+
* Wraps a ByteBuffer into a MessageBuffer.
236+
*
237+
* The new MessageBuffer will be backed by the given byte buffer. Modifications to the new MessageBuffer will cause the byte buffer to be modified and vice versa. However, change of position, limit, or mark of given byte buffer doesn't affect MessageBuffer.
238+
*
239+
* The new buffer's size will be bb.remaining(). hasArray() will return the same result with bb.hasArray().
240+
*
241+
* @param bb the byte buffer that will gack this MessageBuffer
242+
* @throws IllegalArgumentException given byte buffer returns false both from hasArray() and isDirect()
243+
* @throws UnsupportedOperationException given byte buffer is a direct buffer and this platform doesn't support Unsafe API
244+
* @return
245+
*
246+
*/
200247
public static MessageBuffer wrap(ByteBuffer bb)
201248
{
202-
return newMessageBuffer(bb).slice(bb.position(), bb.remaining());
249+
MessageBuffer b = newMessageBuffer(bb);
250+
if (bb.position() > 0 || bb.limit() != bb.capacity()) {
251+
return b.slice(bb.position(), bb.remaining());
252+
}
253+
else {
254+
return b;
255+
}
203256
}
204257

205258
/**
@@ -214,8 +267,24 @@ private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len)
214267
try {
215268
return (MessageBuffer) mbArrConstructor.newInstance(arr, off, len);
216269
}
217-
catch (Throwable e) {
218-
throw new RuntimeException(e);
270+
catch (InstantiationException e) {
271+
// should never happen
272+
throw new IllegalStateException(e);
273+
}
274+
catch (IllegalAccessException e) {
275+
// should never happen unless security manager restricts this reflection
276+
throw new IllegalStateException(e);
277+
}
278+
catch (InvocationTargetException e) {
279+
if (e.getCause() instanceof RuntimeException) {
280+
// underlaying constructor may throw RuntimeException
281+
throw (RuntimeException) e.getCause();
282+
}
283+
else if (e.getCause() instanceof Error) {
284+
throw (Error) e.getCause();
285+
}
286+
// should never happen
287+
throw new IllegalStateException(e.getCause());
219288
}
220289
}
221290

@@ -232,18 +301,35 @@ private static MessageBuffer newMessageBuffer(ByteBuffer bb)
232301
// We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be
233302
// generated to resolve one of the method references when two or more classes overrides the method.
234303
return (MessageBuffer) mbBBConstructor.newInstance(bb);
235-
} catch (Exception e) {
236-
throw new RuntimeException(e);
304+
}
305+
catch (InstantiationException e) {
306+
// should never happen
307+
throw new IllegalStateException(e);
308+
}
309+
catch (IllegalAccessException e) {
310+
// should never happen unless security manager restricts this reflection
311+
throw new IllegalStateException(e);
312+
}
313+
catch (InvocationTargetException e) {
314+
if (e.getCause() instanceof RuntimeException) {
315+
// underlaying constructor may throw RuntimeException
316+
throw (RuntimeException) e.getCause();
317+
}
318+
else if (e.getCause() instanceof Error) {
319+
throw (Error) e.getCause();
320+
}
321+
// should never happen
322+
throw new IllegalStateException(e.getCause());
237323
}
238324
}
239325

240326
public static void releaseBuffer(MessageBuffer buffer)
241327
{
242-
if (isUniversalBuffer || buffer.base instanceof byte[]) {
328+
if (isUniversalBuffer || buffer.base != null) {
243329
// We have nothing to do. Wait until the garbage-collector collects this array object
244330
}
245-
else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) {
246-
DirectBufferAccess.clean(buffer.base);
331+
else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.reference)) {
332+
DirectBufferAccess.clean(buffer.reference);
247333
}
248334
else {
249335
// Maybe cannot reach here
@@ -260,7 +346,7 @@ else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) {
260346
*/
261347
MessageBuffer(byte[] arr, int offset, int length)
262348
{
263-
this.base = arr;
349+
this.base = arr; // non-null is already checked at newMessageBuffer
264350
this.address = ARRAY_BYTE_BASE_OFFSET + offset;
265351
this.size = length;
266352
this.reference = null;
@@ -275,7 +361,7 @@ else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) {
275361
{
276362
if (bb.isDirect()) {
277363
if (isUniversalBuffer) {
278-
throw new IllegalStateException("Cannot create MessageBuffer from DirectBuffer");
364+
throw new UnsupportedOperationException("Cannot create MessageBuffer from a DirectBuffer on this platform");
279365
}
280366
// Direct buffer or off-heap memory
281367
this.base = null;
@@ -290,7 +376,7 @@ else if (bb.hasArray()) {
290376
this.reference = null;
291377
}
292378
else {
293-
throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer are supported");
379+
throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer is supported");
294380
}
295381
}
296382

@@ -475,7 +561,7 @@ public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int le
475561
*/
476562
public ByteBuffer sliceAsByteBuffer(int index, int length)
477563
{
478-
if (hasArray()) {
564+
if (base != null) {
479565
return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length);
480566
}
481567
else {
@@ -496,7 +582,7 @@ public ByteBuffer sliceAsByteBuffer()
496582

497583
public boolean hasArray()
498584
{
499-
return base instanceof byte[];
585+
return base != null;
500586
}
501587

502588
/**

0 commit comments

Comments
 (0)