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