001 package users;
002
003 import java.io.*;
004
005 import java.util.*;
006
007 import users.events.*;
008 import util.*;
009
010 /**
011 * Manages users, their capabilities and their associations to other objects.
012 *
013 * <p>The UserManager provides possibilities to manage any number of users. Users can
014 * be added, retrieved using their name to identify them, and removed from the system.
015 * Additionally, users can be associated to, and disassociated from, any object. Their can be a maximum of
016 * one user associated to any given object at any given time.</p>
017 *
018 * <p>You can provide a set of default capabilities, that every new user will be provided with.</p>
019 *
020 * @see User
021 * @see #setDefaultCaps
022 * @see sale.SalesPoint
023 * @see #logOn
024 *
025 * @author Steffen Zschaler
026 * @version 2.0 05/05/1999
027 * @since v2.0
028 */
029 public class UserManager extends Object implements Serializable {
030
031 /**
032 * ID for serialization.
033 */
034 private static final long serialVersionUID = 6314914692181586859L;
035
036 /**
037 * The map used to store all the users managed by this UserManager.
038 *
039 * <p>The user's name is being used as the key. The user itself is being stored as
040 * the value.</p>
041 *
042 * @see User
043 *
044 * @serial
045 */
046 private SortedMap<String, User> m_mpUsers = new TreeMap<String, User>();
047
048 /**
049 * The map used to store all the users currently associated to some object.
050 *
051 * <p>The key of the map is the object to which a given user is associated.
052 * The user itself is being stored as the value.</p>
053 *
054 * @see User
055 * @see #logOn
056 *
057 * @serial
058 */
059 private Map<Object, User> m_mpCurrentUsers = new HashMap<Object, User>();
060
061 /**
062 * The map of default capabilities to be associated with each new user.
063 *
064 * <p>The keys and values are being used in the same way as {@link User} uses them, i.e.
065 * the capabilities names are used as keys and the capabilities themselves as
066 * values.</p>
067 *
068 * @see #setDefaultCaps
069 * @see Capability
070 * @see User#setCapabilities
071 *
072 * @serial
073 */
074 private Map<String, Capability> m_mpDefaultCaps = new HashMap<String, Capability>();
075
076 /**
077 * The factory used to create new User objects.
078 *
079 * @see #createUser
080 * @see #setUserCreator
081 * @see User
082 *
083 * @serial
084 */
085 private UserCreator m_ucCreator;
086
087 /**
088 * The list of listeners registered with this UserManager.
089 *
090 * @serial See <a href="#util.ListenerHelper">ListenerHelper's serializable form</a> for more information on
091 * what listeners get a chance to be serialized.
092 */
093 protected ListenerHelper m_lhListeners = new ListenerHelper();
094
095 /**
096 * Create a new UserManager with an empty set of default capabilities, managing direct
097 * instances of the User class.
098 *
099 * @see #setDefaultCaps
100 * @see #createUser
101 */
102 public UserManager() {
103 this(null, null);
104 }
105
106 /**
107 * Create a new UserManager, using a specific set of default capabilities. This
108 * UserManager will manage direct instances of User.
109 *
110 * @param mpDefaultCaps a map describing the default capabilities any new user should
111 * have. The keys of this map should be the name of their associated capability. Specifying
112 * <code>null</code> will result in there being no default capabilities.
113 *
114 * @see #setDefaultCaps
115 * @see #createUser
116 * @see Capability
117 */
118 public UserManager(Map<String, Capability> mpDefaultCaps) {
119 this(mpDefaultCaps, null);
120 }
121
122 /**
123 * Create a new UserManager with an empty set of default capabilities. This UserManager
124 * will create instances of a developer defined subclass of User.
125 *
126 * @param ucCreator the factory to be used to create new User objects. Specifying
127 * <code>null</code> will result in a default implementation being used, which will
128 * create direct instances of the User class.
129 *
130 * @see #setDefaultCaps
131 * @see #createUser
132 */
133 public UserManager(UserCreator ucCreator) {
134 this(null, ucCreator);
135 }
136
137 /**
138 * Create a new UserManager providing both a set of default capabilities and a User
139 * creation factory.
140 *
141 * @param mpDefaultCaps a map describing the default capabilities any new user should
142 * have. The keys of this map should be the name of their associated capability. Specifying
143 * <code>null</code> will result in there being no default capabilities.
144 * @param ucCreator the factory to be used to create new User objects. Specifying
145 * <code>null</code> will result in a default implementation being used, which will
146 * create direct instances of the User class.
147 *
148 * @see #setDefaultCaps
149 * @see Capability
150 * @see #createUser
151 * @see User
152 */
153 public UserManager(Map<String, Capability> mpDefaultCaps, UserCreator ucCreator) {
154 super();
155
156 setDefaultCaps(mpDefaultCaps);
157 setUserCreator(ucCreator);
158 }
159
160 /**
161 * Set the factory to be used when creating new User objects.
162 *
163 * @param ucCreator the factory to be used to create new User objects. Specifying
164 * <code>null</code> will result in a default implementation being used, which will
165 * create direct instances of the User class.
166 *
167 * @see #createUser
168 * @see User
169 *
170 * @override Never
171 */
172 public synchronized void setUserCreator(UserCreator ucCreator) {
173 if (ucCreator != null) {
174 m_ucCreator = ucCreator;
175 } else {
176 m_ucCreator = new UserCreator();
177 }
178 }
179
180 /**
181 * Specify the set of default capabilities to be used when creating new User objects.
182 *
183 * <p>Calling this method will not influence the capabilities of users already created.</p>
184 *
185 * @param mpDefaultCaps a map describing the default capabilities any new user should
186 * have. The keys of this map should be the name of their associated capability. Specifying
187 * <code>null</code> will result in there being no default capabilities.
188 *
189 * @see #createUser
190 * @see Capability
191 *
192 * @override Never
193 */
194 public synchronized void setDefaultCaps(Map<String, Capability> mpDefaultCaps) {
195 if (mpDefaultCaps != null) {
196 m_mpDefaultCaps = new HashMap<String, Capability>(mpDefaultCaps);
197 } else {
198 m_mpDefaultCaps = new HashMap<String, Capability>();
199 }
200 }
201
202 /**
203 * Set a capability to be used as a default capability henceforward.
204 *
205 * <p>Calling this method will not influence the capabilities of users already created.</p>
206 *
207 * <p>If a default capability of the same name as the one given did already exist, it
208 * will be replaced by the new capability.</p>
209 *
210 * @param cap the capability to be set as a default capability.
211 *
212 * @see #createUser
213 *
214 * @override Never
215 */
216 public synchronized void setDefaultCapability(Capability cap) {
217 m_mpDefaultCaps.put(cap.getName(), cap);
218 }
219
220 /**
221 * Create a new user to be managed by this UserManager.
222 *
223 * <p>This method uses the defined {@link UserCreator} (see {@link #setUserCreator}) to create the
224 * new <code>User</code> object. The new user will later be accessible using its name.</p>
225 *
226 * <p>The newly created user will get all the default capabilities defined at the time
227 * this method is called.</p>
228 *
229 * <p>A <code>userAdded</code> event will be received by any {@link UserDataListener} that
230 * registered an interest in this <code>UserManager</code>.</p>
231 *
232 * @param sName the name of the new user. This must be unique, i.e. there must not be
233 * a user with the same name already managed by this UserManager.
234 *
235 * @return the newly created user.
236 *
237 * @exception DuplicateUserException if there already was a user with the given name.
238 *
239 * @see #setDefaultCaps
240 * @see #setUserCreator
241 * @see User
242 * @see UserCreator#createUser
243 * @see users.events.UserDataListener#userAdded
244 *
245 * @override Never Rather than overriding this method, you should provide a new {@link UserCreator}.
246 */
247 public synchronized User createUser(String sName) {
248
249 if (m_mpUsers.containsKey(sName)) {
250 throw new DuplicateUserException("User \"" + sName +
251 "\" already exists ! Cannot have two users with the same user name.");
252 }
253
254 User usr = m_ucCreator.createUser(sName);
255
256 usr.setCapabilities(m_mpDefaultCaps);
257
258 m_mpUsers.put(sName, usr);
259
260 fireUserAdded(usr);
261
262 return usr;
263 }
264
265 /**
266 * Add a user to the UserManager.
267 *
268 * <p>A <code>userAdded</code> event will be received by any {@link UserDataListener} that
269 * registered an interest in this UserManager.</p>
270 *
271 * @param usr the user to be added.
272 *
273 * @exception DuplicateUserException if there already is a user of the same name.
274 *
275 * @see users.events.UserDataListener#userAdded
276 *
277 * @override Never
278 */
279 public synchronized void addUser(User usr) {
280
281 if (m_mpUsers.containsKey(usr.getName())) {
282 throw new DuplicateUserException("User \"" + usr.getName() +
283 "\" already exists ! Cannot have two users with the same user name.");
284 }
285
286 m_mpUsers.put(usr.getName(), usr);
287
288 fireUserAdded(usr);
289 }
290
291 /**
292 * Retrieve a user by name.
293 *
294 * <p>If no user with the given name exists, this method will return <code>null</code>.</p>
295 *
296 * @param sName the name of the user looked for.
297 *
298 * @return the user corresponding to the given name, if any. <code>null</code> will
299 * be returned if no such user can be found.
300 *
301 * @see #createUser
302 *
303 * @override Never
304 */
305 public synchronized User getUser(String sName) {
306 return (User)m_mpUsers.get(sName);
307 }
308
309 /**
310 * Return all user names registered with this UserManager.
311 *
312 * <p>The returned set is backed by the UserManager, i.e. it will reflect changes
313 * made through <code>createUser()</code> or <code>removeUser()</code>. The set itself
314 * is unmodifiable and ordered alphabetically.</p>
315 *
316 * @return an unmodifiable, ordered set of all user names in this UserManager.
317 *
318 * @see #createUser
319 * @see #deleteUser
320 *
321 * @override Never
322 */
323 public synchronized Set<String> getUserNames() {
324 return Collections.unmodifiableSet(m_mpUsers.keySet());
325 }
326
327 /**
328 * Return all users registered with this UserManager.
329 *
330 * <p>The returned collection is backed by the UserManager, i.e. it will reflect
331 * changes made through <code>createUser()</code> or <code>removeUser()</code>. The
332 * collection itself is unmodifiable and ordered alphabetically by the users' names.</p>
333 *
334 * @return an unmodifiable, ordered set of all users in this UserManager.
335 *
336 * @see #createUser
337 * @see #deleteUser
338 *
339 * @override Never
340 */
341 public synchronized Collection<User> getUsers() {
342 return Collections.unmodifiableCollection(m_mpUsers.values());
343 }
344
345 /**
346 * Delete a user from this UserManager.
347 *
348 * <p>The user will be removed from the UserManager and will no longer be available
349 * via {@link #getUser}. A <code>userDeleted</code> event will be received by all
350 * {@link UserDataListener UserDataListeners} registered with this UserManager if a user was removed. If no user
351 * with the given name existed no exception will be thrown and no event will be fired.</p>
352 *
353 * <p>If the user is currently associated to some object, it will stay so until
354 * it is disassociated explicitly. It will not have the possibility to log in again,
355 * though.</p>
356 *
357 * @param sName the name of the user to be removed
358 *
359 * @return the user that was just removed or <code>null</code> if none.
360 *
361 * @see users.events.UserDataListener#userDeleted
362 *
363 * @override Never
364 */
365 public synchronized User deleteUser(String sName) {
366 User usrReturn = (User)m_mpUsers.remove(sName);
367
368 if (usrReturn != null) {
369 fireUserDeleted(usrReturn);
370 }
371
372 return usrReturn;
373 }
374
375 /**
376 * Add a UserDataListener. UserDataListeners will receive an event whenever a user
377 * was created or removed.
378 *
379 * @param udl the UserDataListener to add.
380 *
381 * @override Never
382 */
383 public void addUserDataListener(UserDataListener udl) {
384 m_lhListeners.add(UserDataListener.class, udl);
385 }
386
387 /**
388 * Remove a UserDataListener.
389 *
390 * @param udl the UserDataListener to remove.
391 *
392 * @override Never
393 */
394 public void removeUserDataListener(UserDataListener udl) {
395 m_lhListeners.remove(UserDataListener.class, udl);
396 }
397
398 /**
399 * Fire a <code>userAdded</code> event to all interested listeners.
400 *
401 * @param usr the user that was added.
402 *
403 * @override Never
404 */
405 protected void fireUserAdded(User usr) {
406 UserDataEvent ude = null;
407 // Guaranteed to return a non-null array
408 Object[] listeners = m_lhListeners.getListenerList();
409 // Process the listeners last to first, notifying
410 // those that are interested in this event
411 for (int i = listeners.length - 2; i >= 0; i -= 2) {
412 if (listeners[i] == UserDataListener.class) {
413 // Lazily create the event:
414 if (ude == null) {
415 ude = new UserDataEvent(this, usr);
416
417 }
418 ((UserDataListener)listeners[i + 1]).userAdded(ude);
419 }
420 }
421 }
422
423 /**
424 * Fire a <code>userDeleted</code> event to all interested listeners.
425 *
426 * @param usr the user that was deleted.
427 *
428 * @override Never
429 */
430 protected void fireUserDeleted(User usr) {
431 UserDataEvent ude = null;
432
433 // Guaranteed to return a non-null array
434 Object[] listeners = m_lhListeners.getListenerList();
435
436 // Process the listeners last to first, notifying
437 // those that are interested in this event
438 for (int i = listeners.length - 2; i >= 0; i -= 2) {
439 if (listeners[i] == UserDataListener.class) {
440 // Lazily create the event:
441 if (ude == null) {
442 ude = new UserDataEvent(this, usr);
443
444 }
445 ((UserDataListener)listeners[i + 1]).userDeleted(ude);
446 }
447 }
448 }
449
450 /**
451 * Associate a user with an object.
452 *
453 * <p>Only one user at a time can be associated with one Object. If there is already
454 * another user associated with the given Object, its association is undone and the
455 * user is returned.</p>
456 *
457 * <p>Only users that are actually managed by this UserManager can be logged in. An
458 * exception will be thrown if you try to log in a user that is unknown to this
459 * UserManager. Especially, this can happen if you try to log in a user that was
460 * previously removed using {@link #deleteUser}.</p>
461 *
462 * @param o the Object with which to associate the user.
463 * @param u the user to associate with the Object
464 *
465 * @return the user that was previously associated with the Object or
466 * <code>null</code> if none.
467 *
468 * @exception UnknownUserException if the user to log in is not known at this
469 * UserManager. A user is known at a UserManager, if the User object is registered,
470 * i.e. no <code>equals()</code> method of any kind is called.
471 *
472 * @see User#loggedOn
473 *
474 * @override Never
475 */
476 public synchronized User logOn(Object o, User u) {
477
478 User usrTemp = getUser(u.getName());
479
480 if ((usrTemp == null) || (usrTemp != u)) {
481 throw new UnknownUserException(u.getName());
482 }
483
484 User usrReturn = logOff(o);
485
486 if (u != null) {
487 m_mpCurrentUsers.put(o, u);
488
489 u.loggedOn(o);
490 }
491
492 return usrReturn;
493 }
494
495 /**
496 * Disassociate the current user from an Object.
497 *
498 * @param o the Object from which to disassociate a user.
499 *
500 * @return the user just logged off or <code>null</code> if none.
501 *
502 * @see User#loggedOff
503 *
504 * @override Never
505 */
506 public synchronized User logOff(Object o) {
507 User u = (User)m_mpCurrentUsers.remove(o);
508
509 if (u != null) {
510 u.loggedOff(o);
511 }
512
513 return u;
514 }
515
516 /**
517 * Retrieve the user currently associated with some Object.
518 *
519 * @param o the Object with which the searched user must be associated.
520 *
521 * @return the user associated with the given Object or <code>null</code> if none.
522 *
523 * @override Never
524 */
525 public synchronized User getCurrentUser(Object o) {
526 return (User)m_mpCurrentUsers.get(o);
527 }
528
529 ////////////////////////////////////////////////////////////////////////////////////////////
530 // STATIC PART
531 ////////////////////////////////////////////////////////////////////////////////////////////
532
533 /**
534 * The global UserManager.
535 */
536 private static UserManager s_umGlobal = new UserManager();
537
538 /**
539 * Get the global UserManager.
540 *
541 * <p>The global UserManager can be used as a centralized instance to manage all the
542 * users in an application.</p>
543 *
544 * @return the global UserManager.
545 */
546 public static synchronized UserManager getGlobalUM() {
547 return s_umGlobal;
548 }
549
550 /**
551 * Set a new UserManager to be the global UserManager from now on.
552 *
553 * @param umNew the new global UserManager.
554 *
555 * @return the previous UserManager.
556 */
557 public static synchronized UserManager setGlobalUM(UserManager umNew) {
558 //UserManager umReturn = s_umGlobal;
559
560 s_umGlobal = umNew;
561
562 return s_umGlobal;
563 }
564 }