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 }