1 | /* |
2 | * @(#) $Id: DemuxingProtocolHandler.java 210062 2005-07-11 03:52:38Z trustin $ |
3 | */ |
4 | package org.apache.mina.protocol.handler; |
5 | |
6 | import java.util.HashMap; |
7 | import java.util.HashSet; |
8 | import java.util.Map; |
9 | import java.util.Set; |
10 | |
11 | import org.apache.mina.protocol.ProtocolHandler; |
12 | import org.apache.mina.protocol.ProtocolHandlerAdapter; |
13 | import org.apache.mina.protocol.ProtocolSession; |
14 | |
15 | /** |
16 | * A {@link ProtocolHandler} that demuxes <code>messageReceived</code> events |
17 | * to the appropriate {@link MessageHandler}. |
18 | * |
19 | * You can freely register and deregister {@link MessageHandler}s using |
20 | * {@link #registerMessageType(Class, MessageHandler)} and |
21 | * {@link #deregisterMessageType(Class)}. |
22 | * |
23 | * @author The Apache Directory Project |
24 | * @version $Rev: 210062 $, $Date: 2005-07-11 12:52:38 +0900 $ |
25 | */ |
26 | public class DemuxingProtocolHandler extends ProtocolHandlerAdapter |
27 | { |
28 | private final Map type2handler = new HashMap(); |
29 | |
30 | /** |
31 | * Creates a new instance with no registered {@link MessageHandler}s. |
32 | */ |
33 | protected DemuxingProtocolHandler() |
34 | { |
35 | } |
36 | |
37 | /** |
38 | * Registers a {@link MessageHandler} that receives the messages of |
39 | * the specified <code>type</code>. |
40 | */ |
41 | public void registerMessageType( Class type, MessageHandler handler ) |
42 | { |
43 | synchronized( type2handler ) |
44 | { |
45 | type2handler.put( type, handler ); |
46 | } |
47 | } |
48 | |
49 | /** |
50 | * Deregisters a {@link MessageHandler} that receives the messages of |
51 | * the specified <code>type</code>. |
52 | */ |
53 | public void deregisterMessageType( Class clazz ) |
54 | { |
55 | synchronized( type2handler ) |
56 | { |
57 | type2handler.remove( clazz ); |
58 | } |
59 | } |
60 | |
61 | /** |
62 | * Forwards the received events into the appropriate {@link MessageHandler} |
63 | * which is registered by {@link #registerMessageType(Class, MessageHandler)}. |
64 | */ |
65 | public void messageReceived( ProtocolSession session, Object message ) |
66 | { |
67 | MessageHandler handler = findHandler( message.getClass() ); |
68 | if( handler != null ) |
69 | { |
70 | handler.messageReceived( session, message ); |
71 | } |
72 | else |
73 | { |
74 | throw new UnknownMessageTypeException( |
75 | "No message handler found for message: " + message ); |
76 | } |
77 | } |
78 | |
79 | private MessageHandler findHandler( Class type ) |
80 | { |
81 | MessageHandler handler = ( MessageHandler ) type2handler.get( type ); |
82 | if( handler == null ) |
83 | { |
84 | handler = findHandler( type, new HashSet() ); |
85 | } |
86 | |
87 | return handler; |
88 | } |
89 | |
90 | private MessageHandler findHandler( Class type, Set triedClasses ) |
91 | { |
92 | MessageHandler handler; |
93 | |
94 | if( triedClasses.contains( type ) ) |
95 | return null; |
96 | triedClasses.add( type ); |
97 | |
98 | handler = ( MessageHandler ) type2handler.get( type ); |
99 | if( handler == null ) |
100 | { |
101 | handler = findHandler( type, triedClasses ); |
102 | if( handler != null ) |
103 | return handler; |
104 | |
105 | Class[] interfaces = type.getInterfaces(); |
106 | for( int i = 0; i < interfaces.length; i ++ ) |
107 | { |
108 | handler = findHandler( interfaces[ i ], triedClasses ); |
109 | if( handler != null ) |
110 | return handler; |
111 | } |
112 | |
113 | return null; |
114 | } |
115 | else |
116 | return handler; |
117 | } |
118 | } |