View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the License. You may obtain a copy of the License at:
    7    *
    8    *   http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.channel;
    17
    18  import java.net.SocketAddress;
    19
    20  import org.jboss.netty.buffer.ChannelBuffer;
    21  import org.jboss.netty.logging.InternalLogger;
    22  import org.jboss.netty.logging.InternalLoggerFactory;
    23
    24
    25  /**
    26   * A {@link ChannelHandler} which provides an individual handler method
    27   * for each event type.  This handler down-casts the received upstream or
    28   * or downstream event into more meaningful sub-type event and calls an
    29   * appropriate handler method with the down-cast event.  For an upstream
    30   * event, the names of the methods are identical to the upstream event names,
    31   * as introduced in the {@link ChannelEvent} documentation.  For a
    32   * downstream event, the names of the methods starts with the name of the
    33   * operation and ends with {@code "Requested"}
    34   * (e.g. {@link #writeRequested(ChannelHandlerContext, MessageEvent) writeRequested}.)
    35   * <p>
    36   * Please use {@link SimpleChannelUpstreamHandler} or
    37   * {@link SimpleChannelDownstreamHandler} if you want to intercept only
    38   * upstream or downstream events.
    39   *
    40   * <h3>Overriding the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
    41   *     and {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream} method</h3>
    42   * <p>
    43   * You can override the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
    44   * and {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream}
    45   * method just like overriding an ordinary Java method.  Please make sure to
    46   * call {@code super.handleUpstream()} or {@code super.handleDownstream()} so
    47   * that other handler methods are invoked properly:
    48   * </p>
    49   * <pre>public class MyChannelHandler extends {@link SimpleChannelHandler} {
    50   *
    51   *     {@code @Override}
    52   *     public void handleUpstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
    53   *
    54   *         // Log all channel state changes.
    55   *         if (e instanceof {@link ChannelStateEvent}) {
    56   *             logger.info("Channel state changed: " + e);
    57   *         }
    58   *
    59   *         <strong>super.handleUpstream(ctx, e);</strong>
    60   *     }
    61   *
    62   *     {@code @Override}
    63   *     public void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
    64   *
    65   *         // Log all channel state changes.
    66   *         if (e instanceof {@link MessageEvent}) {
    67   *             logger.info("Writing:: " + e);
    68   *         }
    69   *
    70   *         <strong>super.handleDownstream(ctx, e);</strong>
    71   *     }
    72   * }</pre>
    73   */
    74  public class SimpleChannelHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
    75
    76      private static final InternalLogger logger =
    77          InternalLoggerFactory.getInstance(SimpleChannelHandler.class.getName());
    78
    79      /**
    80       * Creates a new instance.
    81       */
    82      public SimpleChannelHandler() {
    83          super();
    84      }
    85
    86      /**
    87       * {@inheritDoc}  Down-casts the received upstream event into more
    88       * meaningful sub-type event and calls an appropriate handler method with
    89       * the down-casted event.
    90       */
    91      public void handleUpstream(
    92              ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
    93
    94          if (e instanceof MessageEvent) {
    95              messageReceived(ctx, (MessageEvent) e);
    96          } else if (e instanceof WriteCompletionEvent) {
    97              WriteCompletionEvent evt = (WriteCompletionEvent) e;
    98              writeComplete(ctx, evt);
    99          } else if (e instanceof ChildChannelStateEvent) {
    100             ChildChannelStateEvent evt = (ChildChannelStateEvent) e;
    101             if (evt.getChildChannel().isOpen()) {
    102                 childChannelOpen(ctx, evt);
    103             } else {
    104                 childChannelClosed(ctx, evt);
    105             }
    106         } else if (e instanceof ChannelStateEvent) {
    107             ChannelStateEvent evt = (ChannelStateEvent) e;
    108             switch (evt.getState()) {
    109             case OPEN:
    110                 if (Boolean.TRUE.equals(evt.getValue())) {
    111                     channelOpen(ctx, evt);
    112                 } else {
    113                     channelClosed(ctx, evt);
    114                 }
    115                 break;
    116             case BOUND:
    117                 if (evt.getValue() != null) {
    118                     channelBound(ctx, evt);
    119                 } else {
    120                     channelUnbound(ctx, evt);
    121                 }
    122                 break;
    123             case CONNECTED:
    124                 if (evt.getValue() != null) {
    125                     channelConnected(ctx, evt);
    126                 } else {
    127                     channelDisconnected(ctx, evt);
    128                 }
    129                 break;
    130             case INTEREST_OPS:
    131                 channelInterestChanged(ctx, evt);
    132                 break;
    133             default:
    134                 ctx.sendUpstream(e);
    135             }
    136         } else if (e instanceof ExceptionEvent) {
    137             exceptionCaught(ctx, (ExceptionEvent) e);
    138         } else {
    139             ctx.sendUpstream(e);
    140         }
    141     }
    142
    143     /**
    144      * Invoked when a message object (e.g: {@link ChannelBuffer}) was received
    145      * from a remote peer.
    146      */
    147     public void messageReceived(
    148             ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    149         ctx.sendUpstream(e);
    150     }
    151
    152     /**
    153      * Invoked when an exception was raised by an I/O thread or a
    154      * {@link ChannelHandler}.
    155      */
    156     public void exceptionCaught(
    157             ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
    158         if (this == ctx.getPipeline().getLast()) {
    159             logger.warn(
    160                     "EXCEPTION, please implement " + getClass().getName() +
    161                     ".exceptionCaught() for proper handling.", e.getCause());
    162         }
    163         ctx.sendUpstream(e);
    164     }
    165
    166     /**
    167      * Invoked when a {@link Channel} is open, but not bound nor connected.
    168      */
    169     public void channelOpen(
    170             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    171         ctx.sendUpstream(e);
    172     }
    173
    174     /**
    175      * Invoked when a {@link Channel} is open and bound to a local address,
    176      * but not connected.
    177      */
    178     public void channelBound(
    179             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    180         ctx.sendUpstream(e);
    181     }
    182
    183     /**
    184      * Invoked when a {@link Channel} is open, bound to a local address, and
    185      * connected to a remote address.
    186      */
    187     public void channelConnected(
    188             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    189         ctx.sendUpstream(e);
    190     }
    191
    192     /**
    193      * Invoked when a {@link Channel}'s {@link Channel#getInterestOps() interestOps}
    194      * was changed.
    195      */
    196     public void channelInterestChanged(
    197             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    198         ctx.sendUpstream(e);
    199     }
    200
    201     /**
    202      * Invoked when a {@link Channel} was disconnected from its remote peer.
    203      */
    204     public void channelDisconnected(
    205             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    206         ctx.sendUpstream(e);
    207     }
    208
    209     /**
    210      * Invoked when a {@link Channel} was unbound from the current local address.
    211      */
    212     public void channelUnbound(
    213             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    214         ctx.sendUpstream(e);
    215     }
    216
    217     /**
    218      * Invoked when a {@link Channel} was closed and all its related resources
    219      * were released.
    220      */
    221     public void channelClosed(
    222             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    223         ctx.sendUpstream(e);
    224     }
    225
    226     /**
    227      * Invoked when something was written into a {@link Channel}.
    228      */
    229     public void writeComplete(
    230             ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception {
    231         ctx.sendUpstream(e);
    232     }
    233
    234     /**
    235      * Invoked when a child {@link Channel} was open.
    236      * (e.g. a server channel accepted a connection)
    237      */
    238     public void childChannelOpen(
    239             ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
    240         ctx.sendUpstream(e);
    241     }
    242
    243     /**
    244      * Invoked when a child {@link Channel} was closed.
    245      * (e.g. the accepted connection was closed)
    246      */
    247     public void childChannelClosed(
    248             ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
    249         ctx.sendUpstream(e);
    250     }
    251
    252     /**
    253      * {@inheritDoc}  Down-casts the received downstream event into more
    254      * meaningful sub-type event and calls an appropriate handler method with
    255      * the down-casted event.
    256      */
    257     public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
    258             throws Exception {
    259
    260         if (e instanceof MessageEvent) {
    261             writeRequested(ctx, (MessageEvent) e);
    262         } else if (e instanceof ChannelStateEvent) {
    263             ChannelStateEvent evt = (ChannelStateEvent) e;
    264             switch (evt.getState()) {
    265             case OPEN:
    266                 if (!Boolean.TRUE.equals(evt.getValue())) {
    267                     closeRequested(ctx, evt);
    268                 }
    269                 break;
    270             case BOUND:
    271                 if (evt.getValue() != null) {
    272                     bindRequested(ctx, evt);
    273                 } else {
    274                     unbindRequested(ctx, evt);
    275                 }
    276                 break;
    277             case CONNECTED:
    278                 if (evt.getValue() != null) {
    279                     connectRequested(ctx, evt);
    280                 } else {
    281                     disconnectRequested(ctx, evt);
    282                 }
    283                 break;
    284             case INTEREST_OPS:
    285                 setInterestOpsRequested(ctx, evt);
    286                 break;
    287             default:
    288                 ctx.sendDownstream(e);
    289             }
    290         } else {
    291             ctx.sendDownstream(e);
    292         }
    293     }
    294
    295     /**
    296      * Invoked when {@link Channel#write(Object)} is called.
    297      */
    298     public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    299         ctx.sendDownstream(e);
    300     }
    301
    302     /**
    303      * Invoked when {@link Channel#bind(SocketAddress)} was called.
    304      */
    305     public void bindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    306         ctx.sendDownstream(e);
    307
    308     }
    309
    310     /**
    311      * Invoked when {@link Channel#connect(SocketAddress)} was called.
    312      */
    313     public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    314         ctx.sendDownstream(e);
    315
    316     }
    317
    318     /**
    319      * Invoked when {@link Channel#setInterestOps(int)} was called.
    320      */
    321     public void setInterestOpsRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    322         ctx.sendDownstream(e);
    323     }
    324
    325     /**
    326      * Invoked when {@link Channel#disconnect()} was called.
    327      */
    328     public void disconnectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    329         ctx.sendDownstream(e);
    330
    331     }
    332
    333     /**
    334      * Invoked when {@link Channel#unbind()} was called.
    335      */
    336     public void unbindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    337         ctx.sendDownstream(e);
    338
    339     }
    340
    341     /**
    342      * Invoked when {@link Channel#close()} was called.
    343      */
    344     public void closeRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    345         ctx.sendDownstream(e);
    346     }
    347 }