From fe05b6e5142d51c3501af3d6c90e6c67055047c6 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Tue, 16 Sep 2014 17:02:31 +0900 Subject: [PATCH] Auto-generate the handler name when null is specified as a name Motivation: There's no way to generate the name of a handler being newly added automatically and reliably. For example, let's say you have a routine that adds a set of handlers to a pipeline using addBefore() or addAfter(). Because addBefore() and addAfter() always require non-conflicting non-null handler name, making the multiple invocation of the routine on the same pipeline is non-trivial. Modifications: - If a user specifies null as the name of the new handler, DefaultChannelPipeline generates one. - Update the documentation of ChannelPipeline to match the new behavior Result: A user doesn't need to worry about name conflicts anymore. --- .../io/netty/channel/ChannelPipeline.java | 66 +++++++++---------- .../netty/channel/DefaultChannelPipeline.java | 57 +++++++++------- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/ChannelPipeline.java b/transport/src/main/java/io/netty/channel/ChannelPipeline.java index 0cb99989d0..b1c2bdee72 100644 --- a/transport/src/main/java/io/netty/channel/ChannelPipeline.java +++ b/transport/src/main/java/io/netty/channel/ChannelPipeline.java @@ -220,13 +220,13 @@ public interface ChannelPipeline extends Iterable> /** * Inserts a {@link ChannelHandler} at the first position of this pipeline. * - * @param name the name of the handler to insert first + * @param name the name of the handler to insert first. {@code null} to let the name auto-generated. * @param handler the handler to insert first * * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified name or handler is {@code null} + * if the specified handler is {@code null} */ ChannelPipeline addFirst(String name, ChannelHandler handler); @@ -235,13 +235,13 @@ public interface ChannelPipeline extends Iterable> * * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} * methods - * @param name the name of the handler to insert first + * @param name the name of the handler to insert first. {@code null} to let the name auto-generated. * @param handler the handler to insert first * * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified name or handler is {@code null} + * if the specified handler is {@code null} */ ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler); @@ -249,26 +249,26 @@ public interface ChannelPipeline extends Iterable> * Inserts a {@link ChannelHandler} at the first position of this pipeline. * * @param invoker the {@link ChannelHandlerInvoker} which invokes the {@code handler}s event handler methods - * @param name the name of the handler to insert first + * @param name the name of the handler to insert first. {@code null} to let the name auto-generated. * @param handler the handler to insert first * * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified name or handler is {@code null} + * if the specified handler is {@code null} */ ChannelPipeline addFirst(ChannelHandlerInvoker invoker, String name, ChannelHandler handler); /** * Appends a {@link ChannelHandler} at the last position of this pipeline. * - * @param name the name of the handler to append + * @param name the name of the handler to append. {@code null} to let the name auto-generated. * @param handler the handler to append * * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified name or handler is {@code null} + * if the specified handler is {@code null} */ ChannelPipeline addLast(String name, ChannelHandler handler); @@ -277,13 +277,13 @@ public interface ChannelPipeline extends Iterable> * * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} * methods - * @param name the name of the handler to append + * @param name the name of the handler to append. {@code null} to let the name auto-generated. * @param handler the handler to append * * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified name or handler is {@code null} + * if the specified handler is {@code null} */ ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler); @@ -291,13 +291,13 @@ public interface ChannelPipeline extends Iterable> * Appends a {@link ChannelHandler} at the last position of this pipeline. * * @param invoker the {@link ChannelHandlerInvoker} which invokes the {@code handler}s event handler methods - * @param name the name of the handler to append + * @param name the name of the handler to append. {@code null} to let the name auto-generated. * @param handler the handler to append * * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified name or handler is {@code null} + * if the specified handler is {@code null} */ ChannelPipeline addLast(ChannelHandlerInvoker invoker, String name, ChannelHandler handler); @@ -306,7 +306,7 @@ public interface ChannelPipeline extends Iterable> * pipeline. * * @param baseName the name of the existing handler - * @param name the name of the handler to insert before + * @param name the name of the handler to insert before. {@code null} to let the name auto-generated. * @param handler the handler to insert before * * @throws NoSuchElementException @@ -314,7 +314,7 @@ public interface ChannelPipeline extends Iterable> * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} + * if the specified baseName or handler is {@code null} */ ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler); @@ -325,7 +325,7 @@ public interface ChannelPipeline extends Iterable> * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} * methods * @param baseName the name of the existing handler - * @param name the name of the handler to insert before + * @param name the name of the handler to insert before. {@code null} to let the name auto-generated. * @param handler the handler to insert before * * @throws NoSuchElementException @@ -333,7 +333,7 @@ public interface ChannelPipeline extends Iterable> * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} + * if the specified baseName or handler is {@code null} */ ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler); @@ -343,7 +343,7 @@ public interface ChannelPipeline extends Iterable> * * @param invoker the {@link ChannelHandlerInvoker} which invokes the {@code handler}s event handler methods * @param baseName the name of the existing handler - * @param name the name of the handler to insert before + * @param name the name of the handler to insert before. {@code null} to let the name auto-generated. * @param handler the handler to insert before * * @throws NoSuchElementException @@ -351,7 +351,7 @@ public interface ChannelPipeline extends Iterable> * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} + * if the specified baseName or handler is {@code null} */ ChannelPipeline addBefore(ChannelHandlerInvoker invoker, String baseName, String name, ChannelHandler handler); @@ -360,7 +360,7 @@ public interface ChannelPipeline extends Iterable> * pipeline. * * @param baseName the name of the existing handler - * @param name the name of the handler to insert after + * @param name the name of the handler to insert after. {@code null} to let the name auto-generated. * @param handler the handler to insert after * * @throws NoSuchElementException @@ -368,7 +368,7 @@ public interface ChannelPipeline extends Iterable> * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} + * if the specified baseName or handler is {@code null} */ ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler); @@ -379,7 +379,7 @@ public interface ChannelPipeline extends Iterable> * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler} * methods * @param baseName the name of the existing handler - * @param name the name of the handler to insert after + * @param name the name of the handler to insert after. {@code null} to let the name auto-generated. * @param handler the handler to insert after * * @throws NoSuchElementException @@ -387,7 +387,7 @@ public interface ChannelPipeline extends Iterable> * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} + * if the specified baseName or handler is {@code null} */ ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler); @@ -397,7 +397,7 @@ public interface ChannelPipeline extends Iterable> * * @param invoker the {@link ChannelHandlerInvoker} which invokes the {@code handler}s event handler methods * @param baseName the name of the existing handler - * @param name the name of the handler to insert after + * @param name the name of the handler to insert after. {@code null} to let the name auto-generated. * @param handler the handler to insert after * * @throws NoSuchElementException @@ -405,7 +405,7 @@ public interface ChannelPipeline extends Iterable> * @throws IllegalArgumentException * if there's an entry with the same name already in the pipeline * @throws NullPointerException - * if the specified baseName, name, or handler is {@code null} + * if the specified baseName or handler is {@code null} */ ChannelPipeline addAfter(ChannelHandlerInvoker invoker, String baseName, String name, ChannelHandler handler); @@ -528,7 +528,8 @@ public interface ChannelPipeline extends Iterable> * Replaces the specified {@link ChannelHandler} with a new handler in this pipeline. * * @param oldHandler the {@link ChannelHandler} to be replaced - * @param newName the name under which the replacement should be added + * @param newName the name under which the replacement should be added. + * {@code null} to use the same name with the handler being replaced. * @param newHandler the {@link ChannelHandler} which is used as replacement * * @return itself @@ -539,8 +540,7 @@ public interface ChannelPipeline extends Iterable> * if a handler with the specified new name already exists in this * pipeline, except for the handler to be replaced * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} + * if the specified old handler or new handler is {@code null} */ ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler); @@ -548,7 +548,8 @@ public interface ChannelPipeline extends Iterable> * Replaces the {@link ChannelHandler} of the specified name with a new handler in this pipeline. * * @param oldName the name of the {@link ChannelHandler} to be replaced - * @param newName the name under which the replacement should be added + * @param newName the name under which the replacement should be added. + * {@code null} to use the same name with the handler being replaced. * @param newHandler the {@link ChannelHandler} which is used as replacement * * @return the removed handler @@ -559,8 +560,7 @@ public interface ChannelPipeline extends Iterable> * if a handler with the specified new name already exists in this * pipeline, except for the handler to be replaced * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} + * if the specified old handler or new handler is {@code null} */ ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler); @@ -568,7 +568,8 @@ public interface ChannelPipeline extends Iterable> * Replaces the {@link ChannelHandler} of the specified type with a new handler in this pipeline. * * @param oldHandlerType the type of the handler to be removed - * @param newName the name under which the replacement should be added + * @param newName the name under which the replacement should be added. + * {@code null} to use the same name with the handler being replaced. * @param newHandler the {@link ChannelHandler} which is used as replacement * * @return the removed handler @@ -580,8 +581,7 @@ public interface ChannelPipeline extends Iterable> * if a handler with the specified new name already exists in this * pipeline, except for the handler to be replaced * @throws NullPointerException - * if the specified old handler, new name, or new handler is - * {@code null} + * if the specified old handler or new handler is {@code null} */ T replace(Class oldHandlerType, String newName, ChannelHandler newHandler); diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java index 5908e70075..7e6584cd54 100644 --- a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java @@ -94,16 +94,16 @@ final class DefaultChannelPipeline implements ChannelPipeline { @Override public ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler) { synchronized (this) { - checkDuplicateName(name); + name = filterName(name, handler); addFirst0(name, new DefaultChannelHandlerContext(this, findInvoker(group), name, handler)); } return this; } @Override - public ChannelPipeline addFirst(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) { + public ChannelPipeline addFirst(ChannelHandlerInvoker invoker, String name, ChannelHandler handler) { synchronized (this) { - checkDuplicateName(name); + name = filterName(name, handler); addFirst0(name, new DefaultChannelHandlerContext(this, invoker, name, handler)); } return this; @@ -131,16 +131,16 @@ final class DefaultChannelPipeline implements ChannelPipeline { @Override public ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) { synchronized (this) { - checkDuplicateName(name); + name = filterName(name, handler); addLast0(name, new DefaultChannelHandlerContext(this, findInvoker(group), name, handler)); } return this; } @Override - public ChannelPipeline addLast(ChannelHandlerInvoker invoker, final String name, ChannelHandler handler) { + public ChannelPipeline addLast(ChannelHandlerInvoker invoker, String name, ChannelHandler handler) { synchronized (this) { - checkDuplicateName(name); + name = filterName(name, handler); addLast0(name, new DefaultChannelHandlerContext(this, invoker, name, handler)); } return this; @@ -169,7 +169,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { public ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler) { synchronized (this) { AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); + name = filterName(name, handler); addBefore0(name, ctx, new DefaultChannelHandlerContext(this, findInvoker(group), name, handler)); } return this; @@ -177,10 +177,10 @@ final class DefaultChannelPipeline implements ChannelPipeline { @Override public ChannelPipeline addBefore( - ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) { + ChannelHandlerInvoker invoker, String baseName, String name, ChannelHandler handler) { synchronized (this) { AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); + name = filterName(name, handler); addBefore0(name, ctx, new DefaultChannelHandlerContext(this, invoker, name, handler)); } return this; @@ -209,7 +209,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { public ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler) { synchronized (this) { AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); + name = filterName(name, handler); addAfter0(name, ctx, new DefaultChannelHandlerContext(this, findInvoker(group), name, handler)); } return this; @@ -217,17 +217,17 @@ final class DefaultChannelPipeline implements ChannelPipeline { @Override public ChannelPipeline addAfter( - ChannelHandlerInvoker invoker, String baseName, final String name, ChannelHandler handler) { + ChannelHandlerInvoker invoker, String baseName, String name, ChannelHandler handler) { + synchronized (this) { AbstractChannelHandlerContext ctx = getContextOrDie(baseName); - checkDuplicateName(name); + name = filterName(name, handler); addAfter0(name, ctx, new DefaultChannelHandlerContext(this, invoker, name, handler)); } return this; } - private void addAfter0(final String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { - checkDuplicateName(name); + private void addAfter0(String name, AbstractChannelHandlerContext ctx, AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); newCtx.prev = ctx; @@ -287,7 +287,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { for (int i = size - 1; i >= 0; i --) { ChannelHandler h = handlers[i]; - addFirst(invoker, generateName(h), h); + addFirst(invoker, null, h); } return this; @@ -324,7 +324,7 @@ final class DefaultChannelPipeline implements ChannelPipeline { if (h == null) { break; } - addLast(invoker, generateName(h), h); + addLast(invoker, null, h); } return this; @@ -484,16 +484,16 @@ final class DefaultChannelPipeline implements ChannelPipeline { } private ChannelHandler replace( - final AbstractChannelHandlerContext ctx, final String newName, - ChannelHandler newHandler) { + final AbstractChannelHandlerContext ctx, String newName, ChannelHandler newHandler) { assert ctx != head && ctx != tail; Future future; synchronized (this) { - boolean sameName = ctx.name().equals(newName); - if (!sameName) { - checkDuplicateName(newName); + if (newName == null) { + newName = ctx.name(); + } else if (!ctx.name().equals(newName)) { + newName = filterName(newName, newHandler); } final AbstractChannelHandlerContext newCtx = @@ -503,11 +503,12 @@ final class DefaultChannelPipeline implements ChannelPipeline { replace0(ctx, newName, newCtx); return ctx.handler(); } else { + final String finalNewName = newName; future = newCtx.executor().submit(new Runnable() { @Override public void run() { synchronized (DefaultChannelPipeline.this) { - replace0(ctx, newName, newCtx); + replace0(ctx, finalNewName, newCtx); } } }); @@ -994,10 +995,16 @@ final class DefaultChannelPipeline implements ChannelPipeline { return tail.writeAndFlush(msg); } - private void checkDuplicateName(String name) { - if (name2ctx.containsKey(name)) { - throw new IllegalArgumentException("Duplicate handler name: " + name); + private String filterName(String name, ChannelHandler handler) { + if (name == null) { + return generateName(handler); } + + if (!name2ctx.containsKey(name)) { + return name; + } + + throw new IllegalArgumentException("Duplicate handler name: " + name); } private AbstractChannelHandlerContext getContextOrDie(String name) {