View Javadoc

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 2003-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: UserManager.java,v 1.4 2005/12/23 12:17:45 tanderson Exp $
44   */
45  package org.exolab.jms.authentication;
46  
47  import java.sql.Connection;
48  import java.util.Enumeration;
49  import java.util.HashMap;
50  import java.util.Iterator;
51  
52  import org.apache.commons.logging.Log;
53  import org.apache.commons.logging.LogFactory;
54  
55  import org.exolab.jms.config.Configuration;
56  import org.exolab.jms.config.SecurityConfiguration;
57  import org.exolab.jms.persistence.DatabaseService;
58  import org.exolab.jms.persistence.PersistenceAdapter;
59  import org.exolab.jms.persistence.PersistenceException;
60  import org.exolab.jms.service.Service;
61  import org.exolab.jms.service.ServiceException;
62  
63  
64  /***
65   * The user manager is responsible for creating and managing users.
66   *
67   * @author <a href="mailto:knut@lerpold.no">Knut Lerpold</a>
68   * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
69   * @version $Revision: 1.4 $ $Date: 2005/12/23 12:17:45 $
70   */
71  public class UserManager extends Service {
72  
73      /***
74       * Map of username -> User instances.
75       */
76      private HashMap _userCache = new HashMap();
77  
78      /***
79       * The configuration.
80       */
81      private final Configuration _config;
82  
83      /***
84       * The database service.
85       */
86      private final DatabaseService _database;
87  
88      /***
89       * The logger.
90       */
91      private static final Log _log = LogFactory.getLog(UserManager.class);
92  
93  
94      /***
95       * Construct a new <code>UserManager</code>.
96       *
97       * @param config   the configuration
98       * @param database the database service
99       */
100     public UserManager(Configuration config, DatabaseService database) {
101         if (config == null) {
102             throw new IllegalArgumentException("Argument 'config' is null");
103         }
104         if (database == null) {
105             throw new IllegalArgumentException("Argument 'database' is null");
106         }
107         _config = config;
108         _database = database;
109     }
110 
111     /***
112      * Create a new user.
113      *
114      * @param user the user to create
115      * @return <code>true</code> if the user is created otherwise
116      *         <code>false</code>
117      */
118     public synchronized boolean createUser(User user) {
119         boolean success = false;
120         PersistenceAdapter adapter = _database.getAdapter();
121 
122         if (_userCache.get(user.getUsername()) == null) {
123             try {
124                 _database.begin();
125                 Connection connection = _database.getConnection();
126                 adapter.addUser(connection, user);
127                 addToUserCache(user);
128                 _database.commit();
129                 success = true;
130             } catch (Exception exception) {
131                 _log.error("Failed to create user", exception);
132                 try {
133                     _database.rollback();
134                 } catch (PersistenceException error) {
135                     _log.error(error, error);
136                 }
137             }
138         }
139 
140         return success;
141     }
142 
143     /***
144      * Update an user. Only possible update is password.
145      *
146      * @param user the user to update
147      * @return <code>true</code> if password is updated otherwise
148      *         <code>false</code>
149      */
150     public synchronized boolean updateUser(User user) {
151         boolean success = false;
152         PersistenceAdapter adapter = _database.getAdapter();
153 
154         if (_userCache.get(user.getUsername()) != null) {
155             try {
156                 _database.begin();
157                 Connection connection = _database.getConnection();
158                 adapter.updateUser(connection, user);
159                 _database.commit();
160                 addToUserCache(user);
161                 success = true;
162             } catch (Exception exception) {
163                 _log.error("Failed to update user", exception);
164                 rollback();
165             }
166         }
167 
168         return success;
169     }
170 
171     /***
172      * Delete an user.
173      *
174      * @param user the userobject containing the username
175      * @return <code>true</code> if the is removed otherwise <code>false</code>
176      */
177     public synchronized boolean deleteUser(User user) {
178         boolean success = false;
179         PersistenceAdapter adapter = _database.getAdapter();
180 
181         if (_userCache.get(user.getUsername()) != null) {
182             try {
183                 _database.begin();
184                 Connection connection = _database.getConnection();
185                 adapter.removeUser(connection, user);
186                 removeFromUserCache(user);
187                 success = true;
188                 _database.commit();
189             } catch (Exception exception) {
190                 _log.error("Failed to remove user", exception);
191                 rollback();
192             }
193         }
194         return success;
195     }
196 
197     /***
198      * Return a user.
199      *
200      * @param user the user  containing the username
201      * @return the user, or <code>null</code> if none exists.
202      */
203     public synchronized User getUser(User user) {
204         return (User) _userCache.get(user.getUsername());
205     }
206 
207     /***
208      * Return a list of user names currently supported by the user manager. This
209      * includes all types of users.
210      *
211      * @return an enumeration of the user names
212      */
213     public Iterator userNames() {
214         return _userCache.keySet().iterator();
215     }
216 
217     /***
218      * Determines if a user's name and password are valid.
219      *
220      * @param username the user's name
221      * @param password the user's password
222      * @return <code>true</code> if the name and password are valid, otherwise
223      *         <code>false</code>
224      */
225     public synchronized boolean validateUser(String username,
226                                              String password) {
227         boolean result = false;
228 
229         SecurityConfiguration config = _config.getSecurityConfiguration();
230         if (!config.getSecurityEnabled()) {
231             // security disabled
232             result = true;
233         } else {
234             User user = (User) _userCache.get(username);
235             if (user != null && user.getPassword().equals(password)) {
236                 result = true;
237             }
238         }
239 
240         return result;
241     }
242 
243     /***
244      * Start the service.
245      *
246      * @throws ServiceException if the service fails to start
247      */
248     protected void doStart() throws ServiceException {
249         init();
250     }
251 
252     /***
253      * Stop the service.
254      */
255     protected synchronized void doStop() {
256         _userCache.clear();
257     }
258 
259     /***
260      * Initialise user manager.
261      *
262      * @throws ServiceException if the user manager cannot be initialised
263      */
264     protected void init() throws ServiceException {
265         try {
266             _database.begin();
267             Connection connection = _database.getConnection();
268 
269             Enumeration iter = _database.getAdapter().getAllUsers(connection);
270             _database.commit();
271 
272             while (iter.hasMoreElements()) {
273                 // add each user to the cache
274                 User user = (User) iter.nextElement();
275                 addToUserCache(user);
276             }
277         } catch (Exception exception) {
278             _log.error("Failed to initialise UserManager", exception);
279             rollback();
280             throw new ServiceException(exception);
281         }
282 
283         registerConfiguredUsers();
284     }
285 
286     /***
287      * Add the specified entry to the user cache.
288      *
289      * @param user the user to add
290      */
291     protected void addToUserCache(User user) {
292         _userCache.put(user.getUsername(), user);
293     }
294 
295     /***
296      * Remove the specified user from the cache.
297      *
298      * @param user the user to remove
299      */
300     protected void removeFromUserCache(User user) {
301         _userCache.remove(user.getUsername());
302     }
303 
304     /***
305      * Registers users specified in the configuration.
306      */
307     protected void registerConfiguredUsers() {
308         if (_config.getUsers() != null) {
309             org.exolab.jms.config.User[] users = _config.getUsers().getUser();
310             for (int i = 0; i < users.length; ++i) {
311                 User user = new User(users[i].getName(),
312                                      users[i].getPassword());
313                 createUser(user);
314             }
315         }
316     }
317 
318     /***
319      * Rollback the current transaction, logging any error.
320      */
321     private void rollback() {
322         try {
323             _database.rollback();
324         } catch (PersistenceException exception) {
325             _log.error(exception, exception);
326         }
327     }
328 
329 }