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 org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.logging.InternalLogger;
20 import org.jboss.netty.logging.InternalLoggerFactory;
21
22 import java.util.List;
23
24
25 /**
26 * A {@link ChannelUpstreamHandler} which provides an individual handler method
27 * for each event type. This handler down-casts the received upstream event
28 * into more meaningful sub-type event and calls an appropriate handler method
29 * with the down-cast event. The names of the methods are identical to the
30 * upstream event names, as introduced in the {@link ChannelEvent} documentation.
31 * <p>
32 * Please use {@link SimpleChannelHandler} if you need to implement both
33 * {@link ChannelUpstreamHandler} and {@link ChannelDownstreamHandler}.
34 *
35 * <h3>Overriding the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream} method</h3>
36 * <p>
37 * You can override the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
38 * method just like overriding an ordinary Java method. Please make sure to
39 * call {@code super.handleUpstream()} so that other handler methods are invoked
40 * properly:
41 * </p>
42 * <pre>public class MyChannelHandler extends {@link SimpleChannelUpstreamHandler} {
43 *
44 * {@code @Override}
45 * public void handleUpstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
46 *
47 * // Log all channel state changes.
48 * if (e instanceof {@link ChannelStateEvent}) {
49 * logger.info("Channel state changed: " + e);
50 * }
51 *
52 * <strong>super.handleUpstream(ctx, e);</strong>
53 * }
54 * }</pre>
55 */
56 public class SimpleChannelUpstreamHandler implements ChannelUpstreamHandler {
57
58 private static final InternalLogger logger =
59 InternalLoggerFactory.getInstance(SimpleChannelUpstreamHandler.class.getName());
60
61 /**
62 * {@inheritDoc} Down-casts the received upstream event into more
63 * meaningful sub-type event and calls an appropriate handler method with
64 * the down-casted event.
65 */
66 public void handleUpstream(
67 ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
68
69 if (e instanceof MessageEvent) {
70 messageReceived(ctx, (MessageEvent) e);
71 } else if (e instanceof WriteCompletionEvent) {
72 WriteCompletionEvent evt = (WriteCompletionEvent) e;
73 writeComplete(ctx, evt);
74 } else if (e instanceof ChildChannelStateEvent) {
75 ChildChannelStateEvent evt = (ChildChannelStateEvent) e;
76 if (evt.getChildChannel().isOpen()) {
77 childChannelOpen(ctx, evt);
78 } else {
79 childChannelClosed(ctx, evt);
80 }
81 } else if (e instanceof ChannelStateEvent) {
82 ChannelStateEvent evt = (ChannelStateEvent) e;
83 switch (evt.getState()) {
84 case OPEN:
85 if (Boolean.TRUE.equals(evt.getValue())) {
86 channelOpen(ctx, evt);
87 } else {
88 channelClosed(ctx, evt);
89 }
90 break;
91 case BOUND:
92 if (evt.getValue() != null) {
93 channelBound(ctx, evt);
94 } else {
95 channelUnbound(ctx, evt);
96 }
97 break;
98 case CONNECTED:
99 if (evt.getValue() != null) {
100 channelConnected(ctx, evt);
101 } else {
102 channelDisconnected(ctx, evt);
103 }
104 break;
105 case INTEREST_OPS:
106 channelInterestChanged(ctx, evt);
107 break;
108 default:
109 ctx.sendUpstream(e);
110 }
111 } else if (e instanceof ExceptionEvent) {
112 exceptionCaught(ctx, (ExceptionEvent) e);
113 } else {
114 ctx.sendUpstream(e);
115 }
116 }
117
118 /**
119 * Invoked when a message object (e.g: {@link ChannelBuffer}) was received
120 * from a remote peer.
121 */
122 public void messageReceived(
123 ChannelHandlerContext ctx, MessageEvent e) throws Exception {
124 ctx.sendUpstream(e);
125 }
126
127 /**
128 * Invoked when an exception was raised by an I/O thread or a
129 * {@link ChannelHandler}.
130 */
131 public void exceptionCaught(
132 ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
133 ChannelPipeline pipeline = ctx.getPipeline();
134
135 ChannelHandler last = pipeline.getLast();
136 if (!(last instanceof ChannelUpstreamHandler) && ctx instanceof DefaultChannelPipeline) {
137 // The names comes in the order of which they are insert when using DefaultChannelPipeline
138 List<String> names = ctx.getPipeline().getNames();
139 for (int i = names.size() - 1; i >= 0; i--) {
140 ChannelHandler handler = ctx.getPipeline().get(names.get(i));
141 if (handler instanceof ChannelUpstreamHandler) {
142 // find the last handler
143 last = handler;
144 break;
145 }
146 }
147 }
148 if (this == last) {
149 logger.warn(
150 "EXCEPTION, please implement " + getClass().getName() +
151 ".exceptionCaught() for proper handling.", e.getCause());
152 }
153 ctx.sendUpstream(e);
154 }
155
156 /**
157 * Invoked when a {@link Channel} is open, but not bound nor connected.
158 * <br/>
159 *
160 * <strong>Be aware that this event is fired from within the Boss-Thread so you should not
161 * execute any heavy operation in there as it will block the dispatching to other workers!</strong>
162 */
163 public void channelOpen(
164 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
165 ctx.sendUpstream(e);
166 }
167
168 /**
169 * Invoked when a {@link Channel} is open and bound to a local address,
170 * but not connected.
171 * <br/>
172 *
173 * <strong>Be aware that this event is fired from within the Boss-Thread so you should not
174 * execute any heavy operation in there as it will block the dispatching to other workers!</strong>
175 */
176 public void channelBound(
177 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
178 ctx.sendUpstream(e);
179 }
180
181 /**
182 * Invoked when a {@link Channel} is open, bound to a local address, and
183 * connected to a remote address.
184 * <br/>
185 *
186 * <strong>Be aware that this event is fired from within the Boss-Thread so you should not
187 * execute any heavy operation in there as it will block the dispatching to other workers!</strong>
188 */
189 public void channelConnected(
190 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
191 ctx.sendUpstream(e);
192 }
193
194 /**
195 * Invoked when a {@link Channel}'s {@link Channel#getInterestOps() interestOps}
196 * was changed.
197 */
198 public void channelInterestChanged(
199 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
200 ctx.sendUpstream(e);
201 }
202
203 /**
204 * Invoked when a {@link Channel} was disconnected from its remote peer.
205 */
206 public void channelDisconnected(
207 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
208 ctx.sendUpstream(e);
209 }
210
211 /**
212 * Invoked when a {@link Channel} was unbound from the current local address.
213 */
214 public void channelUnbound(
215 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
216 ctx.sendUpstream(e);
217 }
218
219 /**
220 * Invoked when a {@link Channel} was closed and all its related resources
221 * were released.
222 */
223 public void channelClosed(
224 ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
225 ctx.sendUpstream(e);
226 }
227
228 /**
229 * Invoked when something was written into a {@link Channel}.
230 */
231 public void writeComplete(
232 ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception {
233 ctx.sendUpstream(e);
234 }
235
236 /**
237 * Invoked when a child {@link Channel} was open.
238 * (e.g. a server channel accepted a connection)
239 */
240 public void childChannelOpen(
241 ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
242 ctx.sendUpstream(e);
243 }
244
245 /**
246 * Invoked when a child {@link Channel} was closed.
247 * (e.g. the accepted connection was closed)
248 */
249 public void childChannelClosed(
250 ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
251 ctx.sendUpstream(e);
252 }
253 }