1 package org.apache.turbine.services.security;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.List;
20 import java.util.Map;
21
22 import javax.servlet.ServletConfig;
23
24 import org.apache.commons.configuration.Configuration;
25
26 import org.apache.commons.lang.StringUtils;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.apache.torque.util.Criteria;
32
33 import org.apache.turbine.om.security.Group;
34 import org.apache.turbine.om.security.Permission;
35 import org.apache.turbine.om.security.Role;
36 import org.apache.turbine.om.security.User;
37 import org.apache.turbine.services.InitializationException;
38 import org.apache.turbine.services.TurbineBaseService;
39 import org.apache.turbine.services.TurbineServices;
40 import org.apache.turbine.services.crypto.CryptoAlgorithm;
41 import org.apache.turbine.services.crypto.CryptoService;
42 import org.apache.turbine.services.crypto.TurbineCrypto;
43 import org.apache.turbine.services.factory.FactoryService;
44 import org.apache.turbine.util.security.AccessControlList;
45 import org.apache.turbine.util.security.DataBackendException;
46 import org.apache.turbine.util.security.EntityExistsException;
47 import org.apache.turbine.util.security.GroupSet;
48 import org.apache.turbine.util.security.PasswordMismatchException;
49 import org.apache.turbine.util.security.PermissionSet;
50 import org.apache.turbine.util.security.RoleSet;
51 import org.apache.turbine.util.security.UnknownEntityException;
52
53 /***
54 * This is a common subset of SecurityService implementation.
55 *
56 * Provided functionality includes:
57 * <ul>
58 * <li> methods for retrieving User objects, that delegates functionality
59 * to the pluggable implementations of the User interface.
60 * <li> synchronization mechanism for methods reading/modifying the security
61 * information, that guarantees that multiple threads may read the
62 * information concurrently, but threads that modify the information
63 * acquires exclusive access.
64 * <li> implementation of convenience methods for retrieving security entities
65 * that maintain in-memory caching of objects for fast access.
66 * </ul>
67 *
68 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
69 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
70 * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a>
71 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
72 * @version $Id: BaseSecurityService.java 264148 2005-08-29 14:21:04Z henning $
73 */
74 public abstract class BaseSecurityService
75 extends TurbineBaseService
76 implements SecurityService
77 {
78 /*** The number of threads concurrently reading security information */
79 private int readerCount = 0;
80
81 /*** The instance of UserManager the SecurityService uses */
82 private UserManager userManager = null;
83
84 /*** The class of User the SecurityService uses */
85 private Class userClass = null;
86
87 /*** The class of Group the SecurityService uses */
88 private Class groupClass = null;
89
90 /*** The class of Permission the SecurityService uses */
91 private Class permissionClass = null;
92
93 /*** The class of Role the SecurityService uses */
94 private Class roleClass = null;
95
96 /*** The class of ACL the SecurityService uses */
97 private Class aclClass = null;
98
99 /*** A factory to construct ACL Objects */
100 private FactoryService aclFactoryService = null;
101
102 /***
103 * The Group object that represents the <a href="#global">global group</a>.
104 */
105 private static Group globalGroup = null;
106
107 /*** Logging */
108 private static Log log = LogFactory.getLog(BaseSecurityService.class);
109
110 /***
111 * This method provides client-side encryption of passwords.
112 *
113 * If <code>secure.passwords</code> are enabled in TurbineResources,
114 * the password will be encrypted, if not, it will be returned unchanged.
115 * The <code>secure.passwords.algorithm</code> property can be used
116 * to chose which digest algorithm should be used for performing the
117 * encryption. <code>SHA</code> is used by default.
118 *
119 * @param password the password to process
120 * @return processed password
121 */
122 public String encryptPassword(String password)
123 {
124 return encryptPassword(password, null);
125 }
126
127 /***
128 * This method provides client-side encryption of passwords.
129 *
130 * If <code>secure.passwords</code> are enabled in TurbineResources,
131 * the password will be encrypted, if not, it will be returned unchanged.
132 * The <code>secure.passwords.algorithm</code> property can be used
133 * to chose which digest algorithm should be used for performing the
134 * encryption. <code>SHA</code> is used by default.
135 *
136 * The used algorithms must be prepared to accept null as a
137 * valid parameter for salt. All algorithms in the Fulcrum Cryptoservice
138 * accept this.
139 *
140 * @param password the password to process
141 * @param salt algorithms that needs a salt can provide one here
142 * @return processed password
143 */
144
145 public String encryptPassword(String password, String salt)
146 {
147 if (password == null)
148 {
149 return null;
150 }
151 String secure = getConfiguration().getString(
152 SecurityService.SECURE_PASSWORDS_KEY,
153 SecurityService.SECURE_PASSWORDS_DEFAULT).toLowerCase();
154
155 String algorithm = getConfiguration().getString(
156 SecurityService.SECURE_PASSWORDS_ALGORITHM_KEY,
157 SecurityService.SECURE_PASSWORDS_ALGORITHM_DEFAULT);
158
159 CryptoService cs = TurbineCrypto.getService();
160
161 if (cs != null && (secure.equals("true") || secure.equals("yes")))
162 {
163 try
164 {
165 CryptoAlgorithm ca = cs.getCryptoAlgorithm(algorithm);
166
167 ca.setSeed(salt);
168
169 String result = ca.encrypt(password);
170
171 return result;
172 }
173 catch (Exception e)
174 {
175 log.error("Unable to encrypt password: ", e);
176
177 return null;
178 }
179 }
180 else
181 {
182 return password;
183 }
184 }
185
186 /***
187 * Checks if a supplied password matches the encrypted password
188 *
189 * @param checkpw The clear text password supplied by the user
190 * @param encpw The current, encrypted password
191 *
192 * @return true if the password matches, else false
193 *
194 */
195
196 public boolean checkPassword(String checkpw, String encpw)
197 {
198 String result = encryptPassword(checkpw, encpw);
199
200 return (result == null) ? false : result.equals(encpw);
201 }
202
203 /***
204 * Initializes the SecurityService, locating the apropriate UserManager
205 * This is a zero parameter variant which queries the Turbine Servlet
206 * for its config.
207 *
208 * @throws InitializationException Something went wrong in the init stage
209 */
210 public void init()
211 throws InitializationException
212 {
213 Configuration conf = getConfiguration();
214
215 String userManagerClassName = conf.getString(
216 SecurityService.USER_MANAGER_KEY,
217 SecurityService.USER_MANAGER_DEFAULT);
218
219 String userClassName = conf.getString(
220 SecurityService.USER_CLASS_KEY,
221 SecurityService.USER_CLASS_DEFAULT);
222
223 String groupClassName = conf.getString(
224 SecurityService.GROUP_CLASS_KEY,
225 SecurityService.GROUP_CLASS_DEFAULT);
226
227 String permissionClassName = conf.getString(
228 SecurityService.PERMISSION_CLASS_KEY,
229 SecurityService.PERMISSION_CLASS_DEFAULT);
230
231 String roleClassName = conf.getString(
232 SecurityService.ROLE_CLASS_KEY,
233 SecurityService.ROLE_CLASS_DEFAULT);
234
235 String aclClassName = conf.getString(
236 SecurityService.ACL_CLASS_KEY,
237 SecurityService.ACL_CLASS_DEFAULT);
238
239 try
240 {
241 userClass = Class.forName(userClassName);
242 groupClass = Class.forName(groupClassName);
243 permissionClass = Class.forName(permissionClassName);
244 roleClass = Class.forName(roleClassName);
245 aclClass = Class.forName(aclClassName);
246 }
247 catch (Exception e)
248 {
249 if (userClass == null)
250 {
251 throw new InitializationException(
252 "Failed to create a Class object for User implementation", e);
253 }
254 if (groupClass == null)
255 {
256 throw new InitializationException(
257 "Failed to create a Class object for Group implementation", e);
258 }
259 if (permissionClass == null)
260 {
261 throw new InitializationException(
262 "Failed to create a Class object for Permission implementation", e);
263 }
264 if (roleClass == null)
265 {
266 throw new InitializationException(
267 "Failed to create a Class object for Role implementation", e);
268 }
269 if (aclClass == null)
270 {
271 throw new InitializationException(
272 "Failed to create a Class object for ACL implementation", e);
273 }
274 }
275
276 try
277 {
278 UserManager userManager =
279 (UserManager) Class.forName(userManagerClassName).newInstance();
280
281 userManager.init(conf);
282
283 setUserManager(userManager);
284 }
285 catch (Exception e)
286 {
287 throw new InitializationException("Failed to instantiate UserManager", e);
288 }
289
290 try
291 {
292 aclFactoryService = (FactoryService) TurbineServices.getInstance().
293 getService(FactoryService.SERVICE_NAME);
294 }
295 catch (Exception e)
296 {
297 throw new InitializationException(
298 "BaseSecurityService.init: Failed to get the Factory Service object", e);
299 }
300
301 setInit(true);
302 }
303
304 /***
305 * Initializes the SecurityService, locating the apropriate UserManager
306 *
307 * @param config a ServletConfig, to enforce early initialization
308 * @throws InitializationException Something went wrong in the init stage
309 * @deprecated use init() instead.
310 */
311 public void init(ServletConfig config) throws InitializationException
312 {
313 init();
314 }
315
316 /***
317 * Return a Class object representing the system's chosen implementation of
318 * of User interface.
319 *
320 * @return systems's chosen implementation of User interface.
321 * @throws UnknownEntityException if the implementation of User interface
322 * could not be determined, or does not exist.
323 */
324 public Class getUserClass()
325 throws UnknownEntityException
326 {
327 if (userClass == null)
328 {
329 throw new UnknownEntityException(
330 "Failed to create a Class object for User implementation");
331 }
332 return userClass;
333 }
334
335 /***
336 * Construct a blank User object.
337 *
338 * This method calls getUserClass, and then creates a new object using
339 * the default constructor.
340 *
341 * @return an object implementing User interface.
342 * @throws UnknownEntityException if the object could not be instantiated.
343 */
344 public User getUserInstance()
345 throws UnknownEntityException
346 {
347 User user;
348 try
349 {
350 user = (User) getUserClass().newInstance();
351 }
352 catch (Exception e)
353 {
354 throw new UnknownEntityException(
355 "Failed instantiate an User implementation object", e);
356 }
357 return user;
358 }
359
360 /***
361 * Construct a blank User object.
362 *
363 * This method calls getUserClass, and then creates a new object using
364 * the default constructor.
365 *
366 * @param userName The name of the user.
367 *
368 * @return an object implementing User interface.
369 *
370 * @throws UnknownEntityException if the object could not be instantiated.
371 */
372 public User getUserInstance(String userName)
373 throws UnknownEntityException
374 {
375 User user = getUserInstance();
376 user.setName(userName);
377 return user;
378 }
379
380 /***
381 * Return a Class object representing the system's chosen implementation of
382 * of Group interface.
383 *
384 * @return systems's chosen implementation of Group interface.
385 * @throws UnknownEntityException if the implementation of Group interface
386 * could not be determined, or does not exist.
387 */
388 public Class getGroupClass()
389 throws UnknownEntityException
390 {
391 if (groupClass == null)
392 {
393 throw new UnknownEntityException(
394 "Failed to create a Class object for Group implementation");
395 }
396 return groupClass;
397 }
398
399 /***
400 * Construct a blank Group object.
401 *
402 * This method calls getGroupClass, and then creates a new object using
403 * the default constructor.
404 *
405 * @return an object implementing Group interface.
406 * @throws UnknownEntityException if the object could not be instantiated.
407 */
408 public Group getGroupInstance()
409 throws UnknownEntityException
410 {
411 Group group;
412 try
413 {
414 group = (Group) getGroupClass().newInstance();
415 }
416 catch (Exception e)
417 {
418 throw new UnknownEntityException("Failed to instantiate a Group implementation object", e);
419 }
420 return group;
421 }
422
423 /***
424 * Construct a blank Group object.
425 *
426 * This method calls getGroupClass, and then creates a new object using
427 * the default constructor.
428 *
429 * @param groupName The name of the Group
430 *
431 * @return an object implementing Group interface.
432 *
433 * @throws UnknownEntityException if the object could not be instantiated.
434 */
435 public Group getGroupInstance(String groupName)
436 throws UnknownEntityException
437 {
438 Group group = getGroupInstance();
439 group.setName(groupName);
440 return group;
441 }
442
443 /***
444 * Return a Class object representing the system's chosen implementation of
445 * of Permission interface.
446 *
447 * @return systems's chosen implementation of Permission interface.
448 * @throws UnknownEntityException if the implementation of Permission interface
449 * could not be determined, or does not exist.
450 */
451 public Class getPermissionClass()
452 throws UnknownEntityException
453 {
454 if (permissionClass == null)
455 {
456 throw new UnknownEntityException(
457 "Failed to create a Class object for Permission implementation");
458 }
459 return permissionClass;
460 }
461
462 /***
463 * Construct a blank Permission object.
464 *
465 * This method calls getPermissionClass, and then creates a new object using
466 * the default constructor.
467 *
468 * @return an object implementing Permission interface.
469 * @throws UnknownEntityException if the object could not be instantiated.
470 */
471 public Permission getPermissionInstance()
472 throws UnknownEntityException
473 {
474 Permission permission;
475 try
476 {
477 permission = (Permission) getPermissionClass().newInstance();
478 }
479 catch (Exception e)
480 {
481 throw new UnknownEntityException("Failed to instantiate a Permission implementation object", e);
482 }
483 return permission;
484 }
485
486 /***
487 * Construct a blank Permission object.
488 *
489 * This method calls getPermissionClass, and then creates a new object using
490 * the default constructor.
491 *
492 * @param permName The name of the permission.
493 *
494 * @return an object implementing Permission interface.
495 * @throws UnknownEntityException if the object could not be instantiated.
496 */
497 public Permission getPermissionInstance(String permName)
498 throws UnknownEntityException
499 {
500 Permission perm = getPermissionInstance();
501 perm.setName(permName);
502 return perm;
503 }
504
505 /***
506 * Return a Class object representing the system's chosen implementation of
507 * of Role interface.
508 *
509 * @return systems's chosen implementation of Role interface.
510 * @throws UnknownEntityException if the implementation of Role interface
511 * could not be determined, or does not exist.
512 */
513 public Class getRoleClass()
514 throws UnknownEntityException
515 {
516 if (roleClass == null)
517 {
518 throw new UnknownEntityException(
519 "Failed to create a Class object for Role implementation");
520 }
521 return roleClass;
522 }
523
524 /***
525 * Construct a blank Role object.
526 *
527 * This method calls getRoleClass, and then creates a new object using
528 * the default constructor.
529 *
530 * @return an object implementing Role interface.
531 * @throws UnknownEntityException if the object could not be instantiated.
532 */
533 public Role getRoleInstance()
534 throws UnknownEntityException
535 {
536 Role role;
537
538 try
539 {
540 role = (Role) getRoleClass().newInstance();
541 }
542 catch (Exception e)
543 {
544 throw new UnknownEntityException("Failed to instantiate a Role implementation object", e);
545 }
546 return role;
547 }
548
549 /***
550 * Construct a blank Role object.
551 *
552 * This method calls getRoleClass, and then creates a new object using
553 * the default constructor.
554 *
555 * @param roleName The name of the role.
556 *
557 * @return an object implementing Role interface.
558 *
559 * @throws UnknownEntityException if the object could not be instantiated.
560 */
561 public Role getRoleInstance(String roleName)
562 throws UnknownEntityException
563 {
564 Role role = getRoleInstance();
565 role.setName(roleName);
566 return role;
567 }
568
569 /***
570 * Return a Class object representing the system's chosen implementation of
571 * of ACL interface.
572 *
573 * @return systems's chosen implementation of ACL interface.
574 * @throws UnknownEntityException if the implementation of ACL interface
575 * could not be determined, or does not exist.
576 */
577 public Class getAclClass()
578 throws UnknownEntityException
579 {
580 if (aclClass == null)
581 {
582 throw new UnknownEntityException(
583 "Failed to create a Class object for ACL implementation");
584 }
585 return aclClass;
586 }
587
588 /***
589 * Construct a new ACL object.
590 *
591 * This constructs a new ACL object from the configured class and
592 * initializes it with the supplied roles and permissions.
593 *
594 * @param roles The roles that this ACL should contain
595 * @param permissions The permissions for this ACL
596 *
597 * @return an object implementing ACL interface.
598 * @throws UnknownEntityException if the object could not be instantiated.
599 */
600 public AccessControlList getAclInstance(Map roles, Map permissions)
601 throws UnknownEntityException
602 {
603 Object[] objects = {roles, permissions};
604 String[] signatures = {Map.class.getName(), Map.class.getName()};
605 AccessControlList accessControlList;
606
607 try
608 {
609 accessControlList =
610 (AccessControlList) aclFactoryService.getInstance(aclClass.getName(),
611 objects,
612 signatures);
613 }
614 catch (Exception e)
615 {
616 throw new UnknownEntityException(
617 "Failed to instantiate an ACL implementation object", e);
618 }
619
620 return accessControlList;
621 }
622
623 /***
624 * Returns the configured UserManager.
625 *
626 * @return An UserManager object
627 */
628 public UserManager getUserManager()
629 {
630 return userManager;
631 }
632
633 /***
634 * Configure a new user Manager.
635 *
636 * @param userManager An UserManager object
637 */
638 public void setUserManager(UserManager userManager)
639 {
640 this.userManager = userManager;
641 }
642
643 /***
644 * Check whether a specified user's account exists.
645 *
646 * The login name is used for looking up the account.
647 *
648 * @param user The user to be checked.
649 * @return true if the specified account exists
650 * @throws DataBackendException if there was an error accessing the data
651 * backend.
652 */
653 public boolean accountExists(User user)
654 throws DataBackendException
655 {
656 return getUserManager().accountExists(user);
657 }
658
659 /***
660 * Check whether a specified user's account exists.
661 *
662 * The login name is used for looking up the account.
663 *
664 * @param userName The name of the user to be checked.
665 * @return true if the specified account exists
666 * @throws DataBackendException if there was an error accessing the data
667 * backend.
668 */
669 public boolean accountExists(String userName)
670 throws DataBackendException
671 {
672 return getUserManager().accountExists(userName);
673 }
674
675 /***
676 * Authenticates an user, and constructs an User object to represent
677 * him/her.
678 *
679 * @param username The user name.
680 * @param password The user password.
681 * @return An authenticated Turbine User.
682 * @throws PasswordMismatchException if the supplied password was incorrect.
683 * @throws UnknownEntityException if the user's account does not
684 * exist in the database.
685 * @throws DataBackendException if there is a problem accessing the storage.
686 */
687 public User getAuthenticatedUser(String username, String password)
688 throws DataBackendException, UnknownEntityException,
689 PasswordMismatchException
690 {
691 return getUserManager().retrieve(username, password);
692 }
693
694 /***
695 * Constructs an User object to represent a registered user of the
696 * application.
697 *
698 * @param username The user name.
699 * @return A Turbine User.
700 * @throws UnknownEntityException if the user's account does not exist
701 * @throws DataBackendException if there is a problem accessing the storage.
702 */
703 public User getUser(String username)
704 throws DataBackendException, UnknownEntityException
705 {
706 return getUserManager().retrieve(username);
707 }
708
709 /***
710 * Retrieve a set of users that meet the specified criteria.
711 *
712 * As the keys for the criteria, you should use the constants that
713 * are defined in {@link User} interface, plus the names
714 * of the custom attributes you added to your user representation
715 * in the data storage. Use verbatim names of the attributes -
716 * without table name prefix in case of DB implementation.
717 *
718 * @param criteria The criteria of selection.
719 * @return a List of users meeting the criteria.
720 * @throws DataBackendException if there is a problem accessing the
721 * storage.
722 * @deprecated Use <a href="#getUserList">getUserList</a> instead.
723 */
724 public User[] getUsers(Criteria criteria)
725 throws DataBackendException
726 {
727 return (User []) getUserList(criteria).toArray(new User[0]);
728 }
729
730 /***
731 * Retrieve a set of users that meet the specified criteria.
732 *
733 * As the keys for the criteria, you should use the constants that
734 * are defined in {@link User} interface, plus the names
735 * of the custom attributes you added to your user representation
736 * in the data storage. Use verbatim names of the attributes -
737 * without table name prefix in case of DB implementation.
738 *
739 * @param criteria The criteria of selection.
740 * @return a List of users meeting the criteria.
741 * @throws DataBackendException if there is a problem accessing the
742 * storage.
743 */
744 public List getUserList(Criteria criteria)
745 throws DataBackendException
746 {
747 return getUserManager().retrieveList(criteria);
748 }
749
750 /***
751 * Constructs an User object to represent an anonymous user of the
752 * application.
753 *
754 * @return An anonymous Turbine User.
755 * @throws UnknownEntityException if the implementation of User interface
756 * could not be determined, or does not exist.
757 */
758 public User getAnonymousUser()
759 throws UnknownEntityException
760 {
761 User user = getUserInstance();
762 user.setName("");
763 return user;
764 }
765
766 /***
767 * Checks whether a passed user object matches the anonymous user pattern
768 * according to the configured user manager
769 *
770 * @param user An user object
771 *
772 * @return True if this is an anonymous user
773 *
774 */
775 public boolean isAnonymousUser(User user)
776 {
777
778 return (user == null) || StringUtils.isEmpty(user.getName());
779 }
780
781 /***
782 * Saves User's data in the permanent storage. The user account is required
783 * to exist in the storage.
784 *
785 * @param user the User object to save
786 * @throws UnknownEntityException if the user's account does not
787 * exist in the database.
788 * @throws DataBackendException if there is a problem accessing the storage.
789 */
790 public void saveUser(User user)
791 throws UnknownEntityException, DataBackendException
792 {
793 getUserManager().store(user);
794 }
795
796 /***
797 * Saves User data when the session is unbound. The user account is required
798 * to exist in the storage.
799 *
800 * LastLogin, AccessCounter, persistent pull tools, and any data stored
801 * in the permData hashtable that is not mapped to a column will be saved.
802 *
803 * @exception UnknownEntityException if the user's account does not
804 * exist in the database.
805 * @exception DataBackendException if there is a problem accessing the
806 * storage.
807 */
808 public void saveOnSessionUnbind(User user)
809 throws UnknownEntityException, DataBackendException
810 {
811 userManager.saveOnSessionUnbind(user);
812 }
813
814 /***
815 * Creates new user account with specified attributes.
816 *
817 * @param user the object describing account to be created.
818 * @param password The password to use for the account.
819 *
820 * @throws DataBackendException if there was an error accessing the
821 * data backend.
822 * @throws EntityExistsException if the user account already exists.
823 */
824 public void addUser(User user, String password)
825 throws DataBackendException, EntityExistsException
826 {
827 getUserManager().createAccount(user, password);
828 }
829
830 /***
831 * Removes an user account from the system.
832 *
833 * @param user the object describing the account to be removed.
834 * @throws DataBackendException if there was an error accessing the data
835 * backend.
836 * @throws UnknownEntityException if the user account is not present.
837 */
838 public void removeUser(User user)
839 throws DataBackendException, UnknownEntityException
840 {
841
842 revokeAll(user);
843
844 getUserManager().removeAccount(user);
845 }
846
847 /***
848 * Change the password for an User.
849 *
850 * @param user an User to change password for.
851 * @param oldPassword the current password supplied by the user.
852 * @param newPassword the current password requested by the user.
853 * @throws PasswordMismatchException if the supplied password was incorrect.
854 * @throws UnknownEntityException if the user's record does not
855 * exist in the database.
856 * @throws DataBackendException if there is a problem accessing the storage.
857 */
858 public void changePassword(User user, String oldPassword,
859 String newPassword)
860 throws PasswordMismatchException, UnknownEntityException,
861 DataBackendException
862 {
863 getUserManager().changePassword(user, oldPassword, newPassword);
864 }
865
866 /***
867 * Forcibly sets new password for an User.
868 *
869 * This is supposed by the administrator to change the forgotten or
870 * compromised passwords. Certain implementatations of this feature
871 * would require administrative level access to the authenticating
872 * server / program.
873 *
874 * @param user an User to change password for.
875 * @param password the new password.
876 * @throws UnknownEntityException if the user's record does not
877 * exist in the database.
878 * @throws DataBackendException if there is a problem accessing the storage.
879 */
880 public void forcePassword(User user, String password)
881 throws UnknownEntityException, DataBackendException
882 {
883 getUserManager().forcePassword(user, password);
884 }
885
886 /***
887 * Acquire a shared lock on the security information repository.
888 *
889 * Methods that read security information need to invoke this
890 * method at the beginning of their body.
891 */
892 protected synchronized void lockShared()
893 {
894 readerCount++;
895 }
896
897 /***
898 * Release a shared lock on the security information repository.
899 *
900 * Methods that read security information need to invoke this
901 * method at the end of their body.
902 */
903 protected synchronized void unlockShared()
904 {
905 readerCount--;
906 this.notify();
907 }
908
909 /***
910 * Acquire an exclusive lock on the security information repository.
911 *
912 * Methods that modify security information need to invoke this
913 * method at the beginning of their body. Note! Those methods must
914 * be <code>synchronized</code> themselves!
915 */
916 protected void lockExclusive()
917 {
918 while (readerCount > 0)
919 {
920 try
921 {
922 this.wait();
923 }
924 catch (InterruptedException e)
925 {
926 }
927 }
928 }
929
930 /***
931 * Release an exclusive lock on the security information repository.
932 *
933 * This method is provided only for completeness. It does not really
934 * do anything. Note! Methods that modify security information
935 * must be <code>synchronized</code>!
936 */
937 protected void unlockExclusive()
938 {
939
940 }
941
942 /***
943 * Provides a reference to the Group object that represents the
944 * <a href="#global">global group</a>.
945 *
946 * @return a Group object that represents the global group.
947 */
948 public Group getGlobalGroup()
949 {
950 if (globalGroup == null)
951 {
952 synchronized (BaseSecurityService.class)
953 {
954 if (globalGroup == null)
955 {
956 try
957 {
958 globalGroup = getAllGroups()
959 .getGroupByName(Group.GLOBAL_GROUP_NAME);
960 }
961 catch (DataBackendException e)
962 {
963 log.error("Failed to retrieve global group object: ", e);
964 }
965 }
966 }
967 }
968 return globalGroup;
969 }
970
971 /***
972 * Retrieve a Group object with specified name.
973 *
974 * @param name the name of the Group.
975 * @return an object representing the Group with specified name.
976 * @throws DataBackendException if there was an error accessing the
977 * data backend.
978 * @throws UnknownEntityException if the group does not exist.
979 * @deprecated Use <a href="#getGroupByName">getGroupByName</a> instead.
980 */
981 public Group getGroup(String name)
982 throws DataBackendException, UnknownEntityException
983 {
984 return getGroupByName(name);
985 }
986
987 /***
988 * Retrieve a Group object with specified name.
989 *
990 * @param name the name of the Group.
991 * @return an object representing the Group with specified name.
992 * @throws DataBackendException if there was an error accessing the
993 * data backend.
994 * @throws UnknownEntityException if the group does not exist.
995 */
996 public Group getGroupByName(String name)
997 throws DataBackendException, UnknownEntityException
998 {
999 Group group = getAllGroups().getGroupByName(name);
1000 if (group == null)
1001 {
1002 throw new UnknownEntityException(
1003 "The specified group does not exist");
1004 }
1005 return group;
1006 }
1007
1008 /***
1009 * Retrieve a Group object with specified Id.
1010 *
1011 * @param id the id of the Group.
1012 * @return an object representing the Group with specified name.
1013 * @throws UnknownEntityException if the permission does not
1014 * exist in the database.
1015 * @throws DataBackendException if there is a problem accessing the
1016 * storage.
1017 */
1018 public Group getGroupById(int id)
1019 throws DataBackendException, UnknownEntityException
1020 {
1021 Group group = getAllGroups().getGroupById(id);
1022 if (group == null)
1023 {
1024 throw new UnknownEntityException(
1025 "The specified group does not exist");
1026 }
1027 return group;
1028 }
1029
1030 /***
1031 * Retrieve a Role object with specified name.
1032 *
1033 * @param name the name of the Role.
1034 * @return an object representing the Role with specified name.
1035 * @throws DataBackendException if there was an error accessing the
1036 * data backend.
1037 * @throws UnknownEntityException if the role does not exist.
1038 * @deprecated Use <a href="#getRoleByName">getRoleByName</a> instead.
1039 */
1040 public Role getRole(String name)
1041 throws DataBackendException, UnknownEntityException
1042 {
1043 return getRoleByName(name);
1044 }
1045
1046 /***
1047 * Retrieve a Role object with specified name.
1048 *
1049 * @param name the name of the Role.
1050 * @return an object representing the Role with specified name.
1051 * @throws DataBackendException if there was an error accessing the
1052 * data backend.
1053 * @throws UnknownEntityException if the role does not exist.
1054 */
1055 public Role getRoleByName(String name)
1056 throws DataBackendException, UnknownEntityException
1057 {
1058 Role role = getAllRoles().getRoleByName(name);
1059 if (role == null)
1060 {
1061 throw new UnknownEntityException(
1062 "The specified role does not exist");
1063 }
1064 role.setPermissions(getPermissions(role));
1065 return role;
1066 }
1067
1068 /***
1069 * Retrieve a Role object with specified Id.
1070 * @param id the id of the Role.
1071 * @return an object representing the Role with specified name.
1072 * @throws UnknownEntityException if the permission does not
1073 * exist in the database.
1074 * @throws DataBackendException if there is a problem accessing the
1075 * storage.
1076 */
1077 public Role getRoleById(int id)
1078 throws DataBackendException,
1079 UnknownEntityException
1080 {
1081 Role role = getAllRoles().getRoleById(id);
1082 if (role == null)
1083 {
1084 throw new UnknownEntityException(
1085 "The specified role does not exist");
1086 }
1087 role.setPermissions(getPermissions(role));
1088 return role;
1089 }
1090
1091 /***
1092 * Retrieve a Permission object with specified name.
1093 *
1094 * @param name the name of the Permission.
1095 * @return an object representing the Permission with specified name.
1096 * @throws DataBackendException if there was an error accessing the
1097 * data backend.
1098 * @throws UnknownEntityException if the permission does not exist.
1099 * @deprecated Use <a href="#getPermissionByName">getPermissionByName</a> instead.
1100 */
1101 public Permission getPermission(String name)
1102 throws DataBackendException, UnknownEntityException
1103 {
1104 return getPermissionByName(name);
1105 }
1106
1107 /***
1108 * Retrieve a Permission object with specified name.
1109 *
1110 * @param name the name of the Permission.
1111 * @return an object representing the Permission with specified name.
1112 * @throws DataBackendException if there was an error accessing the
1113 * data backend.
1114 * @throws UnknownEntityException if the permission does not exist.
1115 */
1116 public Permission getPermissionByName(String name)
1117 throws DataBackendException, UnknownEntityException
1118 {
1119 Permission permission = getAllPermissions().getPermissionByName(name);
1120 if (permission == null)
1121 {
1122 throw new UnknownEntityException(
1123 "The specified permission does not exist");
1124 }
1125 return permission;
1126 }
1127
1128 /***
1129 * Retrieve a Permission object with specified Id.
1130 *
1131 * @param id the id of the Permission.
1132 * @return an object representing the Permission with specified name.
1133 * @throws UnknownEntityException if the permission does not
1134 * exist in the database.
1135 * @throws DataBackendException if there is a problem accessing the
1136 * storage.
1137 */
1138 public Permission getPermissionById(int id)
1139 throws DataBackendException,
1140 UnknownEntityException
1141 {
1142 Permission permission = getAllPermissions().getPermissionById(id);
1143 if (permission == null)
1144 {
1145 throw new UnknownEntityException(
1146 "The specified permission does not exist");
1147 }
1148 return permission;
1149 }
1150
1151 /***
1152 * Retrieves all groups defined in the system.
1153 *
1154 * @return the names of all groups defined in the system.
1155 * @throws DataBackendException if there was an error accessing the
1156 * data backend.
1157 */
1158 public GroupSet getAllGroups()
1159 throws DataBackendException
1160 {
1161 return getGroups(new Criteria());
1162 }
1163
1164 /***
1165 * Retrieves all roles defined in the system.
1166 *
1167 * @return the names of all roles defined in the system.
1168 * @throws DataBackendException if there was an error accessing the
1169 * data backend.
1170 */
1171 public RoleSet getAllRoles()
1172 throws DataBackendException
1173 {
1174 return getRoles(new Criteria());
1175 }
1176
1177 /***
1178 * Retrieves all permissions defined in the system.
1179 *
1180 * @return the names of all roles defined in the system.
1181 * @throws DataBackendException if there was an error accessing the
1182 * data backend.
1183 */
1184 public PermissionSet getAllPermissions()
1185 throws DataBackendException
1186 {
1187 return getPermissions(new Criteria());
1188 }
1189
1190 /***
1191 * @deprecated Use getGroupInstance(String name) instead.
1192 */
1193 public Group getNewGroup(String groupName)
1194 {
1195 try
1196 {
1197 return getGroupInstance(groupName);
1198 }
1199 catch (UnknownEntityException uee)
1200 {
1201 uee.printStackTrace();
1202 return null;
1203 }
1204 }
1205
1206 /***
1207 * @deprecated Use getRoleInstance(String name) instead.
1208 */
1209 public Role getNewRole(String roleName)
1210 {
1211 try
1212 {
1213 return getRoleInstance(roleName);
1214 }
1215 catch (UnknownEntityException uee)
1216 {
1217 return null;
1218 }
1219 }
1220
1221 /***
1222 * @deprecated Use getPermissionInstance(String name) instead.
1223 */
1224 public Permission getNewPermission(String permissionName)
1225 {
1226 try
1227 {
1228 return getPermissionInstance(permissionName);
1229 }
1230 catch (UnknownEntityException uee)
1231 {
1232 return null;
1233 }
1234 }
1235 }