Deprecate CombinedChannelDuplexHandler in favor of ChannelHandlerAppender

- Fixes #2233
- Add ChannelHandlerAppender
This commit is contained in:
Trustin Lee 2014-02-13 19:20:56 -08:00
parent 7e1db4feb7
commit c671103289

View File

@ -0,0 +1,203 @@
/*
* Copyright 2012 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.channel;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link ChannelHandler} that appends the specified {@link ChannelHandler}s right next to itself.
* By default, it removes itself from the {@link ChannelPipeline} once the specified {@link ChannelHandler}s
* are added. Optionally, you can keep it in the {@link ChannelPipeline} by specifying a {@code boolean}
* parameter at construction time.
*/
public class ChannelHandlerAppender extends ChannelInboundHandlerAdapter {
private static final class Entry {
final String name;
final ChannelHandler handler;
Entry(String name, ChannelHandler handler) {
this.name = name;
this.handler = handler;
}
}
private final boolean selfRemoval;
private final List<Entry> handlers = new ArrayList<Entry>();
private boolean added;
/**
* Creates a new uninitialized instance. A class that extends this handler must invoke
* {@link #add(ChannelHandler...)} before adding this handler into a {@link ChannelPipeline}.
*/
protected ChannelHandlerAppender() {
this(true);
}
/**
* Creates a new uninitialized instance. A class that extends this handler must invoke
* {@link #add(ChannelHandler...)} before adding this handler into a {@link ChannelPipeline}.
*
* @param selfRemoval {@code true} to remove itself from the {@link ChannelPipeline} after appending
* the {@link ChannelHandler}s specified via {@link #add(ChannelHandler...)}.
*/
protected ChannelHandlerAppender(boolean selfRemoval) {
this.selfRemoval = selfRemoval;
}
/**
* Creates a new instance that appends the specified {@link ChannelHandler}s right next to itself.
*/
public ChannelHandlerAppender(Iterable<? extends ChannelHandler> handlers) {
this(true, handlers);
}
/**
* Creates a new instance that appends the specified {@link ChannelHandler}s right next to itself.
*/
public ChannelHandlerAppender(ChannelHandler... handlers) {
this(true, handlers);
}
/**
* Creates a new instance that appends the specified {@link ChannelHandler}s right next to itself.
*
* @param selfRemoval {@code true} to remove itself from the {@link ChannelPipeline} after appending
* the specified {@link ChannelHandler}s
*/
public ChannelHandlerAppender(boolean selfRemoval, Iterable<? extends ChannelHandler> handlers) {
this.selfRemoval = selfRemoval;
add(handlers);
}
/**
* Creates a new instance that appends the specified {@link ChannelHandler}s right next to itself.
*
* @param selfRemoval {@code true} to remove itself from the {@link ChannelPipeline} after appending
* the specified {@link ChannelHandler}s
*/
public ChannelHandlerAppender(boolean selfRemoval, ChannelHandler... handlers) {
this.selfRemoval = selfRemoval;
add(handlers);
}
/**
* Adds the specified handler to the list of the appended handlers.
*
* @param name the name of the appended handler. {@code null} to auto-generate
* @param handler the handler to append
*
* @throws IllegalStateException if {@link ChannelHandlerAppender} has been added to the pipeline already
*/
protected final ChannelHandlerAppender add(String name, ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
if (added) {
throw new IllegalStateException("added to the pipeline already");
}
handlers.add(new Entry(name, handler));
return this;
}
/**
* Adds the specified handler to the list of the appended handlers with the auto-generated handler name.
*
* @param handler the handler to append
*
* @throws IllegalStateException if {@link ChannelHandlerAppender} has been added to the pipeline already
*/
protected final ChannelHandlerAppender add(ChannelHandler handler) {
return add(null, handler);
}
/**
* Adds the specified handlers to the list of the appended handlers. The handlers' names are auto-generated.
*
* @throws IllegalStateException if {@link ChannelHandlerAppender} has been added to the pipeline already
*/
@SuppressWarnings("unchecked")
protected final ChannelHandlerAppender add(Iterable<? extends ChannelHandler> handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
for (ChannelHandler h: handlers) {
if (h == null) {
break;
}
add(h);
}
return this;
}
/**
* Adds the specified handlers to the list of the appended handlers. The handlers' names are auto-generated.
*
* @throws IllegalStateException if {@link ChannelHandlerAppender} has been added to the pipeline already
*/
protected final ChannelHandlerAppender add(ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
for (ChannelHandler h: handlers) {
if (h == null) {
break;
}
add(h);
}
return this;
}
/**
* Returns the {@code index}-th appended handler.
*/
@SuppressWarnings("unchecked")
protected final <T extends ChannelHandler> T handlerAt(int index) {
return (T) handlers.get(index).handler;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
added = true;
DefaultChannelPipeline pipeline = (DefaultChannelPipeline) ctx.pipeline();
String name = ctx.name();
try {
for (Entry e: handlers) {
String oldName = name;
if (e.name == null) {
name = pipeline.generateName(e.handler);
} else {
name = e.name;
}
pipeline.addAfter(ctx.executor(), oldName, name, e.handler);
}
} finally {
if (selfRemoval) {
pipeline.remove(this);
}
}
}
}