/* * JBoss, Home of Professional Open Source * * Copyright 2008, Red Hat Middleware LLC, and individual contributors * by the @author tags. See the COPYRIGHT.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.netty.channel; import java.util.Map; import java.util.NoSuchElementException; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.handler.execution.ExecutionHandler; import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor; import org.jboss.netty.handler.ssl.SslHandler; /** * A list of {@link ChannelHandler}s which handles or intercepts * {@link ChannelEvent}s of a {@link Channel}. {@link ChannelPipeline} * implements an advanced form of the * Intercepting * Filter pattern to give a user full control over how an event is handled * and how the {@link ChannelHandler}s in the pipeline interact with each other. * *
* It is recommended to create a new pipeline using the helper methods in * {@link Channels} rather than calling an individual implementation's * constructor: *
* import static org.jboss.netty.channel.Channels.*; * ChannelPipeline pipeline = pipeline(); // same with Channels.pipeline() ** *
* The following diagram describes how {@link ChannelEvent}s are processed by * {@link ChannelHandler}s in a {@link ChannelPipeline} typically. * A {@link ChannelEvent} can be handled by either a {@link ChannelUpstreamHandler} * or a {@link ChannelDownstreamHandler} and be forwarded to the next or * previous handler by calling {@link ChannelHandlerContext#sendUpstream(ChannelEvent)} * or {@link ChannelHandlerContext#sendDownstream(ChannelEvent)}. The meaning * of the event is interpreted somewhat differently depending on whether it is * going upstream or going downstream. Please refer to {@link ChannelEvent} for * more information. * *
* * I/O Request * via {@link Channel} or * {@link ChannelHandlerContext} * | * +---------------------------------------------+--------------------+ * | ChannelPipeline | | * | \|/ | * | +----------------------+ +-----------+------------+ | * | LAST | Upstream Handler N | | Downstream Handler M | LAST | * | . +----------+-----------+ +-----------+------------+ . | * | . /|\ | . | * | . | \|/ . | * | . +----------+-----------+ +-----------+------------+ . | * | . | Upstream Handler N-1 | | Downstream Handler M-1 | . | * | . +----------+-----------+ +-----------+------------+ . | * | . /|\ . . | * | . . . . | * | . [ Going UPSTREAM ] [ Going DOWNSTREAM ] . | * | . . . . | * | . . \|/ . | * | . +----------+-----------+ +-----------+------------+ . | * | . | Upstream Handler 2 | | Downstream Handler 2 | . | * | . +----------+-----------+ +-----------+------------+ . | * | . /|\ | . | * | . | \|/ . | * | . +----------+-----------+ +-----------+------------+ . | * | FIRST | Upstream Handler 1 | | Downstream Handler 1 | FIRST | * | +----------+-----------+ +-----------+------------+ | * | /|\ | | * +------------------+--------------------------+--------------------+ * | \|/ * +------------------+--------------------------+--------------------+ * | I/O Threads (Transport Implementation) | * +------------------------------------------------------------------+ ** Please note that an upstream event flows from the first upstream handler * to the last upstream handler (i.e. to the next) and a downstream event * flows from the last downstream handler to the first downstream handler * (i.e. to the previous). *
* For example, let us assume that we created the following pipeline: *
* ChannelPipeline p = Channels.pipeline(); * p.addLast("1", new UpstreamHandlerA()); * p.addLast("2", new UpstreamHandlerB()); * p.addLast("3", new DownstreamHandlerA()); * p.addLast("4", new DownstreamHandlerB()); * p.addLast("5", new UpstreamHandlerX()); ** The class whose name starts with {@code Upstream} means it is an upstream * handler. The class whose name starts with {@code Downstream} means it is a * downstream handler. *
* In the given example configuration, the handler evaluation order is 1, 2, 3, * 4, 5 when an event goes upstream. When an event goes downstream, the order * is 5, 4, 3, 2, 1. On top of this principle, {@link ChannelPipeline} skips * the evaluation of certain handlers to shorten the stack depth: *
* A user is supposed to have one or more {@link ChannelHandler}s in a * pipeline to receive I/O events (e.g. read) and to request I/O operations * (e.g. write and close). For example, a typical server will have the following * handlers in each channel's pipeline, but your mileage may vary depending on * the complexity and characteristics of the protocol and business logic: * *
* ChannelPipeline pipeline = {@link Channels#pipeline() Channels.pipeline()}; * pipeline.addLast("decoder", new MyProtocolDecoder()); * pipeline.addLast("encoder", new MyProtocolEncoder()); * pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576))); * pipeline.addLast("handler", new MyBusinessLogicHandler()); ** *
* A {@link ChannelHandler} can be added or removed at any time because a
* {@link ChannelPipeline} is thread safe. For example, you can insert a
* {@link SslHandler} when sensitive information is about to be exchanged,
* and remove it after the exchange.
*
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)
*
* @version $Rev$, $Date$
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.ChannelHandlerContext
* @apiviz.owns org.jboss.netty.channel.ChannelHandler
* @apiviz.uses org.jboss.netty.channel.ChannelSink - - sends events downstream
*/
public interface ChannelPipeline {
/**
* Inserts a {@link ChannelHandler} at the first position of this pipeline.
*
* @param name the name of the handler to insert first
* @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}
*/
void addFirst (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 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}
*/
void addLast (String name, ChannelHandler handler);
/**
* Inserts a {@link ChannelHandler} before an existing handler of this
* pipeline.
*
* @param baseName the name of the existing handler
* @param name the name of the handler to insert before
* @param handler the handler to insert before
*
* @throws NoSuchElementException
* if there's no such entry with the specified {@code baseName}
* @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}
*/
void addBefore(String baseName, String name, ChannelHandler handler);
/**
* Inserts a {@link ChannelHandler} after an existing handler of this
* pipeline.
*
* @param baseName the name of the existing handler
* @param name the name of the handler to insert after
* @param handler the handler to insert after
*
* @throws NoSuchElementException
* if there's no such entry with the specified {@code baseName}
* @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}
*/
void addAfter (String baseName, String name, ChannelHandler handler);
/**
* Removes the specified {@link ChannelHandler} from this pipeline.
*
* @throws NoSuchElementException
* if there's no such handler in this pipeline
* @throws NullPointerException
* if the specified handler is {@code null}
*/
void remove(ChannelHandler handler);
/**
* Removes the {@link ChannelHandler} with the specified name from this
* pipeline.
*
* @return the removed handler
*
* @throws NoSuchElementException
* if there's no such handler with the specified name in this pipeline
* @throws NullPointerException
* if the specified name is {@code null}
*/
ChannelHandler remove(String name);
/**
* Removes the {@link ChannelHandler} of the specified type from this
* pipeline
*
* @param