KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > util > connection > SimpleConnectionManager


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.util.connection;
19
20 import java.net.ServerSocket JavaDoc;
21 import java.util.HashMap JavaDoc;
22
23 import org.apache.avalon.excalibur.thread.ThreadPool;
24
25 import org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory;
26 import org.apache.james.services.JamesConnectionManager;
27 import org.apache.avalon.cornerstone.services.threads.ThreadManager;
28 import org.apache.avalon.framework.activity.Initializable;
29 import org.apache.avalon.framework.component.ComponentException;
30 import org.apache.avalon.framework.component.ComponentManager;
31 import org.apache.avalon.framework.component.Composable;
32 import org.apache.avalon.framework.configuration.Configurable;
33 import org.apache.avalon.framework.configuration.Configuration;
34 import org.apache.avalon.framework.configuration.ConfigurationException;
35
36 import org.apache.avalon.framework.activity.Disposable;
37 import org.apache.avalon.framework.logger.AbstractLogEnabled;
38
39
40 /**
41  * An implementation of ConnectionManager that supports configurable
42  * idle timeouts and a configurable value for the maximum number of
43  * client connections to a particular port.
44  *
45  */

46 public class SimpleConnectionManager extends AbstractLogEnabled
47     implements JamesConnectionManager, Composable, Configurable, Disposable {
48
49     /**
50      * The default value for client socket idle timeouts. The
51      * Java default is 0, meaning no timeout. That's dangerous
52      * for a connection handler like this one, because it can
53      * easily lead to consumption of network resources. So we
54      * allow users to configure the system to allow no timeout,
55      * but if no timeout is specified in the configuration, we
56      * use a timeout of 5 minutes.
57      */

58     private static final int DEFAULT_SOCKET_TIMEOUT = 5 * 60 * 1000;
59
60     /**
61      * The default value for the maximum number of allowed client
62      * connections.
63      */

64     private static final int DEFAULT_MAX_CONNECTIONS = 30;
65
66     /**
67      * The map of connection name / server connections managed by this connection
68      * manager.
69      */

70     private final HashMap JavaDoc connectionMap = new HashMap JavaDoc();
71   
72     /**
73      * The idle timeout for the individual sockets spawed from the server socket.
74      */

75     protected int timeout = 0;
76
77     /**
78      * The maximum number of client connections allowed per server connection.
79      */

80     protected int maxOpenConn = 0;
81
82     /**
83      * The ThreadManager component that is used to provide a default thread pool.
84      */

85     private ThreadManager threadManager;
86
87     /**
88      * Whether the SimpleConnectionManager has been disposed.
89      */

90     private volatile boolean disposed = false;
91
92     /**
93      * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
94      */

95     public void configure(final Configuration configuration) throws ConfigurationException {
96         timeout = configuration.getChild("idle-timeout").getValueAsInteger(DEFAULT_SOCKET_TIMEOUT);
97         maxOpenConn = configuration.getChild("max-connections").getValueAsInteger(DEFAULT_MAX_CONNECTIONS);
98
99         if (timeout < 0) {
100             StringBuffer JavaDoc exceptionBuffer =
101                 new StringBuffer JavaDoc(128)
102                     .append("Specified socket timeout value of ")
103                     .append(timeout)
104                     .append(" is not a legal value.");
105             throw new ConfigurationException(exceptionBuffer.toString());
106         }
107
108         if (maxOpenConn < 0) {
109             StringBuffer JavaDoc exceptionBuffer =
110                 new StringBuffer JavaDoc(128)
111                     .append("Specified maximum number of open connections of ")
112                     .append(maxOpenConn)
113                     .append(" is not a legal value.");
114             throw new ConfigurationException(exceptionBuffer.toString());
115         }
116
117         if (getLogger().isDebugEnabled()) {
118             getLogger().debug("Connection timeout is "
119                              + (timeout == 0 ? "unlimited" : Long.toString(timeout)));
120             getLogger().debug("The maximum number of simultaneously open connections is "
121                              + (maxOpenConn == 0 ? "unlimited" : Integer.toString(maxOpenConn)));
122         }
123     }
124
125     /**
126      * @see org.apache.avalon.framework.component.Composable#compose(ComponentManager)
127      */

128     public void compose(ComponentManager componentManager)
129         throws ComponentException {
130         threadManager = (ThreadManager)componentManager.lookup( ThreadManager.ROLE );
131     }
132
133     /**
134      * Disconnects all the underlying ServerConnections
135      */

136     public void dispose() {
137         disposed = true;
138         if (getLogger().isDebugEnabled()) {
139             getLogger().debug("Starting SimpleConnectionManager dispose...");
140         }
141         final String JavaDoc[] names = (String JavaDoc[])connectionMap.keySet().toArray( new String JavaDoc[ 0 ] );
142         for( int i = 0; i < names.length; i++ ) {
143             try {
144                 if (getLogger().isDebugEnabled()) {
145                     getLogger().debug("Disconnecting ServerConnection " + names[i]);
146                 }
147                 disconnect( names[ i ], true);
148             } catch( final Exception JavaDoc e ) {
149                 getLogger().warn( "Error disconnecting " + names[ i ], e );
150             }
151         }
152         if (getLogger().isDebugEnabled()) {
153             getLogger().debug("Finishing SimpleConnectionManager dispose...");
154         }
155     }
156   
157     /**
158      * Start managing a connection.
159      * Management involves accepting connections and farming them out to threads
160      * from pool to be handled.
161      *
162      * @param name the name of connection
163      * @param socket the ServerSocket from which to
164      * @param handlerFactory the factory from which to acquire handlers
165      * @param threadPool the thread pool to use
166      * @param maxOpenConnections the maximum number of open connections allowed for this server socket.
167      * @exception Exception if an error occurs
168      */

169     public void connect( String JavaDoc name,
170                          ServerSocket JavaDoc socket,
171                          ConnectionHandlerFactory handlerFactory,
172                          ThreadPool threadPool,
173                          int maxOpenConnections )
174         throws Exception JavaDoc {
175
176         if (disposed) {
177             throw new IllegalStateException JavaDoc("Connection manager has already been shutdown.");
178         }
179         if( null != connectionMap.get( name ) ) {
180             throw new IllegalArgumentException JavaDoc( "Connection already exists with name " +
181                                                 name );
182         }
183         if (maxOpenConnections < 0) {
184             throw new IllegalArgumentException JavaDoc( "The maximum number of client connections per server socket cannot be less that zero.");
185         }
186         ServerConnection runner = new ServerConnection(socket, handlerFactory, threadPool, timeout, maxOpenConnections);
187         setupLogger( runner );
188         if (runner instanceof Initializable) {
189             ((Initializable)runner).initialize();
190         }
191         connectionMap.put( name, runner );
192         threadPool.execute(runner);
193     }
194
195     /**
196      * Start managing a connection.
197      * Management involves accepting connections and farming them out to threads
198      * from pool to be handled.
199      *
200      * @param name the name of connection
201      * @param socket the ServerSocket from which to
202      * @param handlerFactory the factory from which to acquire handlers
203      * @param threadPool the thread pool to use
204      * @exception Exception if an error occurs
205      */

206     public void connect( String JavaDoc name,
207                          ServerSocket JavaDoc socket,
208                          ConnectionHandlerFactory handlerFactory,
209                          ThreadPool threadPool )
210         throws Exception JavaDoc {
211
212         connect(name, socket, handlerFactory, threadPool, maxOpenConn);
213     }
214
215     /**
216      * Start managing a connection.
217      * This is similar to other connect method except that it uses default thread pool.
218      *
219      * @param name the name of connection
220      * @param socket the ServerSocket from which to
221      * @param handlerFactory the factory from which to acquire handlers
222      * @exception Exception if an error occurs
223      */

224     public void connect( String JavaDoc name,
225                          ServerSocket JavaDoc socket,
226                          ConnectionHandlerFactory handlerFactory )
227         throws Exception JavaDoc {
228         connect( name, socket, handlerFactory, threadManager.getDefaultThreadPool() );
229     }
230
231     /**
232      * Start managing a connection.
233      * This is similar to other connect method except that it uses default thread pool.
234      *
235      * @param name the name of connection
236      * @param socket the ServerSocket from which to
237      * @param handlerFactory the factory from which to acquire handlers
238      * @param maxOpenConnections the maximum number of open connections allowed for this server socket.
239      * @exception Exception if an error occurs
240      */

241     public void connect( String JavaDoc name,
242                          ServerSocket JavaDoc socket,
243                          ConnectionHandlerFactory handlerFactory,
244                          int maxOpenConnections )
245         throws Exception JavaDoc {
246         connect( name, socket, handlerFactory, threadManager.getDefaultThreadPool(), maxOpenConnections );
247     }
248
249     /**
250      * This shuts down all handlers and socket, waiting for each to gracefully shutdown.
251      *
252      * @param name the name of connection
253      * @exception Exception if an error occurs
254      */

255     public void disconnect( final String JavaDoc name )
256         throws Exception JavaDoc {
257         disconnect( name, false );
258     }
259   
260     /**
261      * This shuts down a connection.
262      * If tearDown is true then it will forcefully the connection and try
263      * to return as soon as possible. Otherwise it will behave the same as
264      * void disconnect( String name );
265      *
266      * @param name the name of connection
267      * @param tearDown if true will forcefully tear down all handlers
268      * @exception Exception if an error occurs
269      */

270     public void disconnect( final String JavaDoc name, final boolean tearDown )
271         throws Exception JavaDoc {
272
273         ServerConnection connection = (ServerConnection)connectionMap.remove( name );
274         if( null == connection ) {
275             throw new IllegalArgumentException JavaDoc( "No such connection with name " +
276                                                 name );
277         }
278
279         // TODO: deal with tear down parameter
280
connection.dispose();
281     }
282
283     /**
284      * Returns the default maximum number of open connections supported by this
285      * SimpleConnectionManager
286      *
287      * @return the maximum number of connections
288      */

289     public int getMaximumNumberOfOpenConnections() {
290         return maxOpenConn;
291     }
292 }
293
Popular Tags