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 }