1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.mina.protocol;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.IdentityHashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.mina.common.IdleStatus;
29 import org.apache.mina.protocol.ProtocolFilter.NextFilter;
30
31 /***
32 * An abstract implementation of {@link ProtocolFilterChain} that provides
33 * common operations for developers to extend protocol layer.
34 * <p>
35 * All methods has been implemented. The list of filters is maintained
36 * as a doublely linked list. You can fire any MINA events which is filtered
37 * by this chain using these public methods:
38 * <ul>
39 * <li></li>
40 * </ul>
41 *
42 * The only method a developer should implement is {@link #doWrite(ProtocolSession, Object)}.
43 * This method is invoked when filter chain is evaluated for
44 * {@link ProtocolFilter#filterWrite(NextFilter, ProtocolSession, Object)} and
45 * finally to be written out.
46 *
47 * @author The Apache Directory Project
48 * @version $Rev: 169321 $, $Date: 2005-05-10 00:00:25 +0900 (?, 10 5? 2005) $
49 */
50 public abstract class AbstractProtocolFilterChain implements ProtocolFilterChain
51 {
52 private final Map name2entry = new HashMap();
53
54 private final Map filter2entry = new IdentityHashMap();
55
56 private final Entry head;
57
58 private final Entry tail;
59
60 protected AbstractProtocolFilterChain()
61 {
62 head = new Entry( null, null, "head", createHeadFilter() );
63 tail = new Entry( head, null, "tail", createTailFilter() );
64 head.nextEntry = tail;
65 }
66
67 /***
68 * Override this method to create custom head of this filter chain.
69 */
70 protected ProtocolFilter createHeadFilter()
71 {
72 return new ProtocolFilter()
73 {
74 public void sessionOpened( NextFilter nextFilter, ProtocolSession session )
75 {
76 nextFilter.sessionOpened( session );
77 }
78
79 public void sessionClosed( NextFilter nextFilter, ProtocolSession session )
80 {
81 nextFilter.sessionClosed( session );
82 }
83
84 public void sessionIdle( NextFilter nextFilter, ProtocolSession session,
85 IdleStatus status )
86 {
87 nextFilter.sessionIdle( session, status );
88 }
89
90 public void exceptionCaught( NextFilter nextFilter,
91 ProtocolSession session, Throwable cause )
92 {
93 nextFilter.exceptionCaught( session, cause );
94 }
95
96 public void messageReceived( NextFilter nextFilter, ProtocolSession session,
97 Object message )
98 {
99 nextFilter.messageReceived( session, message );
100 }
101
102 public void messageSent( NextFilter nextFilter, ProtocolSession session,
103 Object message )
104 {
105 nextFilter.messageSent( session, message );
106 }
107
108 public void filterWrite( NextFilter nextFilter, ProtocolSession session,
109 Object message )
110 {
111 doWrite( session, message );
112 }
113 };
114 }
115
116 /***
117 * Override this method to create custom head of this filter chain.
118 */
119 protected ProtocolFilter createTailFilter()
120 {
121 return new ProtocolFilter()
122 {
123 public void sessionOpened( NextFilter nextFilter, ProtocolSession session ) throws Exception
124 {
125 session.getHandler().sessionOpened( session );
126 }
127
128 public void sessionClosed( NextFilter nextFilter, ProtocolSession session ) throws Exception
129 {
130 session.getHandler().sessionClosed( session );
131 }
132
133 public void sessionIdle( NextFilter nextFilter, ProtocolSession session,
134 IdleStatus status ) throws Exception
135 {
136 session.getHandler().sessionIdle( session, status );
137 }
138
139 public void exceptionCaught( NextFilter nextFilter,
140 ProtocolSession session, Throwable cause ) throws Exception
141 {
142 session.getHandler().exceptionCaught( session, cause );
143 }
144
145 public void messageReceived( NextFilter nextFilter, ProtocolSession session,
146 Object message ) throws Exception
147 {
148 ProtocolHandler handler = session.getHandler();
149 handler.messageReceived( session, message );
150 }
151
152 public void messageSent( NextFilter nextFilter, ProtocolSession session,
153 Object message ) throws Exception
154 {
155 session.getHandler().messageSent( session, message );
156 }
157
158 public void filterWrite( NextFilter nextFilter,
159 ProtocolSession session, Object message ) throws Exception
160 {
161 nextFilter.filterWrite( session, message );
162 }
163 };
164 }
165
166 public ProtocolFilter getChild( String name )
167 {
168 Entry e = ( Entry ) name2entry.get( name );
169 if ( e == null )
170 {
171 return null;
172 }
173 return e.filter;
174 }
175
176 /***
177 * Adds the specified interceptor with the specified name at the beginning of this chain.
178 */
179 public synchronized void addFirst( String name,
180 ProtocolFilter filter )
181 {
182 checkAddable( name );
183 register( head, name, filter );
184 }
185
186
187 /***
188 * Adds the specified interceptor with the specified name at the end of this chain.
189 */
190 public synchronized void addLast( String name,
191 ProtocolFilter filter )
192 {
193 checkAddable( name );
194 register( tail.prevEntry, name, filter );
195 }
196
197
198 /***
199 * Adds the specified interceptor with the specified name just before the interceptor whose name is
200 * <code>baseName</code> in this chain.
201 */
202 public synchronized void addBefore( String baseName,
203 String name,
204 ProtocolFilter filter )
205 {
206 Entry baseEntry = checkOldName( baseName );
207 checkAddable( name );
208 register( baseEntry, name, filter );
209 }
210
211
212 /***
213 * Adds the specified interceptor with the specified name just after the interceptor whose name is
214 * <code>baseName</code> in this chain.
215 */
216 public synchronized void addAfter( String baseName,
217 String name,
218 ProtocolFilter filter )
219 {
220 Entry baseEntry = checkOldName( baseName );
221 checkAddable( name );
222 register( baseEntry.prevEntry, name, filter );
223 }
224
225
226 /***
227 * Removes the interceptor with the specified name from this chain.
228 */
229 public synchronized void remove( String name )
230 {
231 Entry entry = checkOldName( name );
232 Entry prevEntry = entry.prevEntry;
233 Entry nextEntry = entry.nextEntry;
234 prevEntry.nextEntry = nextEntry;
235 nextEntry.prevEntry = prevEntry;
236
237 name2entry.remove( name );
238 ProtocolFilter filter = entry.filter;
239 filter2entry.remove( filter );
240 }
241
242
243 /***
244 * Removes all interceptors added to this chain.
245 */
246 public synchronized void clear()
247 {
248 Iterator it = new ArrayList( name2entry.keySet() ).iterator();
249 while ( it.hasNext() )
250 {
251 this.remove( ( String ) it.next() );
252 }
253 }
254
255 private void register( Entry prevEntry, String name, ProtocolFilter filter )
256 {
257 Entry newEntry = new Entry( prevEntry, prevEntry.nextEntry, name, filter );
258 prevEntry.nextEntry.prevEntry = newEntry;
259 prevEntry.nextEntry = newEntry;
260 name2entry.put( name, newEntry );
261 filter2entry.put( filter, newEntry );
262 }
263
264 /***
265 * Throws an exception when the specified interceptor name is not registered in this chain.
266 *
267 * @return An interceptor entry with the specified name.
268 */
269 private Entry checkOldName( String baseName )
270 {
271 Entry e = ( Entry ) name2entry.get( baseName );
272 if ( e == null )
273 {
274 throw new IllegalArgumentException( "Unknown interceptor name:" +
275 baseName );
276 }
277 return e;
278 }
279
280
281 /***
282 * Checks the specified interceptor name is already taken and throws an exception if already taken.
283 */
284 private void checkAddable( String name )
285 {
286 if ( name2entry.containsKey( name ) )
287 {
288 throw new IllegalArgumentException( "Other interceptor is using name '" + name + "'" );
289 }
290 }
291
292 public void sessionOpened( ProtocolSession session )
293 {
294 Entry head = this.head;
295 callNextSessionOpened(head, session);
296 }
297
298 private void callNextSessionOpened( Entry entry,
299 ProtocolSession session)
300 {
301 try
302 {
303 entry.filter.sessionOpened( entry.nextFilter, session );
304 }
305 catch( Throwable e )
306 {
307 exceptionCaught( session, e );
308 }
309 }
310
311 public void sessionClosed( ProtocolSession session )
312 {
313 Entry head = this.head;
314 callNextSessionClosed(head, session);
315 }
316
317 private void callNextSessionClosed( Entry entry,
318 ProtocolSession session )
319 {
320 try
321 {
322 entry.filter.sessionClosed( entry.nextFilter, session );
323
324 }
325 catch( Throwable e )
326 {
327 exceptionCaught( session, e );
328 }
329 }
330
331 public void sessionIdle( ProtocolSession session, IdleStatus status )
332 {
333 Entry head = this.head;
334 callNextSessionIdle(head, session, status);
335 }
336
337 private void callNextSessionIdle( Entry entry,
338 ProtocolSession session,
339 IdleStatus status )
340 {
341 try
342 {
343 entry.filter.sessionIdle( entry.nextFilter, session, status );
344 }
345 catch( Throwable e )
346 {
347 exceptionCaught( session, e );
348 }
349 }
350
351 public void messageReceived( ProtocolSession session, Object message )
352 {
353 Entry head = this.head;
354 callNextMessageReceived(head, session, message );
355 }
356
357 private void callNextMessageReceived( Entry entry,
358 ProtocolSession session,
359 Object message )
360 {
361 try
362 {
363 entry.filter.messageReceived( entry.nextFilter, session, message );
364 }
365 catch( Throwable e )
366 {
367 exceptionCaught( session, e );
368 }
369 }
370
371 public void messageSent( ProtocolSession session, Object message )
372 {
373 Entry head = this.head;
374 callNextMessageSent(head, session, message);
375 }
376
377 private void callNextMessageSent( Entry entry,
378 ProtocolSession session,
379 Object message )
380 {
381 try
382 {
383 entry.filter.messageSent( entry.nextFilter, session, message );
384 }
385 catch( Throwable e )
386 {
387 exceptionCaught( session, e );
388 }
389 }
390
391 public void exceptionCaught( ProtocolSession session, Throwable cause )
392 {
393 Entry head = this.head;
394 callNextExceptionCaught(head, session, cause);
395 }
396
397 private void callNextExceptionCaught( Entry entry,
398 ProtocolSession session,
399 Throwable cause )
400 {
401 try
402 {
403 entry.filter.exceptionCaught( entry.nextFilter, session, cause );
404 }
405 catch( Throwable e )
406 {
407 e.printStackTrace();
408 }
409 }
410
411 public void filterWrite( ProtocolSession session, Object message )
412 {
413 Entry tail = this.tail;
414 callPreviousFilterWrite( tail, session, message );
415 }
416
417 private void callPreviousFilterWrite( Entry entry,
418 ProtocolSession session,
419 Object message )
420 {
421 if( message == null )
422 {
423 return;
424 }
425
426 try
427 {
428 entry.filter.filterWrite( entry.nextFilter, session, message );
429 }
430 catch( Throwable e )
431 {
432 exceptionCaught( session, e );
433 }
434 }
435
436 public List getChildren()
437 {
438 List list = new ArrayList();
439 Entry e = head.nextEntry;
440 while( e != tail )
441 {
442 list.add( e.filter );
443 e = e.nextEntry;
444 }
445
446 return list;
447 }
448
449 public List getChildrenReversed()
450 {
451 List list = new ArrayList();
452 Entry e = tail.prevEntry;
453 while( e != head )
454 {
455 list.add( e.filter );
456 e = e.prevEntry;
457 }
458 return list;
459 }
460
461 protected abstract void doWrite( ProtocolSession session, Object message );
462
463 private class Entry
464 {
465 private Entry prevEntry;
466
467 private Entry nextEntry;
468
469 private final String name;
470
471 private final ProtocolFilter filter;
472
473 private final NextFilter nextFilter;
474
475 private Entry( Entry prevEntry, Entry nextEntry,
476 String name, ProtocolFilter filter )
477 {
478 if( filter == null )
479 {
480 throw new NullPointerException( "filter" );
481 }
482 if( name == null )
483 {
484 throw new NullPointerException( "name" );
485 }
486
487 this.prevEntry = prevEntry;
488 this.nextEntry = nextEntry;
489 this.name = name;
490 this.filter = filter;
491 this.nextFilter = new NextFilter()
492 {
493
494 public void sessionOpened( ProtocolSession session )
495 {
496 Entry nextEntry = Entry.this.nextEntry;
497 callNextSessionOpened( nextEntry, session );
498 }
499
500 public void sessionClosed( ProtocolSession session )
501 {
502 Entry nextEntry = Entry.this.nextEntry;
503 callNextSessionClosed( nextEntry, session );
504 }
505
506 public void sessionIdle( ProtocolSession session, IdleStatus status )
507 {
508 Entry nextEntry = Entry.this.nextEntry;
509 callNextSessionIdle( nextEntry, session, status );
510 }
511
512 public void exceptionCaught( ProtocolSession session,
513 Throwable cause )
514 {
515 Entry nextEntry = Entry.this.nextEntry;
516 callNextExceptionCaught( nextEntry, session, cause );
517 }
518
519 public void messageReceived( ProtocolSession session, Object message )
520 {
521 Entry nextEntry = Entry.this.nextEntry;
522 callNextMessageReceived( nextEntry, session, message );
523 }
524
525 public void messageSent( ProtocolSession session, Object message )
526 {
527 Entry nextEntry = Entry.this.nextEntry;
528 callNextMessageSent( nextEntry, session, message );
529 }
530
531 public void filterWrite( ProtocolSession session, Object message )
532 {
533 Entry nextEntry = Entry.this.prevEntry;
534 callPreviousFilterWrite( nextEntry, session, message );
535 }
536 };
537 }
538
539 public String getName()
540 {
541 return name;
542 }
543
544 public ProtocolFilter getFilter()
545 {
546 return filter;
547 }
548 }
549 }