1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.core.filterchain;
21
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.mina.core.buffer.IoBuffer;
29 import org.apache.mina.core.filterchain.IoFilter.NextFilter;
30 import org.apache.mina.core.future.ConnectFuture;
31 import org.apache.mina.core.future.IoFuture;
32 import org.apache.mina.core.session.AbstractIoSession;
33 import org.apache.mina.core.session.AttributeKey;
34 import org.apache.mina.core.session.IdleStatus;
35 import org.apache.mina.core.session.IoSession;
36 import org.apache.mina.core.session.TrafficMask;
37 import org.apache.mina.core.write.WriteRequest;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41
42
43
44
45
46
47
48
49 public class DefaultIoFilterChain implements IoFilterChain {
50
51
52
53
54
55
56 public static final AttributeKey SESSION_CREATED_FUTURE = new AttributeKey(DefaultIoFilterChain.class, "connectFuture");
57
58 private final AbstractIoSession session;
59
60 private final Map<String, Entry> name2entry = new HashMap<String, Entry>();
61
62 private final EntryImpl head;
63
64 private final EntryImpl tail;
65
66 private final Logger logger = LoggerFactory.getLogger(getClass());
67
68 public DefaultIoFilterChain(AbstractIoSession session) {
69 if (session == null) {
70 throw new NullPointerException("session");
71 }
72
73 this.session = session;
74 head = new EntryImpl(null, null, "head", new HeadFilter());
75 tail = new EntryImpl(head, null, "tail", new TailFilter());
76 head.nextEntry = tail;
77 }
78
79 public IoSession getSession() {
80 return session;
81 }
82
83 public Entry getEntry(String name) {
84 Entry e = name2entry.get(name);
85 if (e == null) {
86 return null;
87 }
88 return e;
89 }
90
91 public Entry getEntry(IoFilter filter) {
92 EntryImpl e = head.nextEntry;
93 while (e != tail) {
94 if (e.getFilter() == filter) {
95 return e;
96 }
97 e = e.nextEntry;
98 }
99 return null;
100 }
101
102 public Entry getEntry(Class<? extends IoFilter> filterType) {
103 EntryImpl e = head.nextEntry;
104 while (e != tail) {
105 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
106 return e;
107 }
108 e = e.nextEntry;
109 }
110 return null;
111 }
112
113 public IoFilter get(String name) {
114 Entry e = getEntry(name);
115 if (e == null) {
116 return null;
117 }
118
119 return e.getFilter();
120 }
121
122 public IoFilter get(Class<? extends IoFilter> filterType) {
123 Entry e = getEntry(filterType);
124 if (e == null) {
125 return null;
126 }
127
128 return e.getFilter();
129 }
130
131 public NextFilter getNextFilter(String name) {
132 Entry e = getEntry(name);
133 if (e == null) {
134 return null;
135 }
136
137 return e.getNextFilter();
138 }
139
140 public NextFilter getNextFilter(IoFilter filter) {
141 Entry e = getEntry(filter);
142 if (e == null) {
143 return null;
144 }
145
146 return e.getNextFilter();
147 }
148
149 public NextFilter getNextFilter(Class<? extends IoFilter> filterType) {
150 Entry e = getEntry(filterType);
151 if (e == null) {
152 return null;
153 }
154
155 return e.getNextFilter();
156 }
157
158 public synchronized void addFirst(String name, IoFilter filter) {
159 checkAddable(name);
160 register(head, name, filter);
161 }
162
163 public synchronized void addLast(String name, IoFilter filter) {
164 checkAddable(name);
165 register(tail.prevEntry, name, filter);
166 }
167
168 public synchronized void addBefore(String baseName, String name,
169 IoFilter filter) {
170 EntryImpl baseEntry = checkOldName(baseName);
171 checkAddable(name);
172 register(baseEntry.prevEntry, name, filter);
173 }
174
175 public synchronized void addAfter(String baseName, String name,
176 IoFilter filter) {
177 EntryImpl baseEntry = checkOldName(baseName);
178 checkAddable(name);
179 register(baseEntry, name, filter);
180 }
181
182 public synchronized IoFilter remove(String name) {
183 EntryImpl entry = checkOldName(name);
184 deregister(entry);
185 return entry.getFilter();
186 }
187
188 public synchronized void remove(IoFilter filter) {
189 EntryImpl e = head.nextEntry;
190 while (e != tail) {
191 if (e.getFilter() == filter) {
192 deregister(e);
193 return;
194 }
195 e = e.nextEntry;
196 }
197 throw new IllegalArgumentException("Filter not found: "
198 + filter.getClass().getName());
199 }
200
201 public synchronized IoFilter remove(Class<? extends IoFilter> filterType) {
202 EntryImpl e = head.nextEntry;
203 while (e != tail) {
204 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
205 IoFilter oldFilter = e.getFilter();
206 deregister(e);
207 return oldFilter;
208 }
209 e = e.nextEntry;
210 }
211 throw new IllegalArgumentException("Filter not found: "
212 + filterType.getName());
213 }
214
215 public synchronized IoFilter replace(String name, IoFilter newFilter) {
216 EntryImpl entry = checkOldName(name);
217 IoFilter oldFilter = entry.getFilter();
218 entry.setFilter(newFilter);
219 return oldFilter;
220 }
221
222 public synchronized void replace(IoFilter oldFilter, IoFilter newFilter) {
223 EntryImpl e = head.nextEntry;
224 while (e != tail) {
225 if (e.getFilter() == oldFilter) {
226 e.setFilter(newFilter);
227 return;
228 }
229 e = e.nextEntry;
230 }
231 throw new IllegalArgumentException("Filter not found: "
232 + oldFilter.getClass().getName());
233 }
234
235 public synchronized IoFilter replace(Class<? extends IoFilter> oldFilterType,
236 IoFilter newFilter) {
237 EntryImpl e = head.nextEntry;
238 while (e != tail) {
239 if (oldFilterType.isAssignableFrom(e.getFilter().getClass())) {
240 IoFilter oldFilter = e.getFilter();
241 e.setFilter(newFilter);
242 return oldFilter;
243 }
244 e = e.nextEntry;
245 }
246 throw new IllegalArgumentException("Filter not found: "
247 + oldFilterType.getName());
248 }
249
250 public synchronized void clear() throws Exception {
251 Iterator<String> it = new ArrayList<String>(name2entry.keySet())
252 .iterator();
253 while (it.hasNext()) {
254 String name = it.next();
255 if (contains(name)) {
256 remove(name);
257 }
258 }
259 }
260
261 private void register(EntryImpl prevEntry, String name, IoFilter filter) {
262 EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry,
263 name, filter);
264
265 try {
266 filter.onPreAdd(this, name, newEntry.getNextFilter());
267 } catch (Exception e) {
268 throw new IoFilterLifeCycleException("onPreAdd(): " + name + ':'
269 + filter + " in " + getSession(), e);
270 }
271
272 prevEntry.nextEntry.prevEntry = newEntry;
273 prevEntry.nextEntry = newEntry;
274 name2entry.put(name, newEntry);
275
276 try {
277 filter.onPostAdd(this, name, newEntry.getNextFilter());
278 } catch (Exception e) {
279 deregister0(newEntry);
280 throw new IoFilterLifeCycleException("onPostAdd(): " + name + ':'
281 + filter + " in " + getSession(), e);
282 }
283 }
284
285 private void deregister(EntryImpl entry) {
286 IoFilter filter = entry.getFilter();
287
288 try {
289 filter.onPreRemove(this, entry.getName(), entry.getNextFilter());
290 } catch (Exception e) {
291 throw new IoFilterLifeCycleException("onPreRemove(): "
292 + entry.getName() + ':' + filter + " in " + getSession(), e);
293 }
294
295 deregister0(entry);
296
297 try {
298 filter.onPostRemove(this, entry.getName(), entry.getNextFilter());
299 } catch (Exception e) {
300 throw new IoFilterLifeCycleException("onPostRemove(): "
301 + entry.getName() + ':' + filter + " in " + getSession(), e);
302 }
303 }
304
305 private void deregister0(EntryImpl entry) {
306 EntryImpl prevEntry = entry.prevEntry;
307 EntryImpl nextEntry = entry.nextEntry;
308 prevEntry.nextEntry = nextEntry;
309 nextEntry.prevEntry = prevEntry;
310
311 name2entry.remove(entry.name);
312 }
313
314
315
316
317
318
319 private EntryImpl checkOldName(String baseName) {
320 EntryImpl e = (EntryImpl) name2entry.get(baseName);
321 if (e == null) {
322 throw new IllegalArgumentException("Filter not found:" + baseName);
323 }
324 return e;
325 }
326
327
328
329
330 private void checkAddable(String name) {
331 if (name2entry.containsKey(name)) {
332 throw new IllegalArgumentException(
333 "Other filter is using the same name '" + name + "'");
334 }
335 }
336
337 public void fireSessionCreated() {
338 Entry head = this.head;
339 callNextSessionCreated(head, session);
340 }
341
342 private void callNextSessionCreated(Entry entry, IoSession session) {
343 try {
344 entry.getFilter().sessionCreated(entry.getNextFilter(), session);
345 } catch (Throwable e) {
346 fireExceptionCaught(e);
347 }
348 }
349
350 public void fireSessionOpened() {
351 Entry head = this.head;
352 callNextSessionOpened(head, session);
353 }
354
355 private void callNextSessionOpened(Entry entry, IoSession session) {
356 try {
357 entry.getFilter().sessionOpened(entry.getNextFilter(), session);
358 } catch (Throwable e) {
359 fireExceptionCaught(e);
360 }
361 }
362
363 public void fireSessionClosed() {
364
365 try {
366 session.getCloseFuture().setClosed();
367 } catch (Throwable t) {
368 fireExceptionCaught(t);
369 }
370
371
372 Entry head = this.head;
373 callNextSessionClosed(head, session);
374 }
375
376 private void callNextSessionClosed(Entry entry, IoSession session) {
377 try {
378 entry.getFilter().sessionClosed(entry.getNextFilter(), session);
379 } catch (Throwable e) {
380 fireExceptionCaught(e);
381 }
382 }
383
384 public void fireSessionIdle(IdleStatus status) {
385 session.increaseIdleCount(status, System.currentTimeMillis());
386 Entry head = this.head;
387 callNextSessionIdle(head, session, status);
388 }
389
390 private void callNextSessionIdle(
391 Entry entry, IoSession session, IdleStatus status) {
392 try {
393 entry.getFilter().sessionIdle(entry.getNextFilter(), session,
394 status);
395 } catch (Throwable e) {
396 fireExceptionCaught(e);
397 }
398 }
399
400 public void fireMessageReceived(Object message) {
401 if (message instanceof IoBuffer) {
402 session.increaseReadBytes(
403 ((IoBuffer) message).remaining(),
404 System.currentTimeMillis());
405 }
406
407 Entry head = this.head;
408 callNextMessageReceived(head, session, message);
409 }
410
411 private void callNextMessageReceived(
412 Entry entry, IoSession session, Object message) {
413 try {
414 entry.getFilter().messageReceived(
415 entry.getNextFilter(), session, message);
416 } catch (Throwable e) {
417 fireExceptionCaught(e);
418 }
419 }
420
421 public void fireMessageSent(WriteRequest request) {
422 session.increaseWrittenMessages(request, System.currentTimeMillis());
423
424 try {
425 request.getFuture().setWritten();
426 } catch (Throwable t) {
427 fireExceptionCaught(t);
428 }
429
430 Entry head = this.head;
431 callNextMessageSent(head, session, request);
432 }
433
434 private void callNextMessageSent(Entry entry, IoSession session,
435 WriteRequest writeRequest) {
436 try {
437 entry.getFilter().messageSent(entry.getNextFilter(), session,
438 writeRequest);
439 } catch (Throwable e) {
440 fireExceptionCaught(e);
441 }
442 }
443
444 public void fireExceptionCaught(Throwable cause) {
445 Entry head = this.head;
446 callNextExceptionCaught(head, session, cause);
447 }
448
449 private void callNextExceptionCaught(Entry entry, IoSession session,
450 Throwable cause) {
451
452 ConnectFuture future = (ConnectFuture) session.removeAttribute(SESSION_CREATED_FUTURE);
453 if (future == null) {
454 try {
455 entry.getFilter().exceptionCaught(entry.getNextFilter(), session,
456 cause);
457 } catch (Throwable e) {
458 logger.warn("Unexpected exception from exceptionCaught handler.", e);
459 }
460 } else {
461
462
463 session.close();
464 future.setException(cause);
465 }
466 }
467
468 public void fireFilterWrite(WriteRequest writeRequest) {
469 Entry tail = this.tail;
470 callPreviousFilterWrite(tail, session, writeRequest);
471 }
472
473 private void callPreviousFilterWrite(Entry entry, IoSession session,
474 WriteRequest writeRequest) {
475 try {
476 entry.getFilter().filterWrite(entry.getNextFilter(), session,
477 writeRequest);
478 } catch (Throwable e) {
479 writeRequest.getFuture().setException(e);
480 fireExceptionCaught(e);
481 }
482 }
483
484 public void fireFilterClose() {
485 Entry tail = this.tail;
486 callPreviousFilterClose(tail, session);
487 }
488
489 private void callPreviousFilterClose(Entry entry, IoSession session) {
490 try {
491 entry.getFilter().filterClose(entry.getNextFilter(), session);
492 } catch (Throwable e) {
493 fireExceptionCaught(e);
494 }
495 }
496
497 public void fireFilterSetTrafficMask(TrafficMask trafficMask) {
498 Entry tail = this.tail;
499 callPreviousFilterSetTrafficMask(tail, session, trafficMask);
500 }
501
502 private void callPreviousFilterSetTrafficMask(Entry entry, IoSession session, TrafficMask trafficMask) {
503 try {
504 entry.getFilter().filterSetTrafficMask(entry.getNextFilter(), session, trafficMask);
505 } catch (Throwable e) {
506 fireExceptionCaught(e);
507 }
508 }
509
510 public List<Entry> getAll() {
511 List<Entry> list = new ArrayList<Entry>();
512 EntryImpl e = head.nextEntry;
513 while (e != tail) {
514 list.add(e);
515 e = e.nextEntry;
516 }
517
518 return list;
519 }
520
521 public List<Entry> getAllReversed() {
522 List<Entry> list = new ArrayList<Entry>();
523 EntryImpl e = tail.prevEntry;
524 while (e != head) {
525 list.add(e);
526 e = e.prevEntry;
527 }
528 return list;
529 }
530
531 public boolean contains(String name) {
532 return getEntry(name) != null;
533 }
534
535 public boolean contains(IoFilter filter) {
536 return getEntry(filter) != null;
537 }
538
539 public boolean contains(Class<? extends IoFilter> filterType) {
540 return getEntry(filterType) != null;
541 }
542
543 @Override
544 public String toString() {
545 StringBuffer buf = new StringBuffer();
546 buf.append("{ ");
547
548 boolean empty = true;
549
550 EntryImpl e = head.nextEntry;
551 while (e != tail) {
552 if (!empty) {
553 buf.append(", ");
554 } else {
555 empty = false;
556 }
557
558 buf.append('(');
559 buf.append(e.getName());
560 buf.append(':');
561 buf.append(e.getFilter());
562 buf.append(')');
563
564 e = e.nextEntry;
565 }
566
567 if (empty) {
568 buf.append("empty");
569 }
570
571 buf.append(" }");
572
573 return buf.toString();
574 }
575
576 @Override
577 protected void finalize() throws Throwable {
578 try {
579 this.clear();
580 } finally {
581 super.finalize();
582 }
583 }
584
585 private class HeadFilter extends IoFilterAdapter {
586 @Override
587 public void sessionCreated(NextFilter nextFilter, IoSession session) {
588 nextFilter.sessionCreated(session);
589 }
590
591 @Override
592 public void sessionOpened(NextFilter nextFilter, IoSession session) {
593 nextFilter.sessionOpened(session);
594 }
595
596 @Override
597 public void sessionClosed(NextFilter nextFilter, IoSession session) {
598 nextFilter.sessionClosed(session);
599 }
600
601 @Override
602 public void sessionIdle(NextFilter nextFilter, IoSession session,
603 IdleStatus status) {
604 nextFilter.sessionIdle(session, status);
605 }
606
607 @Override
608 public void exceptionCaught(NextFilter nextFilter, IoSession session,
609 Throwable cause) {
610 nextFilter.exceptionCaught(session, cause);
611 }
612
613 @Override
614 public void messageReceived(NextFilter nextFilter, IoSession session,
615 Object message) {
616 nextFilter.messageReceived(session, message);
617 }
618
619 @Override
620 public void messageSent(NextFilter nextFilter, IoSession session,
621 WriteRequest writeRequest) {
622 nextFilter.messageSent(session, writeRequest);
623 }
624
625 @SuppressWarnings("unchecked")
626 @Override
627 public void filterWrite(NextFilter nextFilter, IoSession session,
628 WriteRequest writeRequest) throws Exception {
629
630 AbstractIoSession s = (AbstractIoSession) session;
631
632
633 if (writeRequest.getMessage() instanceof IoBuffer) {
634 IoBuffer buffer = (IoBuffer) writeRequest.getMessage();
635
636
637
638 buffer.mark();
639 int remaining = buffer.remaining();
640 if (remaining == 0) {
641
642
643 s.increaseScheduledWriteMessages();
644 } else {
645 s.increaseScheduledWriteBytes(buffer.remaining());
646 }
647 } else {
648 s.increaseScheduledWriteMessages();
649 }
650
651 s.getWriteRequestQueue().offer(s, writeRequest);
652 if (s.getTrafficMask().isWritable()) {
653 s.getProcessor().flush(s);
654 }
655 }
656
657 @SuppressWarnings("unchecked")
658 @Override
659 public void filterClose(NextFilter nextFilter, IoSession session)
660 throws Exception {
661 ((AbstractIoSession) session).getProcessor().remove(session);
662 }
663
664 @SuppressWarnings("unchecked")
665 @Override
666 public void filterSetTrafficMask(NextFilter nextFilter,
667 IoSession session, TrafficMask trafficMask) throws Exception {
668 AbstractIoSession s = (AbstractIoSession) session;
669 s.setTrafficMaskNow(trafficMask);
670 s.getProcessor().updateTrafficMask(s);
671 }
672
673 }
674
675 private static class TailFilter extends IoFilterAdapter {
676 @Override
677 public void sessionCreated(NextFilter nextFilter, IoSession session)
678 throws Exception {
679 try {
680 session.getHandler().sessionCreated(session);
681 } finally {
682
683 ConnectFuture future = (ConnectFuture) session.removeAttribute(SESSION_CREATED_FUTURE);
684 if (future != null) {
685 future.setSession(session);
686 }
687 }
688 }
689
690 @Override
691 public void sessionOpened(NextFilter nextFilter, IoSession session)
692 throws Exception {
693 session.getHandler().sessionOpened(session);
694 }
695
696 @Override
697 public void sessionClosed(NextFilter nextFilter, IoSession session)
698 throws Exception {
699 AbstractIoSession s = (AbstractIoSession) session;
700 try {
701 s.getHandler().sessionClosed(session);
702 } finally {
703 try {
704 s.getWriteRequestQueue().dispose(session);
705 } finally {
706 try {
707 s.getAttributeMap().dispose(session);
708 } finally {
709 try {
710
711 session.getFilterChain().clear();
712 } finally {
713 if (s.getConfig().isUseReadOperation()) {
714 s.offerClosedReadFuture();
715 }
716 }
717 }
718 }
719 }
720 }
721
722 @Override
723 public void sessionIdle(NextFilter nextFilter, IoSession session,
724 IdleStatus status) throws Exception {
725 session.getHandler().sessionIdle(session, status);
726 }
727
728 @Override
729 public void exceptionCaught(NextFilter nextFilter, IoSession session,
730 Throwable cause) throws Exception {
731 AbstractIoSession s = (AbstractIoSession) session;
732 try {
733 s.getHandler().exceptionCaught(s, cause);
734 } finally {
735 if (s.getConfig().isUseReadOperation()) {
736 s.offerFailedReadFuture(cause);
737 }
738 }
739 }
740
741 @Override
742 public void messageReceived(NextFilter nextFilter, IoSession session,
743 Object message) throws Exception {
744 AbstractIoSession s = (AbstractIoSession) session;
745 if (!(message instanceof IoBuffer)) {
746 s.increaseReadMessages(System.currentTimeMillis());
747 } else if (!((IoBuffer) message).hasRemaining()) {
748 s.increaseReadMessages(System.currentTimeMillis());
749 }
750
751 try {
752 session.getHandler().messageReceived(s, message);
753 } finally {
754 if (s.getConfig().isUseReadOperation()) {
755 s.offerReadFuture(message);
756 }
757 }
758 }
759
760 @Override
761 public void messageSent(NextFilter nextFilter, IoSession session,
762 WriteRequest writeRequest) throws Exception {
763 session.getHandler()
764 .messageSent(session, writeRequest.getMessage());
765 }
766
767 @Override
768 public void filterWrite(NextFilter nextFilter, IoSession session,
769 WriteRequest writeRequest) throws Exception {
770 nextFilter.filterWrite(session, writeRequest);
771 }
772
773 @Override
774 public void filterClose(NextFilter nextFilter, IoSession session)
775 throws Exception {
776 nextFilter.filterClose(session);
777 }
778 }
779
780 private class EntryImpl implements Entry {
781 private EntryImpl prevEntry;
782
783 private EntryImpl nextEntry;
784
785 private final String name;
786
787 private IoFilter filter;
788
789 private final NextFilter nextFilter;
790
791 private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry,
792 String name, IoFilter filter) {
793 if (filter == null) {
794 throw new NullPointerException("filter");
795 }
796 if (name == null) {
797 throw new NullPointerException("name");
798 }
799
800 this.prevEntry = prevEntry;
801 this.nextEntry = nextEntry;
802 this.name = name;
803 this.filter = filter;
804 this.nextFilter = new NextFilter() {
805 public void sessionCreated(IoSession session) {
806 Entry nextEntry = EntryImpl.this.nextEntry;
807 callNextSessionCreated(nextEntry, session);
808 }
809
810 public void sessionOpened(IoSession session) {
811 Entry nextEntry = EntryImpl.this.nextEntry;
812 callNextSessionOpened(nextEntry, session);
813 }
814
815 public void sessionClosed(IoSession session) {
816 Entry nextEntry = EntryImpl.this.nextEntry;
817 callNextSessionClosed(nextEntry, session);
818 }
819
820 public void sessionIdle(IoSession session, IdleStatus status) {
821 Entry nextEntry = EntryImpl.this.nextEntry;
822 callNextSessionIdle(nextEntry, session, status);
823 }
824
825 public void exceptionCaught(IoSession session, Throwable cause) {
826 Entry nextEntry = EntryImpl.this.nextEntry;
827 callNextExceptionCaught(nextEntry, session, cause);
828 }
829
830 public void messageReceived(IoSession session, Object message) {
831 Entry nextEntry = EntryImpl.this.nextEntry;
832 callNextMessageReceived(nextEntry, session, message);
833 }
834
835 public void messageSent(IoSession session,
836 WriteRequest writeRequest) {
837 Entry nextEntry = EntryImpl.this.nextEntry;
838 callNextMessageSent(nextEntry, session, writeRequest);
839 }
840
841 public void filterWrite(IoSession session,
842 WriteRequest writeRequest) {
843 Entry nextEntry = EntryImpl.this.prevEntry;
844 callPreviousFilterWrite(nextEntry, session, writeRequest);
845 }
846
847 public void filterClose(IoSession session) {
848 Entry nextEntry = EntryImpl.this.prevEntry;
849 callPreviousFilterClose(nextEntry, session);
850 }
851
852 public void filterSetTrafficMask(IoSession session,
853 TrafficMask trafficMask) {
854 Entry nextEntry = EntryImpl.this.prevEntry;
855 callPreviousFilterSetTrafficMask(nextEntry, session, trafficMask);
856 }
857 };
858 }
859
860 public String getName() {
861 return name;
862 }
863
864 public IoFilter getFilter() {
865 return filter;
866 }
867
868 private void setFilter(IoFilter filter) {
869 if (filter == null) {
870 throw new NullPointerException("filter");
871 }
872
873 this.filter = filter;
874 }
875
876 public NextFilter getNextFilter() {
877 return nextFilter;
878 }
879
880 @Override
881 public String toString() {
882 return "(" + getName() + ':' + filter + ')';
883 }
884
885 public void addAfter(String name, IoFilter filter) {
886 DefaultIoFilterChain.this.addAfter(getName(), name, filter);
887 }
888
889 public void addBefore(String name, IoFilter filter) {
890 DefaultIoFilterChain.this.addBefore(getName(), name, filter);
891 }
892
893 public void remove() {
894 DefaultIoFilterChain.this.remove(getName());
895 }
896
897 public void replace(IoFilter newFilter) {
898 DefaultIoFilterChain.this.replace(getName(), newFilter);
899 }
900 }
901 }