1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  package org.apache.james.util.connection;
23  import java.net.ServerSocket;
24  import java.util.HashMap;
25  import org.apache.excalibur.thread.ThreadPool;
26  import org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory;
27  import org.apache.james.socket.JamesConnectionManager;
28  import org.apache.avalon.cornerstone.services.threads.ThreadManager;
29  import org.apache.avalon.framework.service.ServiceException;
30  import org.apache.avalon.framework.service.ServiceManager;
31  import org.apache.avalon.framework.service.Serviceable;
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  import org.apache.avalon.framework.container.ContainerUtil;
36  import org.apache.avalon.framework.activity.Disposable;
37  import org.apache.avalon.framework.logger.AbstractLogEnabled;
38  
39  
40  
41  
42  
43  
44  public class SimpleConnectionManager
45      extends AbstractLogEnabled
46      implements JamesConnectionManager, Serviceable, Configurable, Disposable {
47      
48  
49  
50  
51  
52  
53  
54  
55  
56      private static final int DEFAULT_SOCKET_TIMEOUT = 5 * 60 * 1000;
57      
58  
59  
60  
61      private static final int DEFAULT_MAX_CONNECTIONS = 30;
62      
63  
64  
65  
66      private static final int DEFAULT_MAX_CONNECTIONS_PER_IP = 0;
67      
68      
69  
70  
71  
72      private final HashMap connectionMap = new HashMap();
73      
74  
75  
76      protected int timeout = 0;
77      
78  
79  
80      protected int maxOpenConn = 0;
81      
82  
83  
84      protected int maxOpenConnPerIP = 0;
85      
86  
87  
88      private ThreadManager threadManager;
89      
90  
91  
92      private volatile boolean disposed = false;
93  
94      public void setThreadManager(ThreadManager threadManager) {
95          this.threadManager = threadManager;
96      }
97  
98      
99  
100 
101     public void configure(final Configuration configuration) throws ConfigurationException {
102         timeout = configuration.getChild("idle-timeout").getValueAsInteger(DEFAULT_SOCKET_TIMEOUT);
103         maxOpenConn = configuration.getChild("max-connections").getValueAsInteger(DEFAULT_MAX_CONNECTIONS);
104         maxOpenConnPerIP = configuration.getChild("max-connections-per-ip").getValueAsInteger(DEFAULT_MAX_CONNECTIONS_PER_IP);
105         if (timeout < 0) {
106             StringBuffer exceptionBuffer =
107                 new StringBuffer(128).append("Specified socket timeout value of ").append(timeout).append(
108                     " is not a legal value.");
109             throw new ConfigurationException(exceptionBuffer.toString());
110         }
111         if (maxOpenConn < 0) {
112             StringBuffer exceptionBuffer =
113                 new StringBuffer(128).append("Specified maximum number of open connections of ").append(
114                     maxOpenConn).append(
115                     " is not a legal value.");
116             throw new ConfigurationException(exceptionBuffer.toString());
117         }
118         if (maxOpenConnPerIP < 0) {
119             StringBuffer exceptionBuffer =
120                 new StringBuffer(128).append("Specified maximum number of open connections per IP of ").append(
121                     maxOpenConnPerIP).append(
122                     " is not a legal value.");
123             throw new ConfigurationException(exceptionBuffer.toString());
124         }
125         if (getLogger().isDebugEnabled()) {
126             getLogger().debug(
127                 "Connection timeout is " + (timeout == 0 ? "unlimited" : Long.toString(timeout)));
128             getLogger().debug(
129                 "The maximum number of simultaneously open connections is "
130                     + (maxOpenConn == 0 ? "unlimited" : Integer.toString(maxOpenConn)));
131         }
132     }
133     
134 
135 
136     public void service(ServiceManager componentManager) throws ServiceException {
137         setThreadManager((ThreadManager)componentManager.lookup(ThreadManager.ROLE));
138     }
139     
140     
141     
142 
143 
144     public void dispose() {
145         disposed = true;
146         if (getLogger().isDebugEnabled()) {
147             getLogger().debug("Starting SimpleConnectionManager dispose...");
148         }
149         final String[] names = (String[])connectionMap.keySet().toArray(new String[0]);
150         for (int i = 0; i < names.length; i++) {
151             try {
152                 if (getLogger().isDebugEnabled()) {
153                     getLogger().debug("Disconnecting ServerConnection " + names[i]);
154                 }
155                 disconnect(names[i], true);
156             } catch (final Exception e) {
157                 getLogger().warn("Error disconnecting " + names[i], e);
158             }
159         }
160         if (getLogger().isDebugEnabled()) {
161             getLogger().debug("Finishing SimpleConnectionManager dispose...");
162         }
163     }
164     
165     
166     
167 
168 
169 
170 
171 
172 
173 
174 
175 
176 
177 
178 
179     public void connect(
180         String name,
181         ServerSocket socket,
182         ConnectionHandlerFactory handlerFactory,
183         ThreadPool threadPool,
184         int maxOpenConnections,
185         int maxOpenConnectionsPerIP)
186         throws Exception {
187         if (disposed) {
188             throw new IllegalStateException("Connection manager has already been shutdown.");
189         }
190         if (null != connectionMap.get(name)) {
191             throw new IllegalArgumentException("Connection already exists with name " + name);
192         }
193         if (maxOpenConnections < 0) {
194             throw new IllegalArgumentException("The maximum number of client connections per server socket cannot be less that zero.");
195         } 
196         if (maxOpenConnectionsPerIP < 0) {
197             throw new IllegalArgumentException("The maximum number of client connections (per IP) per server socket cannot be less that zero.");
198         }
199         ServerConnection runner =
200             new ServerConnection(socket, handlerFactory, threadPool, timeout, maxOpenConnections, maxOpenConnectionsPerIP);
201         setupLogger(runner);
202         ContainerUtil.initialize(runner);
203         connectionMap.put(name, runner);
204         threadPool.execute(runner);
205     }
206     
207     
208     
209 
210 
211 
212 
213 
214 
215 
216 
217 
218 
219     public void connect(
220         String name,
221         ServerSocket socket,
222         ConnectionHandlerFactory handlerFactory,
223         ThreadPool threadPool)
224         throws Exception {
225         connect(name, socket, handlerFactory, threadPool, maxOpenConn, maxOpenConnPerIP);
226     }
227     
228     
229     
230 
231 
232 
233 
234 
235 
236 
237 
238     public void connect(String name, ServerSocket socket, ConnectionHandlerFactory handlerFactory)
239         throws Exception {
240         connect(name, socket, handlerFactory, threadManager.getDefaultThreadPool());
241     }
242     
243     
244     
245 
246 
247 
248 
249 
250 
251 
252 
253 
254     public void connect(
255         String name,
256         ServerSocket socket,
257         ConnectionHandlerFactory handlerFactory,
258         int maxOpenConnections)
259         throws Exception {
260         connect(name, socket, handlerFactory, threadManager.getDefaultThreadPool(), maxOpenConnections);
261     }
262     
263     
264     
265 
266 
267 
268 
269 
270     public void disconnect(final String name) throws Exception {
271         disconnect(name, false);
272     }
273     
274     
275     
276 
277 
278 
279 
280 
281 
282 
283 
284 
285     public void disconnect(final String name, final boolean tearDown) throws Exception {
286         ServerConnection connection = (ServerConnection)connectionMap.remove(name);
287         if (null == connection) {
288             throw new IllegalArgumentException("No such connection with name " + name);
289         }
290         
291         connection.dispose();
292     }
293     
294   
295     
296 
297 
298     public void connect(String name, ServerSocket socket, ConnectionHandlerFactory handlerFactory, ThreadPool threadPool, int maxOpenConnections) throws Exception {
299         connect(name,socket,handlerFactory,threadPool,maxOpenConnections,maxOpenConnPerIP);
300     }
301   
302     
303     
304 
305 
306     public void connect(String name, ServerSocket socket, ConnectionHandlerFactory handlerFactory, int maxOpenConnections,int maxOpenConnectionsPerIP) throws Exception {
307         connect(name,socket,handlerFactory,threadManager.getDefaultThreadPool(),maxOpenConnections,maxOpenConnectionsPerIP);
308     }
309     
310     
311     
312 
313 
314 
315 
316 
317     public int getMaximumNumberOfOpenConnections() {
318         return maxOpenConn;
319     }
320     
321     
322     
323 
324 
325     public int getMaximumNumberOfOpenConnectionsPerIP() {
326         return maxOpenConnPerIP;
327     }
328 
329 }