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