1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.channel;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.jboss.netty.logging.InternalLogger;
25 import org.jboss.netty.logging.InternalLoggerFactory;
26 import org.jboss.netty.util.internal.ConversionUtil;
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 return (T) ctx.getHandler();
288 }
289 }
290
291 public ChannelHandlerContext getContext(String name) {
292 if (name == null) {
293 throw new NullPointerException("name");
294 }
295 return name2ctx.get(name);
296 }
297
298 public ChannelHandlerContext getContext(ChannelHandler handler) {
299 if (handler == null) {
300 throw new NullPointerException("handler");
301 }
302 for (StaticChannelHandlerContext ctx: contexts) {
303 if (ctx.getHandler() == handler) {
304 return ctx;
305 }
306 }
307 return null;
308 }
309
310 public ChannelHandlerContext getContext(Class<? extends ChannelHandler> handlerType) {
311 if (handlerType == null) {
312 throw new NullPointerException("handlerType");
313 }
314 for (StaticChannelHandlerContext ctx: contexts) {
315 if (handlerType.isAssignableFrom(ctx.getHandler().getClass())) {
316 return ctx;
317 }
318 }
319 return null;
320 }
321
322 public List<String> getNames() {
323 List<String> list = new ArrayList<String>();
324 for (StaticChannelHandlerContext ctx: contexts) {
325 list.add(ctx.getName());
326 }
327 return list;
328 }
329
330 public Map<String, ChannelHandler> toMap() {
331 Map<String, ChannelHandler> map = new LinkedHashMap<String, ChannelHandler>();
332 for (StaticChannelHandlerContext ctx: contexts) {
333 map.put(ctx.getName(), ctx.getHandler());
334 }
335 return map;
336 }
337
338
339
340
341 @Override
342 public String toString() {
343 StringBuilder buf = new StringBuilder();
344 buf.append(getClass().getSimpleName());
345 buf.append('{');
346
347 for (StaticChannelHandlerContext ctx: contexts) {
348 buf.append('(');
349 buf.append(ctx.getName());
350 buf.append(" = ");
351 buf.append(ctx.getHandler().getClass().getName());
352 buf.append(')');
353 buf.append(", ");
354 }
355 buf.replace(buf.length() - 2, buf.length(), "}");
356 return buf.toString();
357 }
358
359 public void sendUpstream(ChannelEvent e) {
360 StaticChannelHandlerContext head = getActualUpstreamContext(0);
361 if (head == null) {
362 logger.warn(
363 "The pipeline contains no upstream handlers; discarding: " + e);
364 return;
365 }
366
367 sendUpstream(head, e);
368 }
369
370 void sendUpstream(StaticChannelHandlerContext ctx, ChannelEvent e) {
371 try {
372 ((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
373 } catch (Throwable t) {
374 notifyHandlerException(e, t);
375 }
376 }
377
378 public void sendDownstream(ChannelEvent e) {
379 StaticChannelHandlerContext tail = getActualDownstreamContext(lastIndex);
380 if (tail == null) {
381 try {
382 getSink().eventSunk(this, e);
383 return;
384 } catch (Throwable t) {
385 notifyHandlerException(e, t);
386 return;
387 }
388 }
389
390 sendDownstream(tail, e);
391 }
392
393 void sendDownstream(StaticChannelHandlerContext ctx, ChannelEvent e) {
394 if (e instanceof UpstreamMessageEvent) {
395 throw new IllegalArgumentException("cannot send an upstream event to downstream");
396 }
397
398 try {
399 ((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
400 } catch (Throwable t) {
401
402
403
404
405
406 e.getFuture().setFailure(t);
407 notifyHandlerException(e, t);
408 }
409 }
410
411 StaticChannelHandlerContext getActualUpstreamContext(int index) {
412 for (int i = index; i < contexts.length; i ++) {
413 StaticChannelHandlerContext ctx = contexts[i];
414 if (ctx.canHandleUpstream()) {
415 return ctx;
416 }
417 }
418 return null;
419 }
420
421 StaticChannelHandlerContext getActualDownstreamContext(int index) {
422 for (int i = index; i >= 0; i --) {
423 StaticChannelHandlerContext ctx = contexts[i];
424 if (ctx.canHandleDownstream()) {
425 return ctx;
426 }
427 }
428 return null;
429 }
430
431 protected void notifyHandlerException(ChannelEvent e, Throwable t) {
432 if (e instanceof ExceptionEvent) {
433 logger.warn(
434 "An exception was thrown by a user handler " +
435 "while handling an exception event (" + e + ')', t);
436 return;
437 }
438
439 ChannelPipelineException pe;
440 if (t instanceof ChannelPipelineException) {
441 pe = (ChannelPipelineException) t;
442 } else {
443 pe = new ChannelPipelineException(t);
444 }
445
446 try {
447 sink.exceptionCaught(this, e, pe);
448 } catch (Exception e1) {
449 logger.warn("An exception was thrown by an exception handler.", e1);
450 }
451 }
452
453 private final class StaticChannelHandlerContext implements ChannelHandlerContext {
454 private final int index;
455 private final String name;
456 private final ChannelHandler handler;
457 private final boolean canHandleUpstream;
458 private final boolean canHandleDownstream;
459 private volatile Object attachment;
460
461 StaticChannelHandlerContext(
462 int index, String name, ChannelHandler handler) {
463
464 if (name == null) {
465 throw new NullPointerException("name");
466 }
467 if (handler == null) {
468 throw new NullPointerException("handler");
469 }
470 canHandleUpstream = handler instanceof ChannelUpstreamHandler;
471 canHandleDownstream = handler instanceof ChannelDownstreamHandler;
472
473
474 if (!canHandleUpstream && !canHandleDownstream) {
475 throw new IllegalArgumentException(
476 "handler must be either " +
477 ChannelUpstreamHandler.class.getName() + " or " +
478 ChannelDownstreamHandler.class.getName() + '.');
479 }
480
481 this.index = index;
482 this.name = name;
483 this.handler = handler;
484 }
485
486 public Channel getChannel() {
487 return getPipeline().getChannel();
488 }
489
490 public ChannelPipeline getPipeline() {
491 return StaticChannelPipeline.this;
492 }
493
494 public boolean canHandleDownstream() {
495 return canHandleDownstream;
496 }
497
498 public boolean canHandleUpstream() {
499 return canHandleUpstream;
500 }
501
502 public ChannelHandler getHandler() {
503 return handler;
504 }
505
506 public String getName() {
507 return name;
508 }
509
510 public Object getAttachment() {
511 return attachment;
512 }
513
514 public void setAttachment(Object attachment) {
515 this.attachment = attachment;
516 }
517
518 public void sendDownstream(ChannelEvent e) {
519 StaticChannelHandlerContext prev = getActualDownstreamContext(index - 1);
520 if (prev == null) {
521 try {
522 getSink().eventSunk(StaticChannelPipeline.this, e);
523 } catch (Throwable t) {
524 notifyHandlerException(e, t);
525 }
526 } else {
527 StaticChannelPipeline.this.sendDownstream(prev, e);
528 }
529 }
530
531 public void sendUpstream(ChannelEvent e) {
532 StaticChannelHandlerContext next = getActualUpstreamContext(index + 1);
533 if (next != null) {
534 StaticChannelPipeline.this.sendUpstream(next, e);
535 }
536 }
537 }
538 }