Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.jboss.netty.channel
Interface ChannelPipeline

All Known Implementing Classes:
  DefaultChannelPipeline, StaticChannelPipeline

    public interface ChannelPipeline

A list of `ChannelHandler`s which handles or intercepts `ChannelEvent`s of a `Channel`. `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 `ChannelHandler`s in the pipeline interact with each other.

### Creation of a pipeline

For each new channel, a new pipeline must be created and attached to the channel. Once attached, the coupling between the channel and the pipeline is permanent; the channel cannot attach another pipeline to it nor detach the current pipeline from it.

The recommended way to create a new pipeline is to use the helper methods in `Channels` rather than calling an individual implementation's constructor:

     import static org.jboss.netty.channel.Channels.*;
     ChannelPipeline pipeline = pipeline(); // same with Channels.pipeline()

### How an event flows in a pipeline

The following diagram describes how `ChannelEvent`s are processed by `ChannelHandler`s in a `ChannelPipeline` typically. A `ChannelEvent` can be handled by either a `ChannelUpstreamHandler` or a `ChannelDownstreamHandler` and be forwarded to the closest handler by calling `ChannelHandlerContext.sendUpstream(ChannelEvent)` or `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 `ChannelEvent` for more information.

                                           I/O Request
                                         via Channel or
                                     ChannelHandlerContext
                                               |
      +----------------------------------------+---------------+
      |                  ChannelPipeline       |               |
      |                                       \|/              |
      |  +----------------------+  +-----------+------------+  |
      |  | Upstream Handler  N  |  | Downstream Handler  1  |  |
      |  +----------+-----------+  +-----------+------------+  |
      |            /|\                         |               |
      |             |                         \|/              |
      |  +----------+-----------+  +-----------+------------+  |
      |  | Upstream Handler N-1 |  | Downstream Handler  2  |  |
      |  +----------+-----------+  +-----------+------------+  |
      |            /|\                         .               |
      |             .                          .               |
      |     [ sendUpstream() ]        [ sendDownstream() ]     |
      |     [ + INBOUND data ]        [ + OUTBOUND data  ]     |
      |             .                          .               |
      |             .                         \|/              |
      |  +----------+-----------+  +-----------+------------+  |
      |  | Upstream Handler  2  |  | Downstream Handler M-1 |  |
      |  +----------+-----------+  +-----------+------------+  |
      |            /|\                         |               |
      |             |                         \|/              |
      |  +----------+-----------+  +-----------+------------+  |
      |  | Upstream Handler  1  |  | Downstream Handler  M  |  |
      |  +----------+-----------+  +-----------+------------+  |
      |            /|\                         |               |
      +-------------+--------------------------+---------------+
                    |                         \|/
      +-------------+--------------------------+---------------+
      |             |                          |               |
      |     [ Socket.read() ]          [ Socket.write() ]      |
      |                                                        |
      |  Netty Internal I/O Threads (Transport Implementation) |
      +--------------------------------------------------------+

An upstream event is handled by the upstream handlers in the bottom-up direction as shown on the left side of the diagram. An upstream handler usually handles the inbound data generated by the I/O thread on the bottom of the diagram. The inbound data is often read from a remote peer via the actual input operation such as `InputStream.read(byte[])`. If an upstream event goes beyond the top upstream handler, it is discarded silently.

A downstream event is handled by the downstream handler in the top-down direction as shown on the right side of the diagram. A downstream handler usually generates or transforms the outbound traffic such as write requests. If a downstream event goes beyond the bottom downstream handler, it is handled by an I/O thread associated with the `Channel`. The I/O thread often performs the actual output operation such as `OutputStream.write(byte[])`.

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());

In the example above, the class whose name starts with `Upstream` means it is an upstream handler. The class whose name starts with `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, `ChannelPipeline` skips the evaluation of certain handlers to shorten the stack depth:

- 3 and 4 don't implement `ChannelUpstreamHandler`, and therefore the actual evaluation order of an upstream event will be: 1, 2, and 5.
- 1, 2, and 5 don't implement `ChannelDownstreamHandler`, and therefore the actual evaluation order of a downstream event will be: 4 and 3.
- If 5 extended `SimpleChannelHandler` which implements both `ChannelUpstreamHandler` and `ChannelDownstreamHandler`, the evaluation order of an upstream and a downstream event could be 125 and 543 respectively.

### Building a pipeline

A user is supposed to have one or more `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:

