diff --git a/transport/src/main/java/io/netty/channel/StaticChannelPipeline.java b/transport/src/main/java/io/netty/channel/StaticChannelPipeline.java deleted file mode 100644 index 98d377a177..0000000000 --- a/transport/src/main/java/io/netty/channel/StaticChannelPipeline.java +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright 2011 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.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import io.netty.logging.InternalLogger; -import io.netty.logging.InternalLoggerFactory; -import io.netty.util.internal.ConversionUtil; - -/** - * A {@link ChannelPipeline} that might perform better at the cost of - * disabled dynamic insertion and removal of {@link ChannelHandler}s. - * An attempt to insert, remove, or replace a handler in this pipeline will - * trigger an {@link UnsupportedOperationException}. - */ -public class StaticChannelPipeline implements ChannelPipeline { - - // FIXME Code duplication with DefaultChannelPipeline - static final InternalLogger logger = InternalLoggerFactory.getInstance(StaticChannelPipeline.class); - - private volatile Channel channel; - private volatile ChannelSink sink; - private final StaticChannelHandlerContext[] contexts; - private final int lastIndex; - private final Map name2ctx = - new HashMap(4); - - /** - * Creates a new pipeline from the specified handlers. - * The names of the specified handlers are generated automatically; - * the first handler's name is {@code "0"}, the second handler's name is - * {@code "1"}, the third handler's name is {@code "2"}, and so on. - */ - public StaticChannelPipeline(ChannelHandler... handlers) { - if (handlers == null) { - throw new NullPointerException("handlers"); - } - if (handlers.length == 0) { - throw new IllegalArgumentException("no handlers specified"); - } - - // Get the number of first non-null handlers. - StaticChannelHandlerContext[] contexts = - new StaticChannelHandlerContext[handlers.length]; - int nContexts; - for (nContexts = 0; nContexts < contexts.length; nContexts ++) { - ChannelHandler h = handlers[nContexts]; - if (h == null) { - break; - } - } - - if (nContexts == contexts.length) { - this.contexts = contexts; - lastIndex = contexts.length - 1; - } else { - this.contexts = contexts = - new StaticChannelHandlerContext[nContexts]; - lastIndex = nContexts - 1; - } - - // Initialize the first non-null handlers only. - for (int i = 0; i < nContexts; i ++) { - ChannelHandler h = handlers[i]; - String name = ConversionUtil.toString(i); - StaticChannelHandlerContext ctx = - new StaticChannelHandlerContext(i, name, h); - contexts[i] = ctx; - name2ctx.put(name, ctx); - } - - for (ChannelHandlerContext ctx: contexts) { - callBeforeAdd(ctx); - callAfterAdd(ctx); - } - } - - @Override - public Channel getChannel() { - return channel; - } - - @Override - public ChannelSink getSink() { - ChannelSink sink = this.sink; - if (sink == null) { - return DefaultChannelPipeline.discardingSink; - } - return sink; - } - - @Override - public void attach(Channel channel, ChannelSink sink) { - if (channel == null) { - throw new NullPointerException("channel"); - } - if (sink == null) { - throw new NullPointerException("sink"); - } - if (this.channel != null || this.sink != null) { - throw new IllegalStateException("attached already"); - } - this.channel = channel; - this.sink = sink; - } - - @Override - public boolean isAttached() { - return sink != null; - } - - @Override - public void addFirst(String name, ChannelHandler handler) { - throw new UnsupportedOperationException(); - } - - @Override - public void addLast(String name, ChannelHandler handler) { - throw new UnsupportedOperationException(); - } - - @Override - public void addBefore(String baseName, String name, ChannelHandler handler) { - throw new UnsupportedOperationException(); - } - - @Override - public void addAfter(String baseName, String name, ChannelHandler handler) { - throw new UnsupportedOperationException(); - } - - @Override - public void remove(ChannelHandler handler) { - throw new UnsupportedOperationException(); - } - - @Override - public ChannelHandler remove(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public T remove(Class handlerType) { - throw new UnsupportedOperationException(); - } - - @Override - public ChannelHandler removeFirst() { - throw new UnsupportedOperationException(); - } - - @Override - public ChannelHandler removeLast() { - throw new UnsupportedOperationException(); - } - - @Override - public void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) { - throw new UnsupportedOperationException(); - } - - @Override - public ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) { - throw new UnsupportedOperationException(); - } - - @Override - public T replace( - Class oldHandlerType, String newName, ChannelHandler newHandler) { - throw new UnsupportedOperationException(); - } - - private void callBeforeAdd(ChannelHandlerContext ctx) { - if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) { - return; - } - - LifeCycleAwareChannelHandler h = - (LifeCycleAwareChannelHandler) ctx.getHandler(); - - try { - h.beforeAdd(ctx); - } catch (Throwable t) { - throw new ChannelHandlerLifeCycleException( - h.getClass().getName() + - ".beforeAdd() has thrown an exception; not adding.", t); - } - } - - private void callAfterAdd(ChannelHandlerContext ctx) { - if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) { - return; - } - - LifeCycleAwareChannelHandler h = - (LifeCycleAwareChannelHandler) ctx.getHandler(); - - try { - h.afterAdd(ctx); - } catch (Throwable t) { - boolean removed = false; - try { - callBeforeRemove(ctx); - callAfterRemove(ctx); - removed = true; - } catch (Throwable t2) { - logger.warn("Failed to remove a handler: " + ctx.getName(), t2); - } - - if (removed) { - throw new ChannelHandlerLifeCycleException( - h.getClass().getName() + - ".afterAdd() has thrown an exception; removed.", t); - } else { - throw new ChannelHandlerLifeCycleException( - h.getClass().getName() + - ".afterAdd() has thrown an exception; also failed to remove.", t); - } - } - } - - private void callBeforeRemove(ChannelHandlerContext ctx) { - if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) { - return; - } - - LifeCycleAwareChannelHandler h = - (LifeCycleAwareChannelHandler) ctx.getHandler(); - - try { - h.beforeRemove(ctx); - } catch (Throwable t) { - throw new ChannelHandlerLifeCycleException( - h.getClass().getName() + - ".beforeRemove() has thrown an exception; not removing.", t); - } - } - - private void callAfterRemove(ChannelHandlerContext ctx) { - if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) { - return; - } - - LifeCycleAwareChannelHandler h = - (LifeCycleAwareChannelHandler) ctx.getHandler(); - - try { - h.afterRemove(ctx); - } catch (Throwable t) { - throw new ChannelHandlerLifeCycleException( - h.getClass().getName() + - ".afterRemove() has thrown an exception.", t); - } - } - - @Override - public ChannelHandler getFirst() { - return contexts[0].getHandler(); - } - - @Override - public ChannelHandler getLast() { - return contexts[contexts.length - 1].getHandler(); - } - - @Override - public ChannelHandler get(String name) { - StaticChannelHandlerContext ctx = name2ctx.get(name); - if (ctx == null) { - return null; - } else { - return ctx.getHandler(); - } - } - - @Override - @SuppressWarnings("unchecked") - public T get(Class handlerType) { - ChannelHandlerContext ctx = getContext(handlerType); - if (ctx == null) { - return null; - } else { - return (T) ctx.getHandler(); - } - } - - @Override - public ChannelHandlerContext getContext(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - return name2ctx.get(name); - } - - @Override - public ChannelHandlerContext getContext(ChannelHandler handler) { - if (handler == null) { - throw new NullPointerException("handler"); - } - for (StaticChannelHandlerContext ctx: contexts) { - if (ctx.getHandler() == handler) { - return ctx; - } - } - return null; - } - - @Override - public ChannelHandlerContext getContext(Class handlerType) { - if (handlerType == null) { - throw new NullPointerException("handlerType"); - } - for (StaticChannelHandlerContext ctx: contexts) { - if (handlerType.isAssignableFrom(ctx.getHandler().getClass())) { - return ctx; - } - } - return null; - } - - @Override - public List getNames() { - List list = new ArrayList(); - for (StaticChannelHandlerContext ctx: contexts) { - list.add(ctx.getName()); - } - return list; - } - - @Override - public Map toMap() { - Map map = new LinkedHashMap(); - for (StaticChannelHandlerContext ctx: contexts) { - map.put(ctx.getName(), ctx.getHandler()); - } - return map; - } - - /** - * Returns the {@link String} representation of this pipeline. - */ - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append(getClass().getSimpleName()); - buf.append('{'); - - for (StaticChannelHandlerContext ctx: contexts) { - buf.append('('); - buf.append(ctx.getName()); - buf.append(" = "); - buf.append(ctx.getHandler().getClass().getName()); - buf.append(')'); - buf.append(", "); - } - buf.replace(buf.length() - 2, buf.length(), "}"); - return buf.toString(); - } - - @Override - public void sendUpstream(ChannelEvent e) { - StaticChannelHandlerContext head = getActualUpstreamContext(0); - if (head == null) { - logger.warn( - "The pipeline contains no upstream handlers; discarding: " + e); - return; - } - - sendUpstream(head, e); - } - - void sendUpstream(StaticChannelHandlerContext ctx, ChannelEvent e) { - try { - ((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e); - } catch (Throwable t) { - notifyHandlerException(e, t); - } - } - - @Override - public void sendDownstream(ChannelEvent e) { - StaticChannelHandlerContext tail = getActualDownstreamContext(lastIndex); - if (tail == null) { - try { - getSink().eventSunk(this, e); - return; - } catch (Throwable t) { - notifyHandlerException(e, t); - return; - } - } - - sendDownstream(tail, e); - } - - void sendDownstream(StaticChannelHandlerContext ctx, ChannelEvent e) { - if (e instanceof UpstreamMessageEvent) { - throw new IllegalArgumentException("cannot send an upstream event to downstream"); - } - - try { - ((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e); - } catch (Throwable t) { - // Unlike an upstream event, a downstream event usually has an - // incomplete future which is supposed to be updated by ChannelSink. - // However, if an exception is raised before the event reaches at - // ChannelSink, the future is not going to be updated, so we update - // here. - e.getFuture().setFailure(t); - notifyHandlerException(e, t); - } - } - - StaticChannelHandlerContext getActualUpstreamContext(int index) { - for (int i = index; i < contexts.length; i ++) { - StaticChannelHandlerContext ctx = contexts[i]; - if (ctx.canHandleUpstream()) { - return ctx; - } - } - return null; - } - - StaticChannelHandlerContext getActualDownstreamContext(int index) { - for (int i = index; i >= 0; i --) { - StaticChannelHandlerContext ctx = contexts[i]; - if (ctx.canHandleDownstream()) { - return ctx; - } - } - return null; - } - - protected void notifyHandlerException(ChannelEvent e, Throwable t) { - if (e instanceof ExceptionEvent) { - logger.warn( - "An exception was thrown by a user handler " + - "while handling an exception event (" + e + ")", t); - return; - } - - ChannelPipelineException pe; - if (t instanceof ChannelPipelineException) { - pe = (ChannelPipelineException) t; - } else { - pe = new ChannelPipelineException(t); - } - - try { - sink.exceptionCaught(this, e, pe); - } catch (Exception e1) { - logger.warn("An exception was thrown by an exception handler.", e1); - } - } - - private final class StaticChannelHandlerContext implements ChannelHandlerContext { - private final int index; - private final String name; - private final ChannelHandler handler; - private final boolean canHandleUpstream; - private final boolean canHandleDownstream; - private volatile Object attachment; - - StaticChannelHandlerContext( - int index, String name, ChannelHandler handler) { - - if (name == null) { - throw new NullPointerException("name"); - } - if (handler == null) { - throw new NullPointerException("handler"); - } - canHandleUpstream = handler instanceof ChannelUpstreamHandler; - canHandleDownstream = handler instanceof ChannelDownstreamHandler; - - - if (!canHandleUpstream && !canHandleDownstream) { - throw new IllegalArgumentException( - "handler must be either " + - ChannelUpstreamHandler.class.getName() + " or " + - ChannelDownstreamHandler.class.getName() + '.'); - } - - this.index = index; - this.name = name; - this.handler = handler; - } - - @Override - public Channel getChannel() { - return getPipeline().getChannel(); - } - - @Override - public ChannelPipeline getPipeline() { - return StaticChannelPipeline.this; - } - - @Override - public boolean canHandleDownstream() { - return canHandleDownstream; - } - - @Override - public boolean canHandleUpstream() { - return canHandleUpstream; - } - - @Override - public ChannelHandler getHandler() { - return handler; - } - - @Override - public String getName() { - return name; - } - - @Override - public Object getAttachment() { - return attachment; - } - - @Override - public void setAttachment(Object attachment) { - this.attachment = attachment; - } - - @Override - public void sendDownstream(ChannelEvent e) { - StaticChannelHandlerContext prev = getActualDownstreamContext(index - 1); - if (prev == null) { - try { - getSink().eventSunk(StaticChannelPipeline.this, e); - } catch (Throwable t) { - notifyHandlerException(e, t); - } - } else { - StaticChannelPipeline.this.sendDownstream(prev, e); - } - } - - @Override - public void sendUpstream(ChannelEvent e) { - StaticChannelHandlerContext next = getActualUpstreamContext(index + 1); - if (next != null) { - StaticChannelPipeline.this.sendUpstream(next, e); - } - } - } -} diff --git a/transport/src/test/java/io/netty/channel/StaticChannelPipelineTest.java b/transport/src/test/java/io/netty/channel/StaticChannelPipelineTest.java deleted file mode 100644 index 2fce4a6f2f..0000000000 --- a/transport/src/test/java/io/netty/channel/StaticChannelPipelineTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011 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.Map; - -import junit.framework.Assert; - -import org.junit.Test; - -public class StaticChannelPipelineTest { - - @Test - public void testConstructionWithoutNull() { - StaticChannelPipeline p = new StaticChannelPipeline(new A(), new B()); - Map m = p.toMap(); - Assert.assertEquals(2, m.size()); - Assert.assertTrue(m.get("0") instanceof A); - Assert.assertTrue(m.get("1") instanceof B); - } - - @Test - public void testConstructionWithNull1() { - StaticChannelPipeline p = new StaticChannelPipeline(null, new A(), new B()); - Map m = p.toMap(); - Assert.assertEquals(0, m.size()); - - } - - @Test - public void testConstructionWithNull2() { - StaticChannelPipeline p = new StaticChannelPipeline(new A(), null, new B()); - Map m = p.toMap(); - Assert.assertEquals(1, m.size()); - Assert.assertTrue(m.get("0") instanceof A); - - } - - @Test - public void testConstructionWithNull() { - StaticChannelPipeline p = new StaticChannelPipeline(new A(), new B(), null); - Map m = p.toMap(); - Assert.assertEquals(2, m.size()); - Assert.assertTrue(m.get("0") instanceof A); - Assert.assertTrue(m.get("1") instanceof B); - } - - static final class A extends SimpleChannelHandler { - // Dummy - } - - static final class B extends SimpleChannelHandler { - // Dummy - } -}