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: 210062 $, $Date: 2005-07-11 12:52:38 +0900 $
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 ProtocolFilter 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 return filter;
242 }
243
244
245 /***
246 * Removes all interceptors added to this chain.
247 */
248 public synchronized void clear()
249 {
250 Iterator it = new ArrayList( name2entry.keySet() ).iterator();
251 while ( it.hasNext() )
252 {
253 this.remove( ( String ) it.next() );
254 }
255 }
256
257 private void register( Entry prevEntry, String name, ProtocolFilter filter )
258 {
259 Entry newEntry = new Entry( prevEntry, prevEntry.nextEntry, name, filter );
260 prevEntry.nextEntry.prevEntry = newEntry;
261 prevEntry.nextEntry = newEntry;
262 name2entry.put( name, newEntry );
263 filter2entry.put( filter, newEntry );
264 }
265
266 /***
267 * Throws an exception when the specified interceptor name is not registered in this chain.
268 *
269 * @return An interceptor entry with the specified name.
270 */
271 private Entry checkOldName( String baseName )
272 {
273 Entry e = ( Entry ) name2entry.get( baseName );
274 if ( e == null )
275 {
276 throw new IllegalArgumentException( "Unknown interceptor name:" +
277 baseName );
278 }
279 return e;
280 }
281
282
283 /***
284 * Checks the specified interceptor name is already taken and throws an exception if already taken.
285 */
286 private void checkAddable( String name )
287 {
288 if ( name2entry.containsKey( name ) )
289 {
290 throw new IllegalArgumentException( "Other interceptor is using name '" + name + "'" );
291 }
292 }
293
294 public void sessionOpened( ProtocolSession session )
295 {
296 Entry head = this.head;
297 callNextSessionOpened(head, session);
298 }
299
300 private void callNextSessionOpened( Entry entry,
301 ProtocolSession session)
302 {
303 try
304 {
305 entry.filter.sessionOpened( entry.nextFilter, session );
306 }
307 catch( Throwable e )
308 {
309 exceptionCaught( session, e );
310 }
311 }
312
313 public void sessionClosed( ProtocolSession session )
314 {
315 Entry head = this.head;
316 callNextSessionClosed(head, session);
317 }
318
319 private void callNextSessionClosed( Entry entry,
320 ProtocolSession session )
321 {
322 try
323 {
324 entry.filter.sessionClosed( entry.nextFilter, session );
325
326 }
327 catch( Throwable e )
328 {
329 exceptionCaught( session, e );
330 }
331 }
332
333 public void sessionIdle( ProtocolSession session, IdleStatus status )
334 {
335 Entry head = this.head;
336 callNextSessionIdle(head, session, status);
337 }
338
339 private void callNextSessionIdle( Entry entry,
340 ProtocolSession session,
341 IdleStatus status )
342 {
343 try
344 {
345 entry.filter.sessionIdle( entry.nextFilter, session, status );
346 }
347 catch( Throwable e )
348 {
349 exceptionCaught( session, e );
350 }
351 }
352
353 public void messageReceived( ProtocolSession session, Object message )
354 {
355 Entry head = this.head;
356 callNextMessageReceived(head, session, message );
357 }
358
359 private void callNextMessageReceived( Entry entry,
360 ProtocolSession session,
361 Object message )
362 {
363 try
364 {
365 entry.filter.messageReceived( entry.nextFilter, session, message );
366 }
367 catch( Throwable e )
368 {
369 exceptionCaught( session, e );
370 }
371 }
372
373 public void messageSent( ProtocolSession session, Object message )
374 {
375 Entry head = this.head;
376 callNextMessageSent(head, session, message);
377 }
378
379 private void callNextMessageSent( Entry entry,
380 ProtocolSession session,
381 Object message )
382 {
383 try
384 {
385 entry.filter.messageSent( entry.nextFilter, session, message );
386 }
387 catch( Throwable e )
388 {
389 exceptionCaught( session, e );
390 }
391 }
392
393 public void exceptionCaught( ProtocolSession session, Throwable cause )
394 {
395 Entry head = this.head;
396 callNextExceptionCaught(head, session, cause);
397 }
398
399 private void callNextExceptionCaught( Entry entry,
400 ProtocolSession session,
401 Throwable cause )
402 {
403 try
404 {
405 entry.filter.exceptionCaught( entry.nextFilter, session, cause );
406 }
407 catch( Throwable e )
408 {
409 e.printStackTrace();
410 }
411 }
412
413 public void filterWrite( ProtocolSession session, Object message )
414 {
415 Entry tail = this.tail;
416 callPreviousFilterWrite( tail, session, message );
417 }
418
419 private void callPreviousFilterWrite( Entry entry,
420 ProtocolSession session,
421 Object message )
422 {
423 if( message == null )
424 {
425 return;
426 }
427
428 try
429 {
430 entry.filter.filterWrite( entry.nextFilter, session, message );
431 }
432 catch( Throwable e )
433 {
434 exceptionCaught( session, e );
435 }
436 }
437
438 public List getChildren()
439 {
440 List list = new ArrayList();
441 Entry e = head.nextEntry;
442 while( e != tail )
443 {
444 list.add( e.filter );
445 e = e.nextEntry;
446 }
447
448 return list;
449 }
450
451 public List getChildrenReversed()
452 {
453 List list = new ArrayList();
454 Entry e = tail.prevEntry;
455 while( e != head )
456 {
457 list.add( e.filter );
458 e = e.prevEntry;
459 }
460 return list;
461 }
462
463 protected abstract void doWrite( ProtocolSession session, Object message );
464
465 private class Entry
466 {
467 private Entry prevEntry;
468
469 private Entry nextEntry;
470
471 private final String name;
472
473 private final ProtocolFilter filter;
474
475 private final NextFilter nextFilter;
476
477 private Entry( Entry prevEntry, Entry nextEntry,
478 String name, ProtocolFilter filter )
479 {
480 if( filter == null )
481 {
482 throw new NullPointerException( "filter" );
483 }
484 if( name == null )
485 {
486 throw new NullPointerException( "name" );
487 }
488
489 this.prevEntry = prevEntry;
490 this.nextEntry = nextEntry;
491 this.name = name;
492 this.filter = filter;
493 this.nextFilter = new NextFilter()
494 {
495
496 public void sessionOpened( ProtocolSession session )
497 {
498 Entry nextEntry = Entry.this.nextEntry;
499 callNextSessionOpened( nextEntry, session );
500 }
501
502 public void sessionClosed( ProtocolSession session )
503 {
504 Entry nextEntry = Entry.this.nextEntry;
505 callNextSessionClosed( nextEntry, session );
506 }
507
508 public void sessionIdle( ProtocolSession session, IdleStatus status )
509 {
510 Entry nextEntry = Entry.this.nextEntry;
511 callNextSessionIdle( nextEntry, session, status );
512 }
513
514 public void exceptionCaught( ProtocolSession session,
515 Throwable cause )
516 {
517 Entry nextEntry = Entry.this.nextEntry;
518 callNextExceptionCaught( nextEntry, session, cause );
519 }
520
521 public void messageReceived( ProtocolSession session, Object message )
522 {
523 Entry nextEntry = Entry.this.nextEntry;
524 callNextMessageReceived( nextEntry, session, message );
525 }
526
527 public void messageSent( ProtocolSession session, Object message )
528 {
529 Entry nextEntry = Entry.this.nextEntry;
530 callNextMessageSent( nextEntry, session, message );
531 }
532
533 public void filterWrite( ProtocolSession session, Object message )
534 {
535 Entry nextEntry = Entry.this.prevEntry;
536 callPreviousFilterWrite( nextEntry, session, message );
537 }
538 };
539 }
540
541 public String getName()
542 {
543 return name;
544 }
545
546 public ProtocolFilter getFilter()
547 {
548 return filter;
549 }
550 }
551 }