1. Protocol Decoder - translates binary data (e.g. `ChannelBuffer`) into a Java object.
2. Protocol Encoder - translates a Java object into binary data.
3. `ExecutionHandler` - applies a thread model.
4. Business Logic Handler - performs the actual business logic (e.g. database access).

and it could be represented as shown in the following example:

     ChannelPipeline pipeline = Channels.pipeline();
     pipeline.addLast("decoder", new MyProtocolDecoder());
     pipeline.addLast("encoder", new MyProtocolEncoder());
     pipeline.addLast("executor", new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576)));
     pipeline.addLast("handler", new MyBusinessLogicHandler());

### Thread safety

A `ChannelHandler` can be added or removed at any time because a `ChannelPipeline` is thread safe. For example, you can insert a `SslHandler` when sensitive information is about to be exchanged, and remove it after the exchange.

### Pitfall

Due to the internal implementation detail of the current default `ChannelPipeline`, the following code does not work as expected if `FirstHandler` is the last handler in the pipeline:

     public class FirstHandler extends SimpleChannelUpstreamHandler {

         @Override
         public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
             // Remove this handler from the pipeline,
             ctx.getPipeline().remove(this);
             // And let SecondHandler handle the current event.
             ctx.getPipeline().addLast("2nd", new SecondHandler());
             ctx.sendUpstream(e);
         }
     }

To implement the expected behavior, you have to add `SecondHandler` before the removal or make sure there is at least one more handler between `FirstHandler` and `SecondHandler`.

Version:
  $Rev: 2153 $, $Date: 2010-02-17 17:24:25 +0900 (Wed, 17 Feb 2010) $
Author:
  The Netty Project, Trustin Lee

Method Summary
`void` | `addAfter(String baseName, String name, ChannelHandler handler)` Inserts a `ChannelHandler` after an existing handler of this pipeline.
`void` | `addBefore(String baseName, String name, ChannelHandler handler)` Inserts a `ChannelHandler` before an existing handler of this pipeline.
`void` | `addFirst(String name, ChannelHandler handler)` Inserts a `ChannelHandler` at the first position of this pipeline.
`void` | `addLast(String name, ChannelHandler handler)` Appends a `ChannelHandler` at the last position of this pipeline.
`void` | `attach(Channel channel, ChannelSink sink)` Attaches this pipeline to the specified `Channel` and `ChannelSink`.
`
`<T extends ChannelHandler> T`
` | `get(Class<T> handlerType)` Returns the `ChannelHandler` of the specified type in this pipeline.
`ChannelHandler` | `get(String name)` Returns the `ChannelHandler` with the specified name in this pipeline.
`Channel` | `getChannel()` Returns the `Channel` that this pipeline is attached to.
`ChannelHandlerContext` | `getContext(ChannelHandler handler)` Returns the context object of the specified `ChannelHandler` in this pipeline.
`ChannelHandlerContext` | `getContext(Class<? extends ChannelHandler> handlerType)` Returns the context object of the `ChannelHandler` of the specified type in this pipeline.
`ChannelHandlerContext` | `getContext(String name)` Returns the context object of the `ChannelHandler` with the specified name in this pipeline.
`ChannelHandler` | `getFirst()` Returns the first `ChannelHandler` in this pipeline.
`ChannelHandler` | `getLast()` Returns the last `ChannelHandler` in this pipeline.
`ChannelSink` | `getSink()` Returns the `ChannelSink` that this pipeline is attached to.
`boolean` | `isAttached()` Returns `true` if and only if this pipeline is attached to a `Channel`.
`void` | `remove(ChannelHandler handler)` Removes the specified `ChannelHandler` from this pipeline.
`
`<T extends ChannelHandler> T`
` | `remove(Class<T> handlerType)` Removes the `ChannelHandler` of the specified type from this pipeline
`ChannelHandler` | `remove(String name)` Removes the `ChannelHandler` with the specified name from this pipeline.
`ChannelHandler` | `removeFirst()` Removes the first `ChannelHandler` in this pipeline.
`ChannelHandler` | `removeLast()` Removes the last `ChannelHandler` in this pipeline.
`void` | `replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler)` Replaces the specified `ChannelHandler` with a new handler in this pipeline.
`
`<T extends ChannelHandler> T`
` | `replace(Class<T> oldHandlerType, String newName, ChannelHandler newHandler)` Replaces the `ChannelHandler` of the specified type with a new handler in this pipeline.
`ChannelHandler` | `replace(String oldName, String newName, ChannelHandler newHandler)` Replaces the `ChannelHandler` of the specified name with a new handler in this pipeline.
`void` | `sendDownstream(ChannelEvent e)` Sends the specified `ChannelEvent` to the last `ChannelDownstreamHandler` in this pipeline.
`void` | `sendUpstream(ChannelEvent e)` Sends the specified `ChannelEvent` to the first `ChannelUpstreamHandler` in this pipeline.
`Map<String,ChannelHandler>` | `toMap()` Converts this pipeline into an ordered `Map` whose keys are handler names and whose values are handlers.

