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