View Javadoc

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 }