KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > spice > netserve > connection > impl > DefaultAcceptorManager


1 /*
2  * Copyright (C) The Spice Group. All rights reserved.
3  *
4  * This software is published under the terms of the Spice
5  * Software License version 1.1, a copy of which has been included
6  * with this distribution in the LICENSE.txt file.
7  */

8 package org.codehaus.spice.netserve.connection.impl;
9
10 import java.net.ServerSocket JavaDoc;
11 import java.util.Hashtable JavaDoc;
12 import java.util.Map JavaDoc;
13 import org.codehaus.spice.netserve.connection.RequestHandler;
14 import org.codehaus.spice.netserve.connection.SocketAcceptorManager;
15 import org.codehaus.spice.netserve.connection.impl.AcceptorConfig;
16 import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
17 import org.codehaus.spice.netserve.connection.impl.ConnectionAcceptor;
18
19 /**
20  * Default implementation of SocketAcceptorManager that uses
21  * a thread per acceptor approach.
22  *
23  * <p>Note that on some OS/JVM combinations <tt>soTimeout</tt> must
24  * be set to non-0 value or else the ServerSocket will never get out
25  * of accept() system call and we wont be able to shutdown the server
26  * socket properly. However it can introduce performance problems if
27  * constantly timing out. </p>
28  *
29  * @author Peter Donald
30  * @author Mauro Talevi
31  * @version $Revision: 1.3 $ $Date: 2004/03/21 23:42:59 $
32  */

33 public class DefaultAcceptorManager
34     implements SocketAcceptorManager
35 {
36     /**
37      * The map of name->acceptor.
38      */

39     private final Map JavaDoc m_acceptors = new Hashtable JavaDoc();
40
41     /**
42      * The monitor that receives notifications of Connection events
43      */

44     private AcceptorMonitor m_monitor = NullAcceptorMonitor.MONITOR;
45
46     /**
47      * Value that we are to set SO_TIMEOUT to if the user
48      * has not already set the timeout. Defaults to 1000 (1s timeout).
49      */

50     private int m_soTimeout = 1000;
51
52     /**
53      * Set to the number of milliseconds that we will wait
54      * for a connection to shutdown gracefully. Defaults to 0
55      * which indicates indefinite wait.
56      */

57     private int m_shutdownTimeout;
58
59     /**
60      * Set the AcceptorMonitor that receives events when changes occur.
61      *
62      * @param monitor the AcceptorMonitor that receives events when
63      * changes occur.
64      */

65     public void setMonitor( final AcceptorMonitor monitor )
66     {
67         m_monitor = monitor;
68     }
69
70     /**
71      * Set the value that we are to set SO_TIMEOUT to if the user
72      * has not already set the timeout. Defaults to 1000 (1s timeout).
73      *
74      * @param soTimeout the timeout value
75      */

76     public void setSoTimeout( final int soTimeout )
77     {
78         m_soTimeout = soTimeout;
79     }
80
81     /**
82      * Set timeout for shutting down handlers.
83      * The timeout defaults to 0 which means wait indefinetly.
84      *
85      * @param shutdownTimeout the timeout
86      */

87     public void setShutdownTimeout( final int shutdownTimeout )
88     {
89         m_shutdownTimeout = shutdownTimeout;
90     }
91
92     /**
93      * Return the shutdownTimeout.
94      *
95      * @return the shutdownTimeout
96      */

97     protected int getShutdownTimeout()
98     {
99         return m_shutdownTimeout;
100     }
101
102     /**
103      * Dispose the ConnectionManager which involves shutting down all
104      * the connected acceptors.
105      */

106     public void shutdownAcceptors()
107     {
108         final String JavaDoc[] names;
109         synchronized( m_acceptors )
110         {
111             names = (String JavaDoc[])m_acceptors.keySet().toArray( new String JavaDoc[ 0 ] );
112         }
113         for( int i = 0; i < names.length; i++ )
114         {
115             disconnect( names[ i ] );
116         }
117     }
118
119     /**
120      * Start accepting connections from a socket and passing connections
121      * to specified handler.
122      *
123      * @param name the name of connection. This serves as a key used to
124      * shutdown acceptor.
125      * @param socket the ServerSocket from which connections are accepted
126      * @throws java.lang.Exception if unable to initiate connection management. This could
127      * be due to the key already being used for another acceptor,
128      * the serversocket being closed, the handler being null etc.
129      */

130     public void connect( final String JavaDoc name,
131                          final ServerSocket JavaDoc socket,
132                          final RequestHandler handler )
133         throws Exception JavaDoc
134     {
135         if( null == name )
136         {
137             throw new NullPointerException JavaDoc( "name" );
138         }
139         if( null == socket )
140         {
141             throw new NullPointerException JavaDoc( "socket" );
142         }
143         if( null == handler )
144         {
145             throw new NullPointerException JavaDoc( "handler" );
146         }
147
148         if( 0 == socket.getSoTimeout() )
149         {
150             socket.setSoTimeout( m_soTimeout );
151         }
152
153         final ConnectionAcceptor acceptor;
154         synchronized( m_acceptors )
155         {
156             if( isConnected( name ) )
157             {
158                 final String JavaDoc message =
159                     "Connection already exists with name " + name;
160                 throw new IllegalArgumentException JavaDoc( message );
161             }
162
163             final AcceptorConfig config = new AcceptorConfig( name, socket, handler );
164             acceptor = new ConnectionAcceptor( config, getMonitor() );
165             m_acceptors.put( name, acceptor );
166         }
167
168         final Thread JavaDoc thread =
169             new Thread JavaDoc( acceptor, "Acceptor[" + name + "]" );
170         thread.start();
171         while( !acceptor.hasStarted() )
172         {
173             Thread.sleep( 5 );
174         }
175     }
176
177     /**
178      * Return true if acceptor with specified name exists.
179      *
180      * @param name the name
181      * @return true if acceptor with specified name exists.
182      */

183     public boolean isConnected( final String JavaDoc name )
184     {
185         return m_acceptors.containsKey( name );
186     }
187
188     /**
189      * This shuts down the acceptor and the associated ServerSocket.
190      *
191      * @param name the name of connection
192      * @throws java.lang.IllegalArgumentException if no connection with specified name
193      */

194     public void disconnect( final String JavaDoc name )
195     {
196         final ConnectionAcceptor acceptor =
197             (ConnectionAcceptor)m_acceptors.remove( name );
198         if( null == acceptor )
199         {
200             final String JavaDoc message = "No connection with name " + name;
201             throw new IllegalArgumentException JavaDoc( message );
202         }
203
204         acceptor.close( getShutdownTimeout() );
205     }
206
207     /**
208      * Return the monitor used by manager.
209      *
210      * @return the monitor used by manager.
211      */

212     protected AcceptorMonitor getMonitor()
213     {
214         return m_monitor;
215     }
216 }
217
Popular Tags