diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java index 6e8263f4aa..e8dce97003 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java @@ -71,6 +71,15 @@ public abstract class AbstractByteBuf extends ByteBuf { return false; } + @SuppressWarnings("deprecation") + @Override + public ByteBuf asReadOnly() { + if (isReadOnly()) { + return this; + } + return Unpooled.unmodifiableBuffer(this); + } + @Override public int maxCapacity() { return maxCapacity; diff --git a/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java b/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java index 749f0ca0d0..ea11606fbf 100644 --- a/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java @@ -868,6 +868,12 @@ final class AdvancedLeakAwareByteBuf extends WrappedByteBuf { return super.writeBytes(in, position, length); } + @Override + public ByteBuf asReadOnly() { + recordLeakNonRefCountingOperation(leak); + return new AdvancedLeakAwareByteBuf(super.asReadOnly(), leak); + } + @Override public ByteBuf retain() { leak.record(); diff --git a/buffer/src/main/java/io/netty/buffer/ByteBuf.java b/buffer/src/main/java/io/netty/buffer/ByteBuf.java index 9c1f0198b4..793d786254 100644 --- a/buffer/src/main/java/io/netty/buffer/ByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/ByteBuf.java @@ -300,6 +300,11 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable { */ public abstract boolean isReadOnly(); + /** + * Returns a read-only version of this buffer. + */ + public abstract ByteBuf asReadOnly(); + /** * Returns the {@code readerIndex} of this buffer. */ diff --git a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java index 3c3b768b80..52cfedddac 100644 --- a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java @@ -95,6 +95,11 @@ public final class EmptyByteBuf extends ByteBuf { return null; } + @Override + public ByteBuf asReadOnly() { + return Unpooled.unmodifiableBuffer(this); + } + @Override public boolean isReadOnly() { return false; diff --git a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java index 906436c4fa..710d7b9ab4 100644 --- a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java @@ -97,6 +97,11 @@ public class SwappedByteBuf extends ByteBuf { return buf.isReadOnly(); } + @Override + public ByteBuf asReadOnly() { + return Unpooled.unmodifiableBuffer(this); + } + @Override public boolean isDirect() { return buf.isDirect(); diff --git a/buffer/src/main/java/io/netty/buffer/Unpooled.java b/buffer/src/main/java/io/netty/buffer/Unpooled.java index c2b45752ca..9b6c434c94 100644 --- a/buffer/src/main/java/io/netty/buffer/Unpooled.java +++ b/buffer/src/main/java/io/netty/buffer/Unpooled.java @@ -674,7 +674,10 @@ public final class Unpooled { * on the specified {@code buffer}. The new buffer has the same * {@code readerIndex} and {@code writerIndex} with the specified * {@code buffer}. + * + * @deprecated Use {@link ByteBuf#asReadOnly()}. */ + @Deprecated public static ByteBuf unmodifiableBuffer(ByteBuf buffer) { ByteOrder endianness = buffer.order(); if (endianness == BIG_ENDIAN) { diff --git a/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java index 2b26f29137..ea686b6f49 100644 --- a/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java @@ -45,6 +45,11 @@ final class UnreleasableByteBuf extends WrappedByteBuf { return swappedBuf; } + @Override + public ByteBuf asReadOnly() { + return new UnreleasableByteBuf(buf.asReadOnly()); + } + @Override public ByteBuf readSlice(int length) { return new UnreleasableByteBuf(buf.readSlice(length)); diff --git a/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java b/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java index 7ad3a56263..954d5e6ff6 100644 --- a/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java @@ -93,6 +93,11 @@ class WrappedByteBuf extends ByteBuf { return buf; } + @Override + public ByteBuf asReadOnly() { + return buf.asReadOnly(); + } + @Override public boolean isReadOnly() { return buf.isReadOnly(); diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java index 98ea24fd76..b3cf71eb70 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java @@ -16,7 +16,6 @@ package io.netty.handler.codec.http2; import static io.netty.buffer.Unpooled.directBuffer; -import static io.netty.buffer.Unpooled.unmodifiableBuffer; import static io.netty.buffer.Unpooled.unreleasableBuffer; import static io.netty.handler.codec.http2.Http2CodecUtil.CONTINUATION_FRAME_HEADER_LENGTH; import static io.netty.handler.codec.http2.Http2CodecUtil.DATA_FRAME_HEADER_LENGTH; @@ -74,8 +73,8 @@ public class DefaultHttp2FrameWriter implements Http2FrameWriter, Http2FrameSize * When padding is needed it can be taken as a slice of this buffer. Users should call {@link ByteBuf#retain()} * before using their slice. */ - private static final ByteBuf ZERO_BUFFER = unmodifiableBuffer( - unreleasableBuffer(directBuffer(MAX_UNSIGNED_BYTE).writeZero(MAX_UNSIGNED_BYTE))); + private static final ByteBuf ZERO_BUFFER = + unreleasableBuffer(directBuffer(MAX_UNSIGNED_BYTE).writeZero(MAX_UNSIGNED_BYTE)).asReadOnly(); private final Http2HeadersEncoder headersEncoder; private int maxFrameSize; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java index 1b489dc2d4..edc13acd8e 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java @@ -27,7 +27,6 @@ import io.netty.util.AsciiString; import io.netty.util.concurrent.EventExecutor; import static io.netty.buffer.Unpooled.directBuffer; -import static io.netty.buffer.Unpooled.unmodifiableBuffer; import static io.netty.buffer.Unpooled.unreleasableBuffer; import static io.netty.util.CharsetUtil.UTF_8; import static java.lang.Math.max; @@ -54,10 +53,12 @@ public final class Http2CodecUtil { public static final short MAX_WEIGHT = 256; public static final short MIN_WEIGHT = 1; - private static final ByteBuf CONNECTION_PREFACE = unmodifiableBuffer( - unreleasableBuffer(directBuffer(24).writeBytes("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(UTF_8)))); - private static final ByteBuf EMPTY_PING = unmodifiableBuffer( - unreleasableBuffer(directBuffer(PING_FRAME_PAYLOAD_LENGTH).writeZero(PING_FRAME_PAYLOAD_LENGTH))); + private static final ByteBuf CONNECTION_PREFACE = + unreleasableBuffer(directBuffer(24).writeBytes("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(UTF_8))) + .asReadOnly(); + private static final ByteBuf EMPTY_PING = + unreleasableBuffer(directBuffer(PING_FRAME_PAYLOAD_LENGTH).writeZero(PING_FRAME_PAYLOAD_LENGTH)) + .asReadOnly(); private static final int MAX_PADDING_LENGTH_LENGTH = 1; public static final int DATA_FRAME_HEADER_LENGTH = FRAME_HEADER_LENGTH + MAX_PADDING_LENGTH_LENGTH; diff --git a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java index 2a7ef27a37..e533fcc2b9 100644 --- a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java +++ b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java @@ -93,6 +93,12 @@ final class ReplayingDecoderByteBuf extends ByteBuf { return false; } + @SuppressWarnings("deprecation") + @Override + public ByteBuf asReadOnly() { + return Unpooled.unmodifiableBuffer(this); + } + @Override public boolean isDirect() { return buffer.isDirect(); diff --git a/example/src/main/java/io/netty/example/http2/tiles/FallbackRequestHandler.java b/example/src/main/java/io/netty/example/http2/tiles/FallbackRequestHandler.java index b50962a9b3..e9836dcfcb 100644 --- a/example/src/main/java/io/netty/example/http2/tiles/FallbackRequestHandler.java +++ b/example/src/main/java/io/netty/example/http2/tiles/FallbackRequestHandler.java @@ -17,7 +17,6 @@ package io.netty.example.http2.tiles; import static io.netty.buffer.Unpooled.copiedBuffer; -import static io.netty.buffer.Unpooled.unmodifiableBuffer; import static io.netty.buffer.Unpooled.unreleasableBuffer; import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH; import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE; @@ -40,10 +39,10 @@ import io.netty.handler.codec.http2.Http2CodecUtil; */ public final class FallbackRequestHandler extends SimpleChannelInboundHandler { - private static final ByteBuf response = unmodifiableBuffer(unreleasableBuffer(copiedBuffer("" + private static final ByteBuf response = unreleasableBuffer(copiedBuffer("" + "

To view the example you need a browser that supports HTTP/2 (" + Http2CodecUtil.TLS_UPGRADE_PROTOCOL_NAME - + ")

", UTF_8))); + + ")", UTF_8)).asReadOnly(); @Override protected void channelRead0(ChannelHandlerContext ctx, HttpRequest req) throws Exception { diff --git a/example/src/main/java/io/netty/example/http2/tiles/ImageCache.java b/example/src/main/java/io/netty/example/http2/tiles/ImageCache.java index dbf3e0b2da..ad50d9f2e6 100644 --- a/example/src/main/java/io/netty/example/http2/tiles/ImageCache.java +++ b/example/src/main/java/io/netty/example/http2/tiles/ImageCache.java @@ -16,7 +16,6 @@ package io.netty.example.http2.tiles; -import static io.netty.buffer.Unpooled.unmodifiableBuffer; import static io.netty.buffer.Unpooled.unreleasableBuffer; import static io.netty.example.http2.Http2ExampleUtil.toByteBuf; import io.netty.buffer.ByteBuf; @@ -51,8 +50,8 @@ public final class ImageCache { for (int x = 0; x < 20; x++) { try { String name = name(x, y); - ByteBuf fileBytes = unreleasableBuffer(unmodifiableBuffer(toByteBuf(getClass() - .getResourceAsStream(name)))); + ByteBuf fileBytes = unreleasableBuffer(toByteBuf(getClass() + .getResourceAsStream(name)).asReadOnly()); imageBank.put(name, fileBytes); } catch (IOException e) { e.printStackTrace();