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 }