1
2
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: 332218 $, $Date: 2005-11-10 12:52:42 +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 ) throws Exception
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 }