Method Detail

### addFirst

    void addFirst(String name,
                  ChannelHandler handler)

  Inserts a `ChannelHandler` at the first position of this pipeline.

  Parameters:
    `name` - the name of the handler to insert first
    `handler` - the handler to insert first
  Throws:
    `IllegalArgumentException` - if there's an entry with the same name already in the pipeline
    `NullPointerException` - if the specified name or handler is `null`

### addLast

    void addLast(String name,
                 ChannelHandler handler)

  Appends a `ChannelHandler` at the last position of this pipeline.

  Parameters:
    `name` - the name of the handler to append
    `handler` - the handler to append
  Throws:
    `IllegalArgumentException` - if there's an entry with the same name already in the pipeline
    `NullPointerException` - if the specified name or handler is `null`

### addBefore

    void addBefore(String baseName,
                   String name,
                   ChannelHandler handler)

  Inserts a `ChannelHandler` before an existing handler of this pipeline.

  Parameters:
    `baseName` - the name of the existing handler
    `name` - the name of the handler to insert before
    `handler` - the handler to insert before
  Throws:
    `NoSuchElementException` - if there's no such entry with the specified `baseName`
    `IllegalArgumentException` - if there's an entry with the same name already in the pipeline
    `NullPointerException` - if the specified baseName, name, or handler is `null`

### addAfter

    void addAfter(String baseName,
                  String name,
                  ChannelHandler handler)

  Inserts a `ChannelHandler` after an existing handler of this pipeline.

  Parameters:
    `baseName` - the name of the existing handler
    `name` - the name of the handler to insert after
    `handler` - the handler to insert after
  Throws:
    `NoSuchElementException` - if there's no such entry with the specified `baseName`
    `IllegalArgumentException` - if there's an entry with the same name already in the pipeline
    `NullPointerException` - if the specified baseName, name, or handler is `null`

### remove

    void remove(ChannelHandler handler)

  Removes the specified `ChannelHandler` from this pipeline.

  Throws:
    `NoSuchElementException` - if there's no such handler in this pipeline
    `NullPointerException` - if the specified handler is `null`

### remove

    ChannelHandler remove(String name)

  Removes the `ChannelHandler` with the specified name from this pipeline.

  Returns:
    the removed handler
  Throws:
    `NoSuchElementException` - if there's no such handler with the specified name in this pipeline
    `NullPointerException` - if the specified name is `null`

### remove

    <T extends ChannelHandler> T remove(Class<T> handlerType)

  Removes the `ChannelHandler` of the specified type from this pipeline

  Type Parameters:
    `T` - the type of the handler
  Parameters:
    `handlerType` - the type of the handler
  Returns:
    the removed handler
  Throws:
    `NoSuchElementException` - if there's no such handler of the specified type in this pipeline
    `NullPointerException` - if the specified handler type is `null`

### removeFirst

    ChannelHandler removeFirst()

  Removes the first `ChannelHandler` in this pipeline.

  Returns:
    the removed handler
  Throws:
    `NoSuchElementException` - if this pipeline is empty

### removeLast

    ChannelHandler removeLast()

  Removes the last `ChannelHandler` in this pipeline.

  Returns:
    the removed handler
  Throws:
    `NoSuchElementException` - if this pipeline is empty

### replace

    void replace(ChannelHandler oldHandler,
                 String newName,
                 ChannelHandler newHandler)

  Replaces the specified `ChannelHandler` with a new handler in this pipeline.

  Throws:
    `NoSuchElementException` - if the specified old handler does not exist in this pipeline
    `IllegalArgumentException` - if a handler with the specified new name already exists in this pipeline, except for the handler to be replaced
    `NullPointerException` - if the specified old handler, new name, or new handler is `null`

### replace

    ChannelHandler replace(String oldName,
                           String newName,
                           ChannelHandler newHandler)

  Replaces the `ChannelHandler` of the specified name with a new handler in this pipeline.

  Returns:
    the removed handler
  Throws:
    `NoSuchElementException` - if the handler with the specified old name does not exist in this pipeline
    `IllegalArgumentException` - if a handler with the specified new name already exists in this pipeline, except for the handler to be replaced
    `NullPointerException` - if the specified old handler, new name, or new handler is `null`

### replace

    <T extends ChannelHandler> T replace(Class<T> oldHandlerType,
                                         String newName,
                                         ChannelHandler newHandler)

  Replaces the `ChannelHandler` of the specified type with a new handler in this pipeline.

  Returns:
    the removed handler
  Throws:
    `NoSuchElementException` - if the handler of the specified old handler type does not exist in this pipeline
    `IllegalArgumentException` - if a handler with the specified new name already exists in this pipeline, except for the handler to be replaced
    `NullPointerException` - if the specified old handler, new name, or new handler is `null`

### getFirst

    ChannelHandler getFirst()

  Returns the first `ChannelHandler` in this pipeline.

  Returns:
    the first handler. `null` if this pipeline is empty.

### getLast

    ChannelHandler getLast()

  Returns the last `ChannelHandler` in this pipeline.

  Returns:
    the last handler. `null` if this pipeline is empty.

### get

    ChannelHandler get(String name)

  Returns the `ChannelHandler` with the specified name in this pipeline.

  Returns:
    the handler with the specified name. `null` if there's no such handler in this pipeline.

### get

    <T extends ChannelHandler> T get(Class<T> handlerType)

  Returns the `ChannelHandler` of the specified type in this pipeline.

  Returns:
    the handler of the specified handler type. `null` if there's no such handler in this pipeline.

### getContext

    ChannelHandlerContext getContext(ChannelHandler handler)

  Returns the context object of the specified `ChannelHandler` in this pipeline.

  Returns:
    the context object of the specified handler. `null` if there's no such handler in this pipeline.

### getContext

    ChannelHandlerContext getContext(String name)

  Returns the context object of the `ChannelHandler` with the specified name in this pipeline.

  Returns:
    the context object of the handler with the specified name. `null` if there's no such handler in this pipeline.

### getContext

    ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType)

  Returns the context object of the `ChannelHandler` of the specified type in this pipeline.

  Returns:
    the context object of the handler of the specified type. `null` if there's no such handler in this pipeline.

### sendUpstream

    void sendUpstream(ChannelEvent e)

  Sends the specified `ChannelEvent` to the first `ChannelUpstreamHandler` in this pipeline.

  Throws:
    `NullPointerException` - if the specified event is `null`

### sendDownstream

    void sendDownstream(ChannelEvent e)

  Sends the specified `ChannelEvent` to the last `ChannelDownstreamHandler` in this pipeline.

  Throws:
    `NullPointerException` - if the specified event is `null`

### getChannel

    Channel getChannel()

  Returns the `Channel` that this pipeline is attached to.

  Returns:
    the channel. `null` if this pipeline is not attached yet.

### getSink

    ChannelSink getSink()

  Returns the `ChannelSink` that this pipeline is attached to.

  Returns:
    the sink. `null` if this pipeline is not attached yet.

### attach

    void attach(Channel channel,
                ChannelSink sink)

  Attaches this pipeline to the specified `Channel` and `ChannelSink`. Once a pipeline is attached, it can't be detached nor attached again.

  Throws:
    `IllegalStateException` - if this pipeline is attached already

### isAttached

    boolean isAttached()

  Returns `true` if and only if this pipeline is attached to a `Channel`.

### toMap

    Map<String,ChannelHandler> toMap()

  Converts this pipeline into an ordered `Map` whose keys are handler names and whose values are handlers.

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright © 2008-2010 JBoss, a division of Red Hat, Inc.. All Rights Reserved.