Ensure CombinedChannelDuplexHandler can not be shared.

Motivation:

CombinedChannelDuplexHandler must not be shared as it contains state.

Modifications:

Enforce that it is not shared.

Result:

Fixes [#6333]
This commit is contained in:
Norman Maurer 2017-02-08 16:13:20 +01:00
parent fd2e142e74
commit 78586a99b6
6 changed files with 26 additions and 36 deletions

View File

@ -70,7 +70,7 @@ public abstract class ByteToMessageCodec<I> extends ChannelDuplexHandler {
* {@link ByteBuf}, which is backed by an byte array.
*/
protected ByteToMessageCodec(boolean preferDirect) {
CodecUtil.ensureNotSharable(this);
ensureNotSharable();
outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I");
encoder = new Encoder(preferDirect);
}
@ -84,7 +84,7 @@ public abstract class ByteToMessageCodec<I> extends ChannelDuplexHandler {
* {@link ByteBuf}, which is backed by an byte array.
*/
protected ByteToMessageCodec(Class<? extends I> outboundMessageType, boolean preferDirect) {
CodecUtil.ensureNotSharable(this);
ensureNotSharable();
outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType);
encoder = new Encoder(preferDirect);
}

View File

@ -138,7 +138,7 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
private int numReads;
protected ByteToMessageDecoder() {
CodecUtil.ensureNotSharable(this);
ensureNotSharable();
}
/**

View File

@ -1,32 +0,0 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec;
import io.netty.channel.ChannelHandlerAdapter;
final class CodecUtil {
/**
* Throws {@link IllegalStateException} if {@link ChannelHandlerAdapter#isSharable()} returns {@code true}
*/
static void ensureNotSharable(ChannelHandlerAdapter handler) {
if (handler.isSharable()) {
throw new IllegalStateException("@Sharable annotation is not allowed");
}
}
private CodecUtil() { }
}

View File

@ -28,6 +28,15 @@ public abstract class ChannelHandlerAdapter implements ChannelHandler {
// Not using volatile because it's used only for a sanity check.
boolean added;
/**
* Throws {@link IllegalStateException} if {@link ChannelHandlerAdapter#isSharable()} returns {@code true}
*/
protected void ensureNotSharable() {
if (isSharable()) {
throw new IllegalStateException("ChannelHandler " + getClass().getName() + " is not allowed to be shared");
}
}
/**
* Return {@code true} if the implementation is {@link Sharable} and so can be added
* to different {@link ChannelPipeline}s.

View File

@ -45,12 +45,15 @@ public class CombinedChannelDuplexHandler<I extends ChannelInboundHandler, O ext
* {@link #init(ChannelInboundHandler, ChannelOutboundHandler)} before adding this handler into a
* {@link ChannelPipeline}.
*/
protected CombinedChannelDuplexHandler() { }
protected CombinedChannelDuplexHandler() {
ensureNotSharable();
}
/**
* Creates a new instance that combines the specified two handlers into one.
*/
public CombinedChannelDuplexHandler(I inboundHandler, O outboundHandler) {
ensureNotSharable();
init(inboundHandler, outboundHandler);
}

View File

@ -387,4 +387,14 @@ public class CombinedChannelDuplexHandlerTest {
promise.syncUninterruptibly();
ch.finish();
}
@Test(expected = IllegalStateException.class)
public void testNotSharable() {
new CombinedChannelDuplexHandler<ChannelInboundHandler, ChannelOutboundHandler>() {
@Override
public boolean isSharable() {
return true;
}
};
}
}