1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2000-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: JmsServerConnectionManager.java,v 1.10 2003/08/17 01:32:26 tanderson Exp $
44 *
45 * Date Author Changes
46 * 04/07/2000 jima Created
47 */
48 package org.exolab.jms.server;
49
50
51 import java.util.Collections;
52 import java.util.HashMap;
53 import java.util.Iterator;
54 import java.util.Map;
55
56 import javax.jms.JMSException;
57 import javax.jms.JMSSecurityException;
58
59 import org.apache.commons.logging.Log;
60 import org.apache.commons.logging.LogFactory;
61
62 import org.exolab.core.foundation.HandleIfc;
63 import org.exolab.jms.authentication.AuthenticationMgr;
64 import org.exolab.jms.events.BasicEventManager;
65 import org.exolab.jms.events.Event;
66 import org.exolab.jms.events.EventHandler;
67 import org.exolab.jms.events.IllegalEventDefinedException;
68
69
70 /***
71 * The connection manager is responsible for managing all connections to the
72 * JmsServer. The connection manager is a singleton (at this point anyway)
73 * that is accessible through the instance class method. It is also responsible
74 * for holding a list of connections.
75 * <p>
76 * A client uses a client identifier to create a connection and a connection
77 * type to identify the connection type- queue or topic.
78 * <p>
79 * TODO:
80 * Look at leasing connections and timing them out.
81 *
82 * @version $Revision: 1.10 $ $Date: 2003/08/17 01:32:26 $
83 * @author <a href="mailto:jima@exoffice.com">Jim Alateras</a>
84 * @see JmsServerConnection
85 */
86 public class JmsServerConnectionManager
87 implements EventHandler {
88
89 /***
90 * The interval that garbage collection on the connection manager is
91 * executed to clean up abnormally terminated connections. This defaults
92 * to every minute.
93 */
94 private long _gcInterval = 60 * 1000;
95
96 /***
97 * holds a list of active connections
98 */
99 private Map _connections = null;
100
101 /***
102 * Holds the singleton instance of the class
103 */
104 private static JmsServerConnectionManager _instance = null;
105
106 /***
107 * Used to stop multiple threads trying to init the singleton
108 */
109 private static final Object _initializer = new Object();
110
111 /***
112 * This is the event that is fired to initiate garbage collection
113 * in the database
114 */
115 private static final int CONNECTION_GC_EVENT = 1;
116
117 /***
118 * The logger
119 */
120 private static final Log _log =
121 LogFactory.getLog(JmsServerConnectionManager.class);
122
123 /***
124 * The private constructor initialises the manager.
125 */
126 private JmsServerConnectionManager() {
127 _connections = Collections.synchronizedMap(new HashMap());
128
129 // check to see whether the gcInterval has been overriden
130 if (System.getProperty("org.exolab.jms.connection.gcInterval") != null) {
131 try {
132 _gcInterval = Long.parseLong(System.getProperty(
133 "org.exolab.jms.connection.gcInterval"));
134 } catch (Exception ignore) {
135 // if the gcinterval is incorrectly specified then use
136 // the default
137 }
138 }
139
140 if (_gcInterval > 0) {
141 registerEvent();
142 }
143 }
144
145 /***
146 * The static method returns the singleton instance of the
147 * JmsConnectionManager. If one does not exist it is created prior to
148 * returning.
149 *
150 * @return JmsConnectionManager
151 */
152 public static JmsServerConnectionManager instance() {
153
154 if (_instance == null) {
155 synchronized (_initializer) {
156 if (_instance == null) {
157 _instance = new JmsServerConnectionManager();
158 }
159 }
160 }
161
162 return _instance;
163 }
164
165 /***
166 * Create a connection with the specified client id. If the client already
167 * has an open connection then simply return a reference to this connection
168 * If a connection already exists for the specified client identity then
169 * simply return the exisiting connection
170 *
171 * @param id the client identity
172 * @param username the client's username
173 * @param password the client's password
174 * @return a new connection
175 * @throws JMSSecurityException if the client cannot be authenticated
176 * @throws JMSException if the connection cannot be created
177 */
178 public JmsServerConnection createConnection(String id, String username,
179 String password)
180 throws JMSSecurityException, JMSException {
181
182 if (!AuthenticationMgr.instance().validateUser(username, password)) {
183 throw new JMSSecurityException("Failed to authenticate user " +
184 username);
185 }
186
187 JmsServerConnection result = (JmsServerConnection) _connections.get(id);
188 if (result == null) {
189 result = new JmsServerConnection(id);
190
191 // the connection is created in the stopped mode and is the
192 // added the list of connections
193 _connections.put(id, result);
194 }
195
196 return result;
197 }
198
199 /***
200 * Return an Enumeration of all the connections currently registered with
201 * the connection manager
202 *
203 * @return Iterator
204 */
205 public Iterator getConnections() {
206 return _connections.values().iterator();
207 }
208
209 /***
210 * Return the connection associated with a particular client identity. If
211 * such a connection does not exist then return null
212 *
213 * @param id identity of the client
214 * @return JmsConnection associated connection or null
215 */
216 public JmsServerConnection getConnection(String id) {
217 return (JmsServerConnection) _connections.get(id);
218 }
219
220 /***
221 * Close the connection associated with a particular client identity. If
222 * a connection for the client does not exist then do nothing.
223 *
224 * @param id identity of the client
225 */
226 public void closeConnection(String id) {
227 JmsServerConnection connection =
228 (JmsServerConnection) _connections.remove(id);
229
230 if (connection != null) {
231 connection.close();
232 }
233 }
234
235 // implementation of EventHandler.handleEvent
236 public void handleEvent(int event, Object callback, long time) {
237 try {
238 Object[] ids = _connections.keySet().toArray();
239 for (int index = 0; index < ids.length; index++) {
240 JmsServerConnection connection =
241 (JmsServerConnection) _connections.get(ids[index]);
242 if ((connection != null) &&
243 (!connection.isClientEndpointActive())) {
244 _log.info("Cleaning up connection " + ids[index]);
245 closeConnection((String) ids[index]);
246 }
247 }
248 } finally {
249 registerEvent();
250 }
251 }
252
253 // implementation of EventHandler.getHandle
254 public HandleIfc getHandle() {
255 // not used
256 return null;
257 }
258
259 /***
260 * Register an event with the event service. The event will tell the
261 * connection manager to initiate garbage collection
262 */
263 private void registerEvent() {
264 try {
265 BasicEventManager.instance().registerEventRelative(
266 new Event(CONNECTION_GC_EVENT, this, null),
267 _gcInterval);
268 } catch (IllegalEventDefinedException exception) {
269 _log.error("JmsServerConnectionManager.registerEvent failed",
270 exception);
271 }
272 }
273
274 } //-- JmsServerConnectionManager
275
This page was automatically generated by Maven