View Javadoc

    1   /*
    2    * Copyright 2009 Red Hat, Inc.
    3    *
    4    * Red Hat licenses this file to you under the Apache License, version 2.0
    5    * (the "License"); you may not use this file except in compliance with the
    6    * 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   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
    75   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
    76   *
    77   * @version $Rev: 2122 $, $Date: 2010-02-02 11:00:04 +0900 (Tue, 02 Feb 2010) $
    78   */
    79  public class SimpleChannelHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
    80
    81      private static final InternalLogger logger =
    82          InternalLoggerFactory.getInstance(SimpleChannelHandler.class.getName());
    83
    84      /**
    85       * Creates a new instance.
    86       */
    87      public SimpleChannelHandler() {
    88          super();
    89      }
    90
    91      /**
    92       * {@inheritDoc}  Down-casts the received upstream event into more
    93       * meaningful sub-type event and calls an appropriate handler method with
    94       * the down-casted event.
    95       */
    96      public void handleUpstream(
    97              ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
    98
    99          if (e instanceof MessageEvent) {
    100             messageReceived(ctx, (MessageEvent) e);
    101         } else if (e instanceof WriteCompletionEvent) {
    102             WriteCompletionEvent evt = (WriteCompletionEvent) e;
    103             writeComplete(ctx, evt);
    104         } else if (e instanceof ChildChannelStateEvent) {
    105             ChildChannelStateEvent evt = (ChildChannelStateEvent) e;
    106             if (evt.getChildChannel().isOpen()) {
    107                 childChannelOpen(ctx, evt);
    108             } else {
    109                 childChannelClosed(ctx, evt);
    110             }
    111         } else if (e instanceof ChannelStateEvent) {
    112             ChannelStateEvent evt = (ChannelStateEvent) e;
    113             switch (evt.getState()) {
    114             case OPEN:
    115                 if (Boolean.TRUE.equals(evt.getValue())) {
    116                     channelOpen(ctx, evt);
    117                 } else {
    118                     channelClosed(ctx, evt);
    119                 }
    120                 break;
    121             case BOUND:
    122                 if (evt.getValue() != null) {
    123                     channelBound(ctx, evt);
    124                 } else {
    125                     channelUnbound(ctx, evt);
    126                 }
    127                 break;
    128             case CONNECTED:
    129                 if (evt.getValue() != null) {
    130                     channelConnected(ctx, evt);
    131                 } else {
    132                     channelDisconnected(ctx, evt);
    133                 }
    134                 break;
    135             case INTEREST_OPS:
    136                 channelInterestChanged(ctx, evt);
    137                 break;
    138             default:
    139                 ctx.sendUpstream(e);
    140             }
    141         } else if (e instanceof ExceptionEvent) {
    142             exceptionCaught(ctx, (ExceptionEvent) e);
    143         } else {
    144             ctx.sendUpstream(e);
    145         }
    146     }
    147
    148     /**
    149      * Invoked when a message object (e.g: {@link ChannelBuffer}) was received
    150      * from a remote peer.
    151      */
    152     public void messageReceived(
    153             ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    154         ctx.sendUpstream(e);
    155     }
    156
    157     /**
    158      * Invoked when an exception was raised by an I/O thread or a
    159      * {@link ChannelHandler}.
    160      */
    161     public void exceptionCaught(
    162             ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
    163         if (this == ctx.getPipeline().getLast()) {
    164             logger.warn(
    165                     "EXCEPTION, please implement " + getClass().getName() +
    166                     ".exceptionCaught() for proper handling.", e.getCause());
    167         }
    168         ctx.sendUpstream(e);
    169     }
    170
    171     /**
    172      * Invoked when a {@link Channel} is open, but not bound nor connected.
    173      */
    174     public void channelOpen(
    175             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    176         ctx.sendUpstream(e);
    177     }
    178
    179     /**
    180      * Invoked when a {@link Channel} is open and bound to a local address,
    181      * but not connected.
    182      */
    183     public void channelBound(
    184             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    185         ctx.sendUpstream(e);
    186     }
    187
    188     /**
    189      * Invoked when a {@link Channel} is open, bound to a local address, and
    190      * connected to a remote address.
    191      */
    192     public void channelConnected(
    193             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    194         ctx.sendUpstream(e);
    195     }
    196
    197     /**
    198      * Invoked when a {@link Channel}'s {@link Channel#getInterestOps() interestOps}
    199      * was changed.
    200      */
    201     public void channelInterestChanged(
    202             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    203         ctx.sendUpstream(e);
    204     }
    205
    206     /**
    207      * Invoked when a {@link Channel} was disconnected from its remote peer.
    208      */
    209     public void channelDisconnected(
    210             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    211         ctx.sendUpstream(e);
    212     }
    213
    214     /**
    215      * Invoked when a {@link Channel} was unbound from the current local address.
    216      */
    217     public void channelUnbound(
    218             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    219         ctx.sendUpstream(e);
    220     }
    221
    222     /**
    223      * Invoked when a {@link Channel} was closed and all its related resources
    224      * were released.
    225      */
    226     public void channelClosed(
    227             ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    228         ctx.sendUpstream(e);
    229     }
    230
    231     /**
    232      * Invoked when something was written into a {@link Channel}.
    233      */
    234     public void writeComplete(
    235             ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception {
    236         ctx.sendUpstream(e);
    237     }
    238
    239     /**
    240      * Invoked when a child {@link Channel} was open.
    241      * (e.g. a server channel accepted a connection)
    242      */
    243     public void childChannelOpen(
    244             ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
    245         ctx.sendUpstream(e);
    246     }
    247
    248     /**
    249      * Invoked when a child {@link Channel} was closed.
    250      * (e.g. the accepted connection was closed)
    251      */
    252     public void childChannelClosed(
    253             ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
    254         ctx.sendUpstream(e);
    255     }
    256
    257     /**
    258      * {@inheritDoc}  Down-casts the received downstream event into more
    259      * meaningful sub-type event and calls an appropriate handler method with
    260      * the down-casted event.
    261      */
    262     public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
    263             throws Exception {
    264
    265         if (e instanceof MessageEvent) {
    266             writeRequested(ctx, (MessageEvent) e);
    267         } else if (e instanceof ChannelStateEvent) {
    268             ChannelStateEvent evt = (ChannelStateEvent) e;
    269             switch (evt.getState()) {
    270             case OPEN:
    271                 if (!Boolean.TRUE.equals(evt.getValue())) {
    272                     closeRequested(ctx, evt);
    273                 }
    274                 break;
    275             case BOUND:
    276                 if (evt.getValue() != null) {
    277                     bindRequested(ctx, evt);
    278                 } else {
    279                     unbindRequested(ctx, evt);
    280                 }
    281                 break;
    282             case CONNECTED:
    283                 if (evt.getValue() != null) {
    284                     connectRequested(ctx, evt);
    285                 } else {
    286                     disconnectRequested(ctx, evt);
    287                 }
    288                 break;
    289             case INTEREST_OPS:
    290                 setInterestOpsRequested(ctx, evt);
    291                 break;
    292             default:
    293                 ctx.sendDownstream(e);
    294             }
    295         } else {
    296             ctx.sendDownstream(e);
    297         }
    298     }
    299
    300     /**
    301      * Invoked when {@link Channel#write(Object)} is called.
    302      */
    303     public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    304         ctx.sendDownstream(e);
    305     }
    306
    307     /**
    308      * Invoked when {@link Channel#bind(SocketAddress)} was called.
    309      */
    310     public void bindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    311         ctx.sendDownstream(e);
    312
    313     }
    314
    315     /**
    316      * Invoked when {@link Channel#connect(SocketAddress)} was called.
    317      */
    318     public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    319         ctx.sendDownstream(e);
    320
    321     }
    322
    323     /**
    324      * Invoked when {@link Channel#setInterestOps(int)} was called.
    325      */
    326     public void setInterestOpsRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    327         ctx.sendDownstream(e);
    328     }
    329
    330     /**
    331      * Invoked when {@link Channel#disconnect()} was called.
    332      */
    333     public void disconnectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    334         ctx.sendDownstream(e);
    335
    336     }
    337
    338     /**
    339      * Invoked when {@link Channel#unbind()} was called.
    340      */
    341     public void unbindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    342         ctx.sendDownstream(e);
    343
    344     }
    345
    346     /**
    347      * Invoked when {@link Channel#close()} was called.
    348      */
    349     public void closeRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    350         ctx.sendDownstream(e);
    351     }
    352 }