1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.channel;
17
18 import org.jboss.netty.logging.InternalLogger;
19 import org.jboss.netty.logging.InternalLoggerFactory;
20 import org.jboss.netty.util.internal.ConversionUtil;
21
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27
28
29
30
31
32
33
34
35
36 @Deprecated
37 public class StaticChannelPipeline implements ChannelPipeline {
38
39
40 static final InternalLogger logger = InternalLoggerFactory.getInstance(StaticChannelPipeline.class);
41
42 private volatile Channel channel;
43 private volatile ChannelSink sink;
44 private final StaticChannelHandlerContext[] contexts;
45 private final int lastIndex;
46 private final Map<String, StaticChannelHandlerContext> name2ctx =
47 new HashMap<String, StaticChannelHandlerContext>(4);
48
49
50
51
52
53
54
55 public StaticChannelPipeline(ChannelHandler... handlers) {
56 if (handlers == null) {
57 throw new NullPointerException("handlers");
58 }
59 if (handlers.length == 0) {
60 throw new IllegalArgumentException("no handlers specified");
61 }
62
63
64 StaticChannelHandlerContext[] contexts =
65 new StaticChannelHandlerContext[handlers.length];
66 int nContexts;
67 for (nContexts = 0; nContexts < contexts.length; nContexts ++) {
68 ChannelHandler h = handlers[nContexts];
69 if (h == null) {
70 break;
71 }
72 }
73
74 if (nContexts == contexts.length) {
75 this.contexts = contexts;
76 lastIndex = contexts.length - 1;
77 } else {
78 this.contexts = contexts =
79 new StaticChannelHandlerContext[nContexts];
80 lastIndex = nContexts - 1;
81 }
82
83
84 for (int i = 0; i < nContexts; i ++) {
85 ChannelHandler h = handlers[i];
86 String name = ConversionUtil.toString(i);
87 StaticChannelHandlerContext ctx =
88 new StaticChannelHandlerContext(i, name, h);
89 contexts[i] = ctx;
90 name2ctx.put(name, ctx);
91 }
92
93 for (ChannelHandlerContext ctx: contexts) {
94 callBeforeAdd(ctx);
95 callAfterAdd(ctx);
96 }
97 }
98
99 public ChannelFuture execute(Runnable task) {
100 return getSink().execute(this, task);
101 }
102
103 public Channel getChannel() {
104 return channel;
105 }
106
107 public ChannelSink getSink() {
108 ChannelSink sink = this.sink;
109 if (sink == null) {
110 return DefaultChannelPipeline.discardingSink;
111 }
112 return sink;
113 }
114
115 public void attach(Channel channel, ChannelSink sink) {
116 if (channel == null) {
117 throw new NullPointerException("channel");
118 }
119 if (sink == null) {
120 throw new NullPointerException("sink");
121 }
122 if (this.channel != null || this.sink != null) {
123 throw new IllegalStateException("attached already");
124 }
125 this.channel = channel;
126 this.sink = sink;
127 }
128
129 public boolean isAttached() {
130 return sink != null;
131 }
132
133 public void addFirst(String name, ChannelHandler handler) {
134 throw new UnsupportedOperationException();
135 }
136
137 public void addLast(String name, ChannelHandler handler) {
138 throw new UnsupportedOperationException();
139 }
140
141 public void addBefore(String baseName, String name, ChannelHandler handler) {
142 throw new UnsupportedOperationException();
143 }
144
145 public void addAfter(String baseName, String name, ChannelHandler handler) {
146 throw new UnsupportedOperationException();
147 }
148
149 public void remove(ChannelHandler handler) {
150 throw new UnsupportedOperationException();
151 }
152
153 public ChannelHandler remove(String name) {
154 throw new UnsupportedOperationException();
155 }
156
157 public <T extends ChannelHandler> T remove(Class<T> handlerType) {
158 throw new UnsupportedOperationException();
159 }
160
161 public ChannelHandler removeFirst() {
162 throw new UnsupportedOperationException();
163 }
164
165 public ChannelHandler removeLast() {
166 throw new UnsupportedOperationException();
167 }
168
169 public void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) {
170 throw new UnsupportedOperationException();
171 }
172
173 public ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) {
174 throw new UnsupportedOperationException();
175 }
176
177 public <T extends ChannelHandler> T replace(
178 Class<T> oldHandlerType, String newName, ChannelHandler newHandler) {
179 throw new UnsupportedOperationException();
180 }
181
182 private static void callBeforeAdd(ChannelHandlerContext ctx) {
183 if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
184 return;
185 }
186
187 LifeCycleAwareChannelHandler h =
188 (LifeCycleAwareChannelHandler) ctx.getHandler();
189
190 try {
191 h.beforeAdd(ctx);
192 } catch (Throwable t) {
193 throw new ChannelHandlerLifeCycleException(
194 h.getClass().getName() +
195 ".beforeAdd() has thrown an exception; not adding.", t);
196 }
197 }
198
199 private static void callAfterAdd(ChannelHandlerContext ctx) {
200 if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
201 return;
202 }
203
204 LifeCycleAwareChannelHandler h =
205 (LifeCycleAwareChannelHandler) ctx.getHandler();
206
207 try {
208 h.afterAdd(ctx);
209 } catch (Throwable t) {
210 boolean removed = false;
211 try {
212 callBeforeRemove(ctx);
213 callAfterRemove(ctx);
214 removed = true;
215 } catch (Throwable t2) {
216 logger.warn("Failed to remove a handler: " + ctx.getName(), t2);
217 }
218
219 if (removed) {
220 throw new ChannelHandlerLifeCycleException(
221 h.getClass().getName() +
222 ".afterAdd() has thrown an exception; removed.", t);
223 } else {
224 throw new ChannelHandlerLifeCycleException(
225 h.getClass().getName() +
226 ".afterAdd() has thrown an exception; also failed to remove.", t);
227 }
228 }
229 }
230
231 private static void callBeforeRemove(ChannelHandlerContext ctx) {
232 if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
233 return;
234 }
235
236 LifeCycleAwareChannelHandler h =
237 (LifeCycleAwareChannelHandler) ctx.getHandler();
238
239 try {
240 h.beforeRemove(ctx);
241 } catch (Throwable t) {
242 throw new ChannelHandlerLifeCycleException(
243 h.getClass().getName() +
244 ".beforeRemove() has thrown an exception; not removing.", t);
245 }
246 }
247
248 private static void callAfterRemove(ChannelHandlerContext ctx) {
249 if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
250 return;
251 }
252
253 LifeCycleAwareChannelHandler h =
254 (LifeCycleAwareChannelHandler) ctx.getHandler();
255
256 try {
257 h.afterRemove(ctx);
258 } catch (Throwable t) {
259 throw new ChannelHandlerLifeCycleException(
260 h.getClass().getName() +
261 ".afterRemove() has thrown an exception.", t);
262 }
263 }
264
265 public ChannelHandler getFirst() {
266 return contexts[0].getHandler();
267 }
268
269 public ChannelHandler getLast() {
270 return contexts[contexts.length - 1].getHandler();
271 }
272
273 public ChannelHandler get(String name) {
274 StaticChannelHandlerContext ctx = name2ctx.get(name);
275 if (ctx == null) {
276 return null;
277 } else {
278 return ctx.getHandler();
279 }
280 }
281
282 public <T extends ChannelHandler> T get(Class<T> handlerType) {
283 ChannelHandlerContext ctx = getContext(handlerType);
284 if (ctx == null) {
285 return null;
286 } else {
287 @SuppressWarnings("unchecked")
288 T handler = (T) ctx.getHandler();
289 return handler;
290 }
291 }
292
293 public ChannelHandlerContext getContext(String name) {
294 if (name == null) {
295 throw new NullPointerException("name");
296 }
297 return name2ctx.get(name);
298 }
299
300 public ChannelHandlerContext getContext(ChannelHandler handler) {
301 if (handler == null) {
302 throw new NullPointerException("handler");
303 }
304 for (StaticChannelHandlerContext ctx: contexts) {
305 if (ctx.getHandler() == handler) {
306 return ctx;
307 }
308 }
309 return null;
310 }
311
312 public ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType) {
313 if (handlerType == null) {
314 throw new NullPointerException("handlerType");
315 }
316 for (StaticChannelHandlerContext ctx: contexts) {
317 if (handlerType.isAssignableFrom(ctx.getHandler().getClass())) {
318 return ctx;
319 }
320 }
321 return null;
322 }
323
324 public List<String> getNames() {
325 List<String> list = new ArrayList<String>();
326 for (StaticChannelHandlerContext ctx: contexts) {
327 list.add(ctx.getName());
328 }
329 return list;
330 }
331
332 public Map<String, ChannelHandler> toMap() {
333 Map<String, ChannelHandler> map = new LinkedHashMap<String, ChannelHandler>();
334 for (StaticChannelHandlerContext ctx: contexts) {
335 map.put(ctx.getName(), ctx.getHandler());
336 }
337 return map;
338 }
339
340
341
342
343 @Override
344 public String toString() {
345 StringBuilder buf = new StringBuilder();
346 buf.append(getClass().getSimpleName());
347 buf.append('{');
348
349 for (StaticChannelHandlerContext ctx: contexts) {
350 buf.append('(');
351 buf.append(ctx.getName());
352 buf.append(" = ");
353 buf.append(ctx.getHandler().getClass().getName());
354 buf.append(')');
355 buf.append(", ");
356 }
357 buf.replace(buf.length() - 2, buf.length(), "}");
358 return buf.toString();
359 }
360
361 public void sendUpstream(ChannelEvent e) {
362 StaticChannelHandlerContext head = getActualUpstreamContext(0);
363 if (head == null) {
364 logger.warn(
365 "The pipeline contains no upstream handlers; discarding: " + e);
366 return;
367 }
368
369 sendUpstream(head, e);
370 }
371
372 void sendUpstream(StaticChannelHandlerContext ctx, ChannelEvent e) {
373 try {
374 ((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
375 } catch (Throwable t) {
376 notifyHandlerException(e, t);
377 }
378 }
379
380 public void sendDownstream(ChannelEvent e) {
381 StaticChannelHandlerContext tail = getActualDownstreamContext(lastIndex);
382 if (tail == null) {
383 try {
384 getSink().eventSunk(this, e);
385 return;
386 } catch (Throwable t) {
387 notifyHandlerException(e, t);
388 return;
389 }
390 }
391
392 sendDownstream(tail, e);
393 }
394
395 void sendDownstream(StaticChannelHandlerContext ctx, ChannelEvent e) {
396 if (e instanceof UpstreamMessageEvent) {
397 throw new IllegalArgumentException("cannot send an upstream event to downstream");
398 }
399
400 try {
401 ((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
402 } catch (Throwable t) {
403
404
405
406
407
408 e.getFuture().setFailure(t);
409 notifyHandlerException(e, t);
410 }
411 }
412
413 private StaticChannelHandlerContext getActualUpstreamContext(int index) {
414 for (int i = index; i < contexts.length; i ++) {
415 StaticChannelHandlerContext ctx = contexts[i];
416 if (ctx.canHandleUpstream()) {
417 return ctx;
418 }
419 }
420 return null;
421 }
422
423 private StaticChannelHandlerContext getActualDownstreamContext(int index) {
424 for (int i = index; i >= 0; i --) {
425 StaticChannelHandlerContext ctx = contexts[i];
426 if (ctx.canHandleDownstream()) {
427 return ctx;
428 }
429 }
430 return null;
431 }
432
433 protected void notifyHandlerException(ChannelEvent e, Throwable t) {
434 if (e instanceof ExceptionEvent) {
435 logger.warn(
436 "An exception was thrown by a user handler " +
437 "while handling an exception event (" + e + ')', t);
438 return;
439 }
440
441 ChannelPipelineException pe;
442 if (t instanceof ChannelPipelineException) {
443 pe = (ChannelPipelineException) t;
444 } else {
445 pe = new ChannelPipelineException(t);
446 }
447
448 try {
449 sink.exceptionCaught(this, e, pe);
450 } catch (Exception e1) {
451 logger.warn("An exception was thrown by an exception handler.", e1);
452 }
453 }
454
455 private final class StaticChannelHandlerContext implements ChannelHandlerContext {
456 private final int index;
457 private final String name;
458 private final ChannelHandler handler;
459 private final boolean canHandleUpstream;
460 private final boolean canHandleDownstream;
461 private volatile Object attachment;
462
463 StaticChannelHandlerContext(
464 int index, String name, ChannelHandler handler) {
465
466 if (name == null) {
467 throw new NullPointerException("name");
468 }
469 if (handler == null) {
470 throw new NullPointerException("handler");
471 }
472 canHandleUpstream = handler instanceof ChannelUpstreamHandler;
473 canHandleDownstream = handler instanceof ChannelDownstreamHandler;
474
475 if (!canHandleUpstream && !canHandleDownstream) {
476 throw new IllegalArgumentException(
477 "handler must be either " +
478 ChannelUpstreamHandler.class.getName() + " or " +
479 ChannelDownstreamHandler.class.getName() + '.');
480 }
481
482 this.index = index;
483 this.name = name;
484 this.handler = handler;
485 }
486
487 public Channel getChannel() {
488 return getPipeline().getChannel();
489 }
490
491 public ChannelPipeline getPipeline() {
492 return StaticChannelPipeline.this;
493 }
494
495 public boolean canHandleDownstream() {
496 return canHandleDownstream;
497 }
498
499 public boolean canHandleUpstream() {
500 return canHandleUpstream;
501 }
502
503 public ChannelHandler getHandler() {
504 return handler;
505 }
506
507 public String getName() {
508 return name;
509 }
510
511 public Object getAttachment() {
512 return attachment;
513 }
514
515 public void setAttachment(Object attachment) {
516 this.attachment = attachment;
517 }
518
519 public void sendDownstream(ChannelEvent e) {
520 StaticChannelHandlerContext prev = getActualDownstreamContext(index - 1);
521 if (prev == null) {
522 try {
523 getSink().eventSunk(StaticChannelPipeline.this, e);
524 } catch (Throwable t) {
525 notifyHandlerException(e, t);
526 }
527 } else {
528 StaticChannelPipeline.this.sendDownstream(prev, e);
529 }
530 }
531
532 public void sendUpstream(ChannelEvent e) {
533 StaticChannelHandlerContext next = getActualUpstreamContext(index + 1);
534 if (next != null) {
535 StaticChannelPipeline.this.sendUpstream(next, e);
536 }
537 }
538 }
539 }