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