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