KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > mina > common > support > AbstractIoFilterChain


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  *
19  */

20 package org.apache.mina.common.support;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import org.apache.mina.common.ConnectFuture;
29 import org.apache.mina.common.IdleStatus;
30 import org.apache.mina.common.IoFilter;
31 import org.apache.mina.common.IoFilterAdapter;
32 import org.apache.mina.common.IoFilterChain;
33 import org.apache.mina.common.IoFilterLifeCycleException;
34 import org.apache.mina.common.IoSession;
35 import org.apache.mina.common.IoFilter.NextFilter;
36 import org.apache.mina.common.IoFilter.WriteRequest;
37 import org.apache.mina.util.ByteBufferUtil;
38 import org.apache.mina.util.SessionLog;
39
40 /**
41  * An abstract implementation of {@link IoFilterChain} that provides
42  * common operations for developers to implement their own transport layer.
43  * <p>
44  * The only method a developer should implement is
45  * {@link #doWrite(IoSession, IoFilter.WriteRequest)}. This method is invoked
46  * when filter chain is evaluated for
47  * {@link IoFilter#filterWrite(NextFilter, IoSession, IoFilter.WriteRequest)} and
48  * finally to be written out.
49  *
50  * @author The Apache Directory Project (mina-dev@directory.apache.org)
51  * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13 7월 2007) $
52  */

53 public abstract class AbstractIoFilterChain implements IoFilterChain {
54     /**
55      * A session attribute that stores a {@link ConnectFuture} related with
56      * the {@link IoSession}. {@link AbstractIoFilterChain} clears this
57      * attribute and notifies the future when {@link #fireSessionOpened(IoSession)}
58      * or {@link #fireExceptionCaught(IoSession, Throwable)} is invoked
59      */

60     public static final String JavaDoc CONNECT_FUTURE = AbstractIoFilterChain.class
61             .getName()
62             + ".connectFuture";
63
64     private final IoSession session;
65
66     private final Map JavaDoc<String JavaDoc, Entry> name2entry = new HashMap JavaDoc<String JavaDoc, Entry>();
67
68     private final EntryImpl head;
69
70     private final EntryImpl tail;
71
72     protected AbstractIoFilterChain(IoSession session) {
73         if (session == null) {
74             throw new NullPointerException JavaDoc("session");
75         }
76
77         this.session = session;
78         head = new EntryImpl(null, null, "head", new HeadFilter());
79         tail = new EntryImpl(head, null, "tail", new TailFilter());
80         head.nextEntry = tail;
81     }
82
83     public IoSession getSession() {
84         return session;
85     }
86
87     public Entry getEntry(String JavaDoc name) {
88         Entry e = name2entry.get(name);
89         if (e == null) {
90             return null;
91         }
92         return e;
93     }
94
95     public IoFilter get(String JavaDoc name) {
96         Entry e = getEntry(name);
97         if (e == null) {
98             return null;
99         }
100
101         return e.getFilter();
102     }
103
104     public NextFilter getNextFilter(String JavaDoc name) {
105         Entry e = getEntry(name);
106         if (e == null) {
107             return null;
108         }
109
110         return e.getNextFilter();
111     }
112
113     public synchronized void addFirst(String JavaDoc name, IoFilter filter) {
114         checkAddable(name);
115         register(head, name, filter);
116     }
117
118     public synchronized void addLast(String JavaDoc name, IoFilter filter) {
119         checkAddable(name);
120         register(tail.prevEntry, name, filter);
121     }
122
123     public synchronized void addBefore(String JavaDoc baseName, String JavaDoc name,
124             IoFilter filter) {
125         EntryImpl baseEntry = checkOldName(baseName);
126         checkAddable(name);
127         register(baseEntry.prevEntry, name, filter);
128     }
129
130     public synchronized void addAfter(String JavaDoc baseName, String JavaDoc name,
131             IoFilter filter) {
132         EntryImpl baseEntry = checkOldName(baseName);
133         checkAddable(name);
134         register(baseEntry, name, filter);
135     }
136
137     public synchronized IoFilter remove(String JavaDoc name) {
138         EntryImpl entry = checkOldName(name);
139         deregister(entry);
140         return entry.getFilter();
141     }
142
143     public synchronized void clear() throws Exception JavaDoc {
144         Iterator JavaDoc<String JavaDoc> it = new ArrayList JavaDoc<String JavaDoc>(name2entry.keySet())
145                 .iterator();
146         while (it.hasNext()) {
147             this.remove(it.next());
148         }
149     }
150
151     private void register(EntryImpl prevEntry, String JavaDoc name, IoFilter filter) {
152         EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry,
153                 name, filter);
154
155         try {
156             filter.onPreAdd(this, name, newEntry.getNextFilter());
157         } catch (Exception JavaDoc e) {
158             throw new IoFilterLifeCycleException("onPreAdd(): " + name + ':'
159                     + filter + " in " + getSession(), e);
160         }
161
162         prevEntry.nextEntry.prevEntry = newEntry;
163         prevEntry.nextEntry = newEntry;
164         name2entry.put(name, newEntry);
165
166         try {
167             filter.onPostAdd(this, name, newEntry.getNextFilter());
168         } catch (Exception JavaDoc e) {
169             deregister0(newEntry);
170             throw new IoFilterLifeCycleException("onPostAdd(): " + name + ':'
171                     + filter + " in " + getSession(), e);
172         }
173     }
174
175     private void deregister(EntryImpl entry) {
176         IoFilter filter = entry.getFilter();
177
178         try {
179             filter.onPreRemove(this, entry.getName(), entry.getNextFilter());
180         } catch (Exception JavaDoc e) {
181             throw new IoFilterLifeCycleException("onPreRemove(): "
182                     + entry.getName() + ':' + filter + " in " + getSession(), e);
183         }
184
185         deregister0(entry);
186
187         try {
188             filter.onPostRemove(this, entry.getName(), entry.getNextFilter());
189         } catch (Exception JavaDoc e) {
190             throw new IoFilterLifeCycleException("onPostRemove(): "
191                     + entry.getName() + ':' + filter + " in " + getSession(), e);
192         }
193     }
194
195     private void deregister0(EntryImpl entry) {
196         EntryImpl prevEntry = entry.prevEntry;
197         EntryImpl nextEntry = entry.nextEntry;
198         prevEntry.nextEntry = nextEntry;
199         nextEntry.prevEntry = prevEntry;
200
201         name2entry.remove(entry.name);
202     }
203
204     /**
205      * Throws an exception when the specified filter name is not registered in this chain.
206      *
207      * @return An filter entry with the specified name.
208      */

209     private EntryImpl checkOldName(String JavaDoc baseName) {
210         EntryImpl e = (EntryImpl) name2entry.get(baseName);
211         if (e == null) {
212             throw new IllegalArgumentException JavaDoc("Unknown filter name:"
213                     + baseName);
214         }
215         return e;
216     }
217
218     /**
219      * Checks the specified filter name is already taken and throws an exception if already taken.
220      */

221     private void checkAddable(String JavaDoc name) {
222         if (name2entry.containsKey(name)) {
223             throw new IllegalArgumentException JavaDoc(
224                     "Other filter is using the same name '" + name + "'");
225         }
226     }
227
228     public void fireSessionCreated(IoSession session) {
229         Entry head = this.head;
230         callNextSessionCreated(head, session);
231     }
232
233     private void callNextSessionCreated(Entry entry, IoSession session) {
234         try {
235             entry.getFilter().sessionCreated(entry.getNextFilter(), session);
236         } catch (Throwable JavaDoc e) {
237             fireExceptionCaught(session, e);
238         }
239     }
240
241     public void fireSessionOpened(IoSession session) {
242         Entry head = this.head;
243         callNextSessionOpened(head, session);
244     }
245
246     private void callNextSessionOpened(Entry entry, IoSession session) {
247         try {
248             entry.getFilter().sessionOpened(entry.getNextFilter(), session);
249         } catch (Throwable JavaDoc e) {
250             fireExceptionCaught(session, e);
251         }
252     }
253
254     public void fireSessionClosed(IoSession session) {
255         // Update future.
256
try {
257             session.getCloseFuture().setClosed();
258         } catch (Throwable JavaDoc t) {
259             fireExceptionCaught(session, t);
260         }
261
262         // And start the chain.
263
Entry head = this.head;
264         callNextSessionClosed(head, session);
265     }
266
267     private void callNextSessionClosed(Entry entry, IoSession session) {
268         try {
269             entry.getFilter().sessionClosed(entry.getNextFilter(), session);
270
271         } catch (Throwable JavaDoc e) {
272             fireExceptionCaught(session, e);
273         }
274     }
275
276     public void fireSessionIdle(IoSession session, IdleStatus status) {
277         Entry head = this.head;
278         callNextSessionIdle(head, session, status);
279     }
280
281     private void callNextSessionIdle(Entry entry, IoSession session,
282             IdleStatus status) {
283         try {
284             entry.getFilter().sessionIdle(entry.getNextFilter(), session,
285                     status);
286         } catch (Throwable JavaDoc e) {
287             fireExceptionCaught(session, e);
288         }
289     }
290
291     public void fireMessageReceived(IoSession session, Object JavaDoc message) {
292         Entry head = this.head;
293         callNextMessageReceived(head, session, message);
294     }
295
296     private void callNextMessageReceived(Entry entry, IoSession session,
297             Object JavaDoc message) {
298         try {
299             entry.getFilter().messageReceived(entry.getNextFilter(), session,
300                     message);
301         } catch (Throwable JavaDoc e) {
302             fireExceptionCaught(session, e);
303         }
304     }
305
306     public void fireMessageSent(IoSession session, WriteRequest request) {
307         try {
308             request.getFuture().setWritten(true);
309         } catch (Throwable JavaDoc t) {
310             fireExceptionCaught(session, t);
311         }
312
313         Entry head = this.head;
314         callNextMessageSent(head, session, request.getMessage());
315     }
316
317     private void callNextMessageSent(Entry entry, IoSession session,
318             Object JavaDoc message) {
319         try {
320             entry.getFilter().messageSent(entry.getNextFilter(), session,
321                     message);
322         } catch (Throwable JavaDoc e) {
323             fireExceptionCaught(session, e);
324         }
325     }
326
327     public void fireExceptionCaught(IoSession session, Throwable JavaDoc cause) {
328         // Notify the related ConnectFuture
329
// if the session is created from SocketConnector.
330
ConnectFuture future = (ConnectFuture) session
331                 .removeAttribute(CONNECT_FUTURE);
332         if (future == null) {
333             Entry head = this.head;
334             callNextExceptionCaught(head, session, cause);
335         } else {
336             // Please note that this place is not the only place that
337
// calls ConnectFuture.setException().
338
future.setException(cause);
339         }
340     }
341
342     private void callNextExceptionCaught(Entry entry, IoSession session,
343             Throwable JavaDoc cause) {
344         try {
345             entry.getFilter().exceptionCaught(entry.getNextFilter(), session,
346                     cause);
347         } catch (Throwable JavaDoc e) {
348             SessionLog.warn(session,
349                     "Unexpected exception from exceptionCaught handler.", e);
350         }
351     }
352
353     public void fireFilterWrite(IoSession session, WriteRequest writeRequest) {
354         Entry tail = this.tail;
355         callPreviousFilterWrite(tail, session, writeRequest);
356     }
357
358     private void callPreviousFilterWrite(Entry entry, IoSession session,
359             WriteRequest writeRequest) {
360         try {
361             entry.getFilter().filterWrite(entry.getNextFilter(), session,
362                     writeRequest);
363         } catch (Throwable JavaDoc e) {
364             fireExceptionCaught(session, e);
365         }
366     }
367
368     public void fireFilterClose(IoSession session) {
369         Entry tail = this.tail;
370         callPreviousFilterClose(tail, session);
371     }
372
373     private void callPreviousFilterClose(Entry entry, IoSession session) {
374         try {
375             entry.getFilter().filterClose(entry.getNextFilter(), session);
376         } catch (Throwable JavaDoc e) {
377             fireExceptionCaught(session, e);
378         }
379     }
380
381     public List JavaDoc<Entry> getAll() {
382         List JavaDoc<Entry> list = new ArrayList JavaDoc<Entry>();
383         EntryImpl e = head.nextEntry;
384         while (e != tail) {
385             list.add(e);
386             e = e.nextEntry;
387         }
388
389         return list;
390     }
391
392     public List JavaDoc<Entry> getAllReversed() {
393         List JavaDoc<Entry> list = new ArrayList JavaDoc<Entry>();
394         EntryImpl e = tail.prevEntry;
395         while (e != head) {
396             list.add(e);
397             e = e.prevEntry;
398         }
399         return list;
400     }
401
402     public boolean contains(String JavaDoc name) {
403         return getEntry(name) != null;
404     }
405
406     public boolean contains(IoFilter filter) {
407         EntryImpl e = head.nextEntry;
408         while (e != tail) {
409             if (e.getFilter() == filter) {
410                 return true;
411             }
412             e = e.nextEntry;
413         }
414         return false;
415     }
416
417     public boolean contains(Class JavaDoc<? extends IoFilter> filterType) {
418         EntryImpl e = head.nextEntry;
419         while (e != tail) {
420             if (filterType.isAssignableFrom(e.getFilter().getClass())) {
421                 return true;
422             }
423             e = e.nextEntry;
424         }
425         return false;
426     }
427
428     public String JavaDoc toString() {
429         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
430         buf.append("{ ");
431
432         boolean empty = true;
433
434         EntryImpl e = head.nextEntry;
435         while (e != tail) {
436             if (!empty) {
437                 buf.append(", ");
438             } else {
439                 empty = false;
440             }
441
442             buf.append('(');
443             buf.append(e.getName());
444             buf.append(':');
445             buf.append(e.getFilter());
446             buf.append(')');
447
448             e = e.nextEntry;
449         }
450
451         if (empty) {
452             buf.append("empty");
453         }
454
455         buf.append(" }");
456
457         return buf.toString();
458     }
459
460     protected void finalize() throws Throwable JavaDoc {
461         try {
462             this.clear();
463         } finally {
464             super.finalize();
465         }
466     }
467
468     protected abstract void doWrite(IoSession session, WriteRequest writeRequest)
469             throws Exception JavaDoc;
470
471     protected abstract void doClose(IoSession session) throws Exception JavaDoc;
472
473     private class HeadFilter extends IoFilterAdapter {
474         public void sessionCreated(NextFilter nextFilter, IoSession session) {
475             nextFilter.sessionCreated(session);
476         }
477
478         public void sessionOpened(NextFilter nextFilter, IoSession session) {
479             nextFilter.sessionOpened(session);
480         }
481
482         public void sessionClosed(NextFilter nextFilter, IoSession session) {
483             nextFilter.sessionClosed(session);
484         }
485
486         public void sessionIdle(NextFilter nextFilter, IoSession session,
487                 IdleStatus status) {
488             nextFilter.sessionIdle(session, status);
489         }
490
491         public void exceptionCaught(NextFilter nextFilter, IoSession session,
492                 Throwable JavaDoc cause) {
493             nextFilter.exceptionCaught(session, cause);
494         }
495
496         public void messageReceived(NextFilter nextFilter, IoSession session,
497                 Object JavaDoc message) {
498             nextFilter.messageReceived(session, message);
499         }
500
501         public void messageSent(NextFilter nextFilter, IoSession session,
502                 Object JavaDoc message) {
503             nextFilter.messageSent(session, message);
504         }
505
506         public void filterWrite(NextFilter nextFilter, IoSession session,
507                 WriteRequest writeRequest) throws Exception JavaDoc {
508             if (session.getTransportType().getEnvelopeType().isAssignableFrom(
509                     writeRequest.getMessage().getClass())) {
510                 doWrite(session, writeRequest);
511             } else {
512                 throw new IllegalStateException JavaDoc(
513                         "Write requests must be transformed to "
514                                 + session.getTransportType().getEnvelopeType()
515                                 + ": " + writeRequest);
516             }
517         }
518
519         public void filterClose(NextFilter nextFilter, IoSession session)
520                 throws Exception JavaDoc {
521             doClose(session);
522         }
523     }
524
525     private static class TailFilter extends IoFilterAdapter {
526         public void sessionCreated(NextFilter nextFilter, IoSession session)
527                 throws Exception JavaDoc {
528             session.getHandler().sessionCreated(session);
529         }
530
531         public void sessionOpened(NextFilter nextFilter, IoSession session)
532                 throws Exception JavaDoc {
533             try {
534                 session.getHandler().sessionOpened(session);
535             } finally {
536                 // Notify the related ConnectFuture
537
// if the session is created from SocketConnector.
538
ConnectFuture future = (ConnectFuture) session
539                         .removeAttribute(CONNECT_FUTURE);
540                 if (future != null) {
541                     future.setSession(session);
542                 }
543             }
544         }
545
546         public void sessionClosed(NextFilter nextFilter, IoSession session)
547                 throws Exception JavaDoc {
548             try {
549                 session.getHandler().sessionClosed(session);
550             } finally {
551                 // Remove all filters.
552
session.getFilterChain().clear();
553             }
554         }
555
556         public void sessionIdle(NextFilter nextFilter, IoSession session,
557                 IdleStatus status) throws Exception JavaDoc {
558             session.getHandler().sessionIdle(session, status);
559         }
560
561         public void exceptionCaught(NextFilter nextFilter, IoSession session,
562                 Throwable JavaDoc cause) throws Exception JavaDoc {
563             session.getHandler().exceptionCaught(session, cause);
564         }
565
566         public void messageReceived(NextFilter nextFilter, IoSession session,
567                 Object JavaDoc message) throws Exception JavaDoc {
568             try {
569                 session.getHandler().messageReceived(session, message);
570             } finally {
571                 ByteBufferUtil.releaseIfPossible(message);
572             }
573         }
574
575         public void messageSent(NextFilter nextFilter, IoSession session,
576                 Object JavaDoc message) throws Exception JavaDoc {
577             try {
578                 session.getHandler().messageSent(session, message);
579             } finally {
580                 ByteBufferUtil.releaseIfPossible(message);
581             }
582         }
583
584         public void filterWrite(NextFilter nextFilter, IoSession session,
585                 WriteRequest writeRequest) throws Exception JavaDoc {
586             nextFilter.filterWrite(session, writeRequest);
587         }
588
589         public void filterClose(NextFilter nextFilter, IoSession session)
590                 throws Exception JavaDoc {
591             nextFilter.filterClose(session);
592         }
593     }
594
595     private class EntryImpl implements Entry {
596         private EntryImpl prevEntry;
597
598         private EntryImpl nextEntry;
599
600         private final String JavaDoc name;
601
602         private final IoFilter filter;
603
604         private final NextFilter nextFilter;
605
606         private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry,
607                 String JavaDoc name, IoFilter filter) {
608             if (filter == null) {
609                 throw new NullPointerException JavaDoc("filter");
610             }
611             if (name == null) {
612                 throw new NullPointerException JavaDoc("name");
613             }
614
615             this.prevEntry = prevEntry;
616             this.nextEntry = nextEntry;
617             this.name = name;
618             this.filter = filter;
619             this.nextFilter = new NextFilter() {
620                 public void sessionCreated(IoSession session) {
621                     Entry nextEntry = EntryImpl.this.nextEntry;
622                     callNextSessionCreated(nextEntry, session);
623                 }
624
625                 public void sessionOpened(IoSession session) {
626                     Entry nextEntry = EntryImpl.this.nextEntry;
627                     callNextSessionOpened(nextEntry, session);
628                 }
629
630                 public void sessionClosed(IoSession session) {
631                     Entry nextEntry = EntryImpl.this.nextEntry;
632                     callNextSessionClosed(nextEntry, session);
633                 }
634
635                 public void sessionIdle(IoSession session, IdleStatus status) {
636                     Entry nextEntry = EntryImpl.this.nextEntry;
637                     callNextSessionIdle(nextEntry, session, status);
638                 }
639
640                 public void exceptionCaught(IoSession session, Throwable JavaDoc cause) {
641                     Entry nextEntry = EntryImpl.this.nextEntry;
642                     callNextExceptionCaught(nextEntry, session, cause);
643                 }
644
645                 public void messageReceived(IoSession session, Object JavaDoc message) {
646                     Entry nextEntry = EntryImpl.this.nextEntry;
647                     callNextMessageReceived(nextEntry, session, message);
648                 }
649
650                 public void messageSent(IoSession session, Object JavaDoc message) {
651                     Entry nextEntry = EntryImpl.this.nextEntry;
652                     callNextMessageSent(nextEntry, session, message);
653                 }
654
655                 public void filterWrite(IoSession session,
656                         WriteRequest writeRequest) {
657                     Entry nextEntry = EntryImpl.this.prevEntry;
658                     callPreviousFilterWrite(nextEntry, session, writeRequest);
659                 }
660
661                 public void filterClose(IoSession session) {
662                     Entry nextEntry = EntryImpl.this.prevEntry;
663                     callPreviousFilterClose(nextEntry, session);
664                 }
665             };
666         }
667
668         public String JavaDoc getName() {
669             return name;
670         }
671
672         public IoFilter getFilter() {
673             return filter;
674         }
675
676         public NextFilter getNextFilter() {
677             return nextFilter;
678         }
679
680         public String JavaDoc toString() {
681             return "(" + getName() + ':' + filter + ')';
682         }
683     }
684 }
685
Popular Tags