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 }