001 package org.apache.turbine.services.security.torque;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.util.ArrayList;
023 import java.util.Hashtable;
024 import java.util.Iterator;
025 import java.util.List;
026
027 import org.apache.commons.configuration.Configuration;
028 import org.apache.commons.lang.StringUtils;
029 import org.apache.commons.logging.Log;
030 import org.apache.commons.logging.LogFactory;
031 import org.apache.torque.TorqueException;
032 import org.apache.torque.om.NumberKey;
033 import org.apache.torque.om.Persistent;
034 import org.apache.torque.util.Criteria;
035 import org.apache.turbine.om.security.Group;
036 import org.apache.turbine.om.security.Permission;
037 import org.apache.turbine.om.security.Role;
038 import org.apache.turbine.om.security.User;
039 import org.apache.turbine.services.InitializationException;
040 import org.apache.turbine.services.security.BaseSecurityService;
041 import org.apache.turbine.services.security.TurbineSecurity;
042 import org.apache.turbine.services.security.torque.om.TurbineRolePermissionPeer;
043 import org.apache.turbine.services.security.torque.om.TurbineUserGroupRolePeer;
044 import org.apache.turbine.util.security.AccessControlList;
045 import org.apache.turbine.util.security.DataBackendException;
046 import org.apache.turbine.util.security.EntityExistsException;
047 import org.apache.turbine.util.security.GroupSet;
048 import org.apache.turbine.util.security.PermissionSet;
049 import org.apache.turbine.util.security.RoleSet;
050 import org.apache.turbine.util.security.UnknownEntityException;
051
052 /**
053 * An implementation of SecurityService that uses torque objects.
054 *
055 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
056 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
057 * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a>
058 * @version $Id: TorqueSecurityService.java 1096130 2011-04-23 10:37:19Z ludwig $
059 */
060 public class TorqueSecurityService
061 extends BaseSecurityService
062 {
063 /** Logging */
064 private static Log log = LogFactory.getLog(TorqueSecurityService.class);
065
066 /**
067 * Initializes the TorqueSecurityService, loading the various class objects
068 * representing the security entity peer classes
069 *
070 * @exception InitializationException A problem occured during initialization
071 */
072
073 public void init()
074 throws InitializationException
075 {
076 Configuration conf = getConfiguration();
077
078 GroupPeerManager.init(conf);
079 RolePeerManager.init(conf);
080 PermissionPeerManager.init(conf);
081
082 /* At the end, because it calls setInit(true)! */
083 super.init();
084 }
085
086
087 /*-----------------------------------------------------------------------
088 Creation of AccessControlLists
089 -----------------------------------------------------------------------*/
090
091 /**
092 * Constructs an AccessControlList for a specific user.
093 *
094 * This method creates a snapshot of the state of security information
095 * concerning this user, at the moment of invocation and stores it
096 * into an AccessControlList object.
097 *
098 * @param user the user for whom the AccessControlList are to be retrieved
099 * @return A new AccessControlList object.
100 * @throws DataBackendException if there was an error accessing the data
101 * backend.
102 * @throws UnknownEntityException if user account is not present.
103 */
104 public AccessControlList getACL(User user)
105 throws DataBackendException, UnknownEntityException
106 {
107 if (!TurbineSecurity.accountExists(user))
108 {
109 throw new UnknownEntityException("The account '"
110 + user.getName() + "' does not exist");
111 }
112 try
113 {
114 Hashtable roles = new Hashtable();
115 Hashtable permissions = new Hashtable();
116 // notify the state modifiers (writers) that we want to create
117 // the snapshot.
118 lockShared();
119
120 // construct the snapshot:
121
122 // foreach group in the system
123 for (Iterator groupsIterator = getAllGroups().iterator();
124 groupsIterator.hasNext();)
125 {
126 Group group = (Group) groupsIterator.next();
127 // get roles of user in the group
128 RoleSet groupRoles = RolePeerManager.retrieveSet(user, group);
129 // put the Set into roles(group)
130 roles.put(group, groupRoles);
131 // collect all permissions in this group
132 PermissionSet groupPermissions = new PermissionSet();
133 // foreach role in Set
134 for (Iterator rolesIterator = groupRoles.iterator();
135 rolesIterator.hasNext();)
136 {
137 Role role = (Role) rolesIterator.next();
138 // get permissions of the role
139 PermissionSet rolePermissions =
140 PermissionPeerManager.retrieveSet(role);
141 groupPermissions.add(rolePermissions);
142 }
143 // put the Set into permissions(group)
144 permissions.put(group, groupPermissions);
145 }
146 return getAclInstance(roles, permissions);
147 }
148 catch (Exception e)
149 {
150 throw new DataBackendException("Failed to build ACL for user '" +
151 user.getName() + "'" , e);
152 }
153 finally
154 {
155 // notify the state modifiers that we are done creating the snapshot.
156 unlockShared();
157 }
158 }
159
160 /*-----------------------------------------------------------------------
161 Security management
162 -----------------------------------------------------------------------*/
163
164 /**
165 * Grant an User a Role in a Group.
166 *
167 * @param user the user.
168 * @param group the group.
169 * @param role the role.
170 * @throws DataBackendException if there was an error accessing the data
171 * backend.
172 * @throws UnknownEntityException if user account, group or role is not
173 * present.
174 */
175 public synchronized void grant(User user, Group group, Role role)
176 throws DataBackendException, UnknownEntityException
177 {
178 boolean userExists = false;
179 boolean groupExists = false;
180 boolean roleExists = false;
181 try
182 {
183 lockExclusive();
184 userExists = TurbineSecurity.accountExists(user);
185 groupExists = checkExists(group);
186 roleExists = checkExists(role);
187 if (userExists && groupExists && roleExists)
188 {
189 Criteria criteria = new Criteria();
190 criteria.add(TurbineUserGroupRolePeer.USER_ID,
191 ((Persistent) user).getPrimaryKey());
192 criteria.add(TurbineUserGroupRolePeer.GROUP_ID,
193 ((Persistent) group).getPrimaryKey());
194 criteria.add(TurbineUserGroupRolePeer.ROLE_ID,
195 ((Persistent) role).getPrimaryKey());
196 TurbineUserGroupRolePeer.doInsert(criteria);
197 return;
198 }
199 }
200 catch (Exception e)
201 {
202 throw new DataBackendException("grant(User,Group,Role) failed", e);
203 }
204 finally
205 {
206 unlockExclusive();
207 }
208 if (!userExists)
209 {
210 throw new UnknownEntityException("Unknown user '"
211 + user.getName() + "'");
212 }
213 if (!groupExists)
214 {
215 throw new UnknownEntityException("Unknown group '"
216 + group.getName() + "'");
217 }
218 if (!roleExists)
219 {
220 throw new UnknownEntityException("Unknown role '"
221 + role.getName() + "'");
222 }
223 }
224
225 /**
226 * Revoke a Role in a Group from an User.
227 *
228 * @param user the user.
229 * @param group the group.
230 * @param role the role.
231 * @throws DataBackendException if there was an error accessing the data
232 * backend.
233 * @throws UnknownEntityException if user account, group or role is not
234 * present.
235 */
236 public synchronized void revoke(User user, Group group, Role role)
237 throws DataBackendException, UnknownEntityException
238 {
239 boolean userExists = false;
240 boolean groupExists = false;
241 boolean roleExists = false;
242 try
243 {
244 lockExclusive();
245 userExists = TurbineSecurity.accountExists(user);
246 groupExists = checkExists(group);
247 roleExists = checkExists(role);
248 if (userExists && groupExists && roleExists)
249 {
250 Criteria criteria = new Criteria();
251 criteria.add(TurbineUserGroupRolePeer.USER_ID,
252 ((Persistent) user).getPrimaryKey());
253 criteria.add(TurbineUserGroupRolePeer.GROUP_ID,
254 ((Persistent) group).getPrimaryKey());
255 criteria.add(TurbineUserGroupRolePeer.ROLE_ID,
256 ((Persistent) role).getPrimaryKey());
257 TurbineUserGroupRolePeer.doDelete(criteria);
258 return;
259 }
260 }
261 catch (Exception e)
262 {
263 throw new DataBackendException("revoke(User,Role,Group) failed", e);
264 }
265 finally
266 {
267 unlockExclusive();
268 }
269 if (!userExists)
270 {
271 throw new UnknownEntityException("Unknown user '"
272 + user.getName() + "'");
273 }
274 if (!groupExists)
275 {
276 throw new UnknownEntityException("Unknown group '"
277 + group.getName() + "'");
278 }
279 if (!roleExists)
280 {
281 throw new UnknownEntityException("Unknown role '"
282 + role.getName() + "'");
283 }
284 }
285
286 /**
287 * Revokes all roles from an User.
288 *
289 * This method is used when deleting an account.
290 *
291 * @param user the User.
292 * @throws DataBackendException if there was an error accessing the data
293 * backend.
294 * @throws UnknownEntityException if the account is not present.
295 */
296 public synchronized void revokeAll(User user)
297 throws DataBackendException, UnknownEntityException
298 {
299 boolean userExists = false;
300 try
301 {
302 lockExclusive();
303 userExists = TurbineSecurity.accountExists(user);
304 if (userExists)
305 {
306 // The following would not work, due to an annoying misfeature
307 // of Village. Village allows only a single row to be deleted at
308 // a time. I wish that it was possible to disable this
309 // behaviour!
310
311 // Criteria criteria = new Criteria();
312 // criteria.add(UserGroupRolePeer.USER_ID,
313 // ((Persistent) user).getPrimaryKey());
314 // UserGroupRolePeer.doDelete(criteria);
315 int id = ((NumberKey) ((Persistent) user)
316 .getPrimaryKey()).intValue();
317 TurbineUserGroupRolePeer.deleteAll(
318 TurbineUserGroupRolePeer.TABLE_NAME,
319 TurbineUserGroupRolePeer.USER_ID, id);
320 return;
321 }
322 }
323 catch (Exception e)
324 {
325 throw new DataBackendException("revokeAll(User) failed", e);
326 }
327 finally
328 {
329 unlockExclusive();
330 }
331 throw new UnknownEntityException("Unknown user '"
332 + user.getName() + "'");
333 }
334
335 /**
336 * Grants a Role a Permission
337 *
338 * @param role the Role.
339 * @param permission the Permission.
340 * @throws DataBackendException if there was an error accessing the data
341 * backend.
342 * @throws UnknownEntityException if role or permission is not present.
343 */
344 public synchronized void grant(Role role, Permission permission)
345 throws DataBackendException, UnknownEntityException
346 {
347 boolean roleExists = false;
348 boolean permissionExists = false;
349 try
350 {
351 lockExclusive();
352 roleExists = checkExists(role);
353 permissionExists = checkExists(permission);
354 if (roleExists && permissionExists)
355 {
356 Criteria criteria = new Criteria();
357 criteria.add(TurbineRolePermissionPeer.ROLE_ID,
358 ((Persistent) role).getPrimaryKey());
359 criteria.add(TurbineRolePermissionPeer.PERMISSION_ID,
360 ((Persistent) permission).getPrimaryKey());
361 TurbineRolePermissionPeer.doInsert(criteria);
362 return;
363 }
364 }
365 catch (Exception e)
366 {
367 throw new DataBackendException("grant(Role,Permission) failed", e);
368 }
369 finally
370 {
371 unlockExclusive();
372 }
373 if (!roleExists)
374 {
375 throw new UnknownEntityException("Unknown role '"
376 + role.getName() + "'");
377 }
378 if (!permissionExists)
379 {
380 throw new UnknownEntityException("Unknown permission '"
381 + permission.getName() + "'");
382 }
383 }
384
385 /**
386 * Revokes a Permission from a Role.
387 *
388 * @param role the Role.
389 * @param permission the Permission.
390 * @throws DataBackendException if there was an error accessing the data
391 * backend.
392 * @throws UnknownEntityException if role or permission is not present.
393 */
394 public synchronized void revoke(Role role, Permission permission)
395 throws DataBackendException, UnknownEntityException
396 {
397 boolean roleExists = false;
398 boolean permissionExists = false;
399 try
400 {
401 lockExclusive();
402 roleExists = checkExists(role);
403 permissionExists = checkExists(permission);
404 if (roleExists && permissionExists)
405 {
406 Criteria criteria = new Criteria();
407 criteria.add(TurbineRolePermissionPeer.ROLE_ID,
408 ((Persistent) role).getPrimaryKey());
409 criteria.add(TurbineRolePermissionPeer.PERMISSION_ID,
410 ((Persistent) permission).getPrimaryKey());
411 TurbineRolePermissionPeer.doDelete(criteria);
412 return;
413 }
414 }
415 catch (Exception e)
416 {
417 throw new DataBackendException("revoke(Role,Permission) failed", e);
418 }
419 finally
420 {
421 unlockExclusive();
422 }
423 if (!roleExists)
424 {
425 throw new UnknownEntityException("Unknown role '"
426 + role.getName() + "'");
427 }
428 if (!permissionExists)
429 {
430 throw new UnknownEntityException("Unknown permission '"
431 + permission.getName() + "'");
432 }
433 }
434
435 /**
436 * Revokes all permissions from a Role.
437 *
438 * This method is user when deleting a Role.
439 *
440 * @param role the Role
441 * @throws DataBackendException if there was an error accessing the data
442 * backend.
443 * @throws UnknownEntityException if the Role is not present.
444 */
445 public synchronized void revokeAll(Role role)
446 throws DataBackendException, UnknownEntityException
447 {
448 boolean roleExists = false;
449 try
450 {
451 lockExclusive();
452 roleExists = checkExists(role);
453 if (roleExists)
454 {
455 // The following would not work, due to an annoying misfeature
456 // of Village. see revokeAll( user )
457
458 // Criteria criteria = new Criteria();
459 // criteria.add(RolePermissionPeer.ROLE_ID,
460 // role.getPrimaryKey());
461 // RolePermissionPeer.doDelete(criteria);
462
463 int id = ((NumberKey) ((Persistent) role)
464 .getPrimaryKey()).intValue();
465 TurbineRolePermissionPeer.deleteAll(
466 TurbineRolePermissionPeer.TABLE_NAME,
467 TurbineRolePermissionPeer.ROLE_ID, id);
468 return;
469 }
470 }
471 catch (Exception e)
472 {
473 throw new DataBackendException("revokeAll(Role) failed", e);
474 }
475 finally
476 {
477 unlockExclusive();
478 }
479 throw new UnknownEntityException("Unknown role '"
480 + role.getName() + "'");
481 }
482
483 /*-----------------------------------------------------------------------
484 Group/Role/Permission management
485 -----------------------------------------------------------------------*/
486
487 /**
488 * Retrieve a set of Groups that meet the specified Criteria.
489 *
490 * @param criteria A Criteria of Group selection.
491 * @return a set of Groups that meet the specified Criteria.
492 * @throws DataBackendException if there was an error accessing the data
493 * backend.
494 */
495 public GroupSet getGroups(Object criteria)
496 throws DataBackendException
497 {
498 if (criteria instanceof Criteria)
499 {
500 Criteria torqueCriteria = new Criteria();
501 Criteria c = (Criteria)criteria;
502 Iterator keys = c.keySet().iterator();
503 while (keys.hasNext())
504 {
505 String key = (String) keys.next();
506 torqueCriteria.put(GroupPeerManager.getColumnName(key),
507 c.get(key));
508 }
509 List groups = new ArrayList(0);
510 try
511 {
512 groups = GroupPeerManager.doSelect(torqueCriteria);
513 }
514 catch (TorqueException e)
515 {
516 throw new DataBackendException("getGroups(Object) failed", e);
517 }
518
519 return new GroupSet(groups);
520 }
521 else
522 {
523 throw new DataBackendException(
524 "getGroups(Object) failed with invalid criteria");
525 }
526 }
527
528 /**
529 * Retrieve a set of Roles that meet the specified Criteria.
530 *
531 * @param criteria A Criteria of Roles selection.
532 * @return a set of Roles that meet the specified Criteria.
533 * @throws DataBackendException if there was an error accessing the data
534 * backend.
535 */
536 public RoleSet getRoles(Object criteria)
537 throws DataBackendException
538 {
539 if (criteria instanceof Criteria)
540 {
541 Criteria torqueCriteria = new Criteria();
542 Criteria c = (Criteria)criteria;
543 Iterator keys = c.keySet().iterator();
544 while (keys.hasNext())
545 {
546 String key = (String) keys.next();
547 torqueCriteria.put(RolePeerManager.getColumnName(key),
548 c.get(key));
549 }
550 List roles = new ArrayList(0);
551 try
552 {
553 roles = RolePeerManager.doSelect(torqueCriteria);
554 }
555 catch (TorqueException e)
556 {
557 throw new DataBackendException("getRoles(Criteria) failed", e);
558 }
559 return new RoleSet(roles);
560 }
561 else
562 {
563 throw new DataBackendException(
564 "getRoles(Object) failed with invalid criteria");
565 }
566 }
567
568 /**
569 * Retrieve a set of Permissions that meet the specified Criteria.
570 *
571 * @param criteria A Criteria of Permissions selection.
572 * @return a set of Permissions that meet the specified Criteria.
573 * @throws DataBackendException if there was an error accessing the data
574 * backend.
575 */
576 public PermissionSet getPermissions(Object criteria)
577 throws DataBackendException
578 {
579 if (criteria instanceof Criteria)
580 {
581 Criteria torqueCriteria = new Criteria();
582 Criteria c = (Criteria)criteria;
583 Iterator keys = c.keySet().iterator();
584 while (keys.hasNext())
585 {
586 String key = (String) keys.next();
587 torqueCriteria.put(PermissionPeerManager.getColumnName(key),
588 c.get(key));
589 }
590 List permissions = new ArrayList(0);
591 try
592 {
593 permissions = PermissionPeerManager.doSelect(torqueCriteria);
594 }
595 catch (TorqueException e)
596 {
597 throw new DataBackendException(
598 "getPermissions(Object) failed", e);
599 }
600
601 return new PermissionSet(permissions);
602 }
603 else
604 {
605 throw new DataBackendException(
606 "getPermissions(Object) failed with invalid criteria");
607 }
608 }
609
610 /**
611 * Retrieves all permissions associated with a role.
612 *
613 * @param role the role name, for which the permissions are to be retrieved.
614 * @return A Permission set for the Role.
615 * @throws DataBackendException if there was an error accessing the data
616 * backend.
617 * @throws UnknownEntityException if the role is not present.
618 */
619 public PermissionSet getPermissions(Role role)
620 throws DataBackendException, UnknownEntityException
621 {
622 boolean roleExists = false;
623 try
624 {
625 lockShared();
626 roleExists = checkExists(role);
627 if (roleExists)
628 {
629 return PermissionPeerManager.retrieveSet(role);
630 }
631 }
632 catch (Exception e)
633 {
634 throw new DataBackendException("getPermissions(Role) failed", e);
635 }
636 finally
637 {
638 unlockShared();
639 }
640 throw new UnknownEntityException("Unknown role '"
641 + role.getName() + "'");
642 }
643
644 /**
645 * Stores Group's attributes. The Groups is required to exist in the system.
646 *
647 * @param group The Group to be stored.
648 * @throws DataBackendException if there was an error accessing the data
649 * backend.
650 * @throws UnknownEntityException if the group does not exist.
651 */
652 public void saveGroup(Group group)
653 throws DataBackendException, UnknownEntityException
654 {
655 boolean groupExists = false;
656 try
657 {
658 groupExists = checkExists(group);
659 if (groupExists)
660 {
661 Criteria criteria = GroupPeerManager.buildCriteria(group);
662 GroupPeerManager.doUpdate(criteria);
663 return;
664 }
665 }
666 catch (Exception e)
667 {
668 throw new DataBackendException("saveGroup(Group) failed", e);
669 }
670 throw new UnknownEntityException("Unknown group '" + group + "'");
671 }
672
673 /**
674 * Stores Role's attributes. The Roles is required to exist in the system.
675 *
676 * @param role The Role to be stored.
677 * @throws DataBackendException if there was an error accessing the data
678 * backend.
679 * @throws UnknownEntityException if the role does not exist.
680 */
681 public void saveRole(Role role)
682 throws DataBackendException, UnknownEntityException
683 {
684 boolean roleExists = false;
685 try
686 {
687 roleExists = checkExists(role);
688 if (roleExists)
689 {
690 Criteria criteria = RolePeerManager.buildCriteria(role);
691 RolePeerManager.doUpdate(criteria);
692 return;
693 }
694 }
695 catch (Exception e)
696 {
697 throw new DataBackendException("saveRole(Role) failed", e);
698 }
699 throw new UnknownEntityException("Unknown role '" + role + "'");
700 }
701
702 /**
703 * Stores Permission's attributes. The Permissions is required to exist in
704 * the system.
705 *
706 * @param permission The Permission to be stored.
707 * @throws DataBackendException if there was an error accessing the data
708 * backend.
709 * @throws UnknownEntityException if the permission does not exist.
710 */
711 public void savePermission(Permission permission)
712 throws DataBackendException, UnknownEntityException
713 {
714 boolean permissionExists = false;
715 try
716 {
717 permissionExists = checkExists(permission);
718 if (permissionExists)
719 {
720 Criteria criteria = PermissionPeerManager.buildCriteria(permission);
721 PermissionPeerManager.doUpdate(criteria);
722 return;
723 }
724 }
725 catch (Exception e)
726 {
727 throw new DataBackendException(
728 "savePermission(Permission) failed", e);
729 }
730 throw new UnknownEntityException("Unknown permission '"
731 + permission + "'");
732 }
733
734 /**
735 * Creates a new group with specified attributes.
736 *
737 * @param group the object describing the group to be created.
738 * @return a new Group object that has id set up properly.
739 * @throws DataBackendException if there was an error accessing the data
740 * backend.
741 * @throws EntityExistsException if the group already exists.
742 */
743 public synchronized Group addGroup(Group group)
744 throws DataBackendException,
745 EntityExistsException
746 {
747 boolean groupExists = false;
748
749 if (StringUtils.isEmpty(group.getName()))
750 {
751 throw new DataBackendException("Could not create "
752 + "a group with empty name!");
753 }
754
755 try
756 {
757 lockExclusive();
758 groupExists = checkExists(group);
759 if (!groupExists)
760 {
761 // add a row to the table
762 Criteria criteria = GroupPeerManager.buildCriteria(group);
763 GroupPeerManager.doInsert(criteria);
764 // try to get the object back using the name as key.
765 criteria = new Criteria();
766 criteria.add(GroupPeerManager.getNameColumn(),
767 group.getName());
768 List results = GroupPeerManager.doSelect(criteria);
769 if (results.size() != 1)
770 {
771 throw new DataBackendException(
772 "Internal error - query returned "
773 + results.size() + " rows");
774 }
775 Group newGroup = (Group) results.get(0);
776 // add the group to system-wide cache
777 getAllGroups().add(newGroup);
778 // return the object with correct id
779 return newGroup;
780 }
781 }
782 catch (Exception e)
783 {
784 throw new DataBackendException("addGroup(Group) failed", e);
785 }
786 finally
787 {
788 unlockExclusive();
789 }
790 // the only way we could get here without return/throw tirggered
791 // is that the groupExists was true.
792 throw new EntityExistsException("Group '" + group + "' already exists");
793 }
794
795 /**
796 * Creates a new role with specified attributes.
797 *
798 * @param role the object describing the role to be created.
799 * @return a new Role object that has id set up properly.
800 * @throws DataBackendException if there was an error accessing the data
801 * backend.
802 * @throws EntityExistsException if the role already exists.
803 */
804 public synchronized Role addRole(Role role)
805 throws DataBackendException, EntityExistsException
806 {
807 boolean roleExists = false;
808
809 if (StringUtils.isEmpty(role.getName()))
810 {
811 throw new DataBackendException("Could not create "
812 + "a role with empty name!");
813 }
814
815 try
816 {
817 lockExclusive();
818 roleExists = checkExists(role);
819 if (!roleExists)
820 {
821 // add a row to the table
822 Criteria criteria = RolePeerManager.buildCriteria(role);
823 RolePeerManager.doInsert(criteria);
824 // try to get the object back using the name as key.
825 criteria = new Criteria();
826 criteria.add(RolePeerManager.getNameColumn(), role.getName());
827 List results = RolePeerManager.doSelect(criteria);
828 if (results.size() != 1)
829 {
830 throw new DataBackendException(
831 "Internal error - query returned "
832 + results.size() + " rows");
833 }
834 Role newRole = (Role) results.get(0);
835 // add the role to system-wide cache
836 getAllRoles().add(newRole);
837 // return the object with correct id
838 return newRole;
839 }
840 }
841 catch (Exception e)
842 {
843 throw new DataBackendException("addRole(Role) failed", e);
844 }
845 finally
846 {
847 unlockExclusive();
848 }
849 // the only way we could get here without return/throw tirggered
850 // is that the roleExists was true.
851 throw new EntityExistsException("Role '" + role + "' already exists");
852 }
853
854 /**
855 * Creates a new permission with specified attributes.
856 *
857 * @param permission the object describing the permission to be created.
858 * @return a new Permission object that has id set up properly.
859 * @throws DataBackendException if there was an error accessing the data
860 * backend.
861 * @throws EntityExistsException if the permission already exists.
862 */
863 public synchronized Permission addPermission(Permission permission)
864 throws DataBackendException, EntityExistsException
865 {
866 boolean permissionExists = false;
867
868 if (StringUtils.isEmpty(permission.getName()))
869 {
870 throw new DataBackendException("Could not create "
871 + "a permission with empty name!");
872 }
873
874 try
875 {
876 lockExclusive();
877 permissionExists = checkExists(permission);
878 if (!permissionExists)
879 {
880 // add a row to the table
881 Criteria criteria = PermissionPeerManager.buildCriteria(permission);
882 PermissionPeerManager.doInsert(criteria);
883 // try to get the object back using the name as key.
884 criteria = new Criteria();
885 criteria.add(PermissionPeerManager.getNameColumn(),
886 permission.getName());
887 List results = PermissionPeerManager.doSelect(criteria);
888 if (results.size() != 1)
889 {
890 throw new DataBackendException(
891 "Internal error - query returned "
892 + results.size() + " rows");
893 }
894 Permission newPermission = (Permission) results.get(0);
895 // add the permission to system-wide cache
896 getAllPermissions().add(newPermission);
897 // return the object with correct id
898 return newPermission;
899 }
900 }
901 catch (Exception e)
902 {
903 throw new DataBackendException(
904 "addPermission(Permission) failed", e);
905 }
906 finally
907 {
908 unlockExclusive();
909 }
910 // the only way we could get here without return/throw tirggered
911 // is that the permissionExists was true.
912 throw new EntityExistsException("Permission '" + permission
913 + "' already exists");
914 }
915
916 /**
917 * Removes a Group from the system.
918 *
919 * @param group The object describing the group to be removed.
920 * @throws DataBackendException if there was an error accessing the data
921 * backend.
922 * @throws UnknownEntityException if the group does not exist.
923 */
924 public synchronized void removeGroup(Group group)
925 throws DataBackendException, UnknownEntityException
926 {
927 boolean groupExists = false;
928 try
929 {
930 lockExclusive();
931 groupExists = checkExists(group);
932 if (groupExists)
933 {
934 Criteria criteria = GroupPeerManager.buildCriteria(group);
935 GroupPeerManager.doDelete(criteria);
936 getAllGroups().remove(group);
937 return;
938 }
939 }
940 catch (Exception e)
941 {
942 log.error("Failed to delete a Group");
943 log.error(e);
944 throw new DataBackendException("removeGroup(Group) failed", e);
945 }
946 finally
947 {
948 unlockExclusive();
949 }
950 throw new UnknownEntityException("Unknown group '" + group + "'");
951 }
952
953 /**
954 * Removes a Role from the system.
955 *
956 * @param role The object describing the role to be removed.
957 * @throws DataBackendException if there was an error accessing the data
958 * backend.
959 * @throws UnknownEntityException if the role does not exist.
960 */
961 public synchronized void removeRole(Role role)
962 throws DataBackendException, UnknownEntityException
963 {
964 boolean roleExists = false;
965 try
966 {
967 lockExclusive();
968 roleExists = checkExists(role);
969 if (roleExists)
970 {
971 // revoke all permissions from the role to be deleted
972 revokeAll(role);
973 Criteria criteria = RolePeerManager.buildCriteria(role);
974 RolePeerManager.doDelete(criteria);
975 getAllRoles().remove(role);
976 return;
977 }
978 }
979 catch (Exception e)
980 {
981 throw new DataBackendException("removeRole(Role)", e);
982 }
983 finally
984 {
985 unlockExclusive();
986 }
987 throw new UnknownEntityException("Unknown role '" + role + "'");
988 }
989
990 /**
991 * Removes a Permission from the system.
992 *
993 * @param permission The object describing the permission to be removed.
994 * @throws DataBackendException if there was an error accessing the data
995 * backend.
996 * @throws UnknownEntityException if the permission does not exist.
997 */
998 public synchronized void removePermission(Permission permission)
999 throws DataBackendException, UnknownEntityException
1000 {
1001 boolean permissionExists = false;
1002 try
1003 {
1004 lockExclusive();
1005 permissionExists = checkExists(permission);
1006 if (permissionExists)
1007 {
1008 Criteria criteria = PermissionPeerManager.buildCriteria(permission);
1009 PermissionPeerManager.doDelete(criteria);
1010 getAllPermissions().remove(permission);
1011 return;
1012 }
1013 }
1014 catch (Exception e)
1015 {
1016 throw new DataBackendException("removePermission(Permission)", e);
1017 }
1018 finally
1019 {
1020 unlockExclusive();
1021 }
1022 throw new UnknownEntityException("Unknown permission '"
1023 + permission + "'");
1024 }
1025
1026 /**
1027 * Renames an existing Group.
1028 *
1029 * @param group The object describing the group to be renamed.
1030 * @param name the new name for the group.
1031 * @throws DataBackendException if there was an error accessing the data
1032 * backend.
1033 * @throws UnknownEntityException if the group does not exist.
1034 */
1035 public synchronized void renameGroup(Group group, String name)
1036 throws DataBackendException, UnknownEntityException
1037 {
1038 boolean groupExists = false;
1039 try
1040 {
1041 lockExclusive();
1042 groupExists = checkExists(group);
1043 if (groupExists)
1044 {
1045 group.setName(name);
1046 Criteria criteria = GroupPeerManager.buildCriteria(group);
1047 GroupPeerManager.doUpdate(criteria);
1048 return;
1049 }
1050 }
1051 catch (Exception e)
1052 {
1053 throw new DataBackendException("renameGroup(Group,String)", e);
1054 }
1055 finally
1056 {
1057 unlockExclusive();
1058 }
1059 throw new UnknownEntityException("Unknown group '" + group + "'");
1060 }
1061
1062 /**
1063 * Renames an existing Role.
1064 *
1065 * @param role The object describing the role to be renamed.
1066 * @param name the new name for the role.
1067 * @throws DataBackendException if there was an error accessing the data
1068 * backend.
1069 * @throws UnknownEntityException if the role does not exist.
1070 */
1071 public synchronized void renameRole(Role role, String name)
1072 throws DataBackendException, UnknownEntityException
1073 {
1074 boolean roleExists = false;
1075 try
1076 {
1077 lockExclusive();
1078 roleExists = checkExists(role);
1079 if (roleExists)
1080 {
1081 role.setName(name);
1082 Criteria criteria = RolePeerManager.buildCriteria(role);
1083 RolePeerManager.doUpdate(criteria);
1084 return;
1085 }
1086 }
1087 catch (Exception e)
1088 {
1089 throw new DataBackendException("renameRole(Role,String)", e);
1090 }
1091 finally
1092 {
1093 unlockExclusive();
1094 }
1095 throw new UnknownEntityException("Unknown role '" + role + "'");
1096 }
1097
1098 /**
1099 * Renames an existing Permission.
1100 *
1101 * @param permission The object describing the permission to be renamed.
1102 * @param name the new name for the permission.
1103 * @throws DataBackendException if there was an error accessing the data
1104 * backend.
1105 * @throws UnknownEntityException if the permission does not exist.
1106 */
1107 public synchronized void renamePermission(Permission permission,
1108 String name)
1109 throws DataBackendException, UnknownEntityException
1110 {
1111 boolean permissionExists = false;
1112 try
1113 {
1114 lockExclusive();
1115 permissionExists = checkExists(permission);
1116 if (permissionExists)
1117 {
1118 permission.setName(name);
1119 Criteria criteria = PermissionPeerManager.buildCriteria(permission);
1120 PermissionPeerManager.doUpdate(criteria);
1121 return;
1122 }
1123 }
1124 catch (Exception e)
1125 {
1126 throw new DataBackendException(
1127 "renamePermission(Permission,name)", e);
1128 }
1129 finally
1130 {
1131 unlockExclusive();
1132 }
1133 throw new UnknownEntityException("Unknown permission '"
1134 + permission + "'");
1135 }
1136
1137 /* Service specific implementation methods */
1138
1139 /**
1140 * Determines if the <code>Group</code> exists in the security system.
1141 *
1142 * @param group a <code>Group</code> value
1143 * @return true if the group exists in the system, false otherwise
1144 * @throws DataBackendException when more than one Group with
1145 * the same name exists.
1146 * @throws Exception A generic exception.
1147 */
1148 protected boolean checkExists(Group group)
1149 throws DataBackendException, Exception
1150 {
1151 return GroupPeerManager.checkExists(group);
1152 }
1153
1154 /**
1155 * Determines if the <code>Role</code> exists in the security system.
1156 *
1157 * @param role a <code>Role</code> value
1158 * @return true if the role exists in the system, false otherwise
1159 * @throws DataBackendException when more than one Role with
1160 * the same name exists.
1161 * @throws Exception A generic exception.
1162 */
1163 protected boolean checkExists(Role role)
1164 throws DataBackendException, Exception
1165 {
1166 return RolePeerManager.checkExists(role);
1167 }
1168
1169 /**
1170 * Determines if the <code>Permission</code> exists in the security system.
1171 *
1172 * @param permission a <code>Permission</code> value
1173 * @return true if the permission exists in the system, false otherwise
1174 * @throws DataBackendException when more than one Permission with
1175 * the same name exists.
1176 * @throws Exception A generic exception.
1177 */
1178 protected boolean checkExists(Permission permission)
1179 throws DataBackendException, Exception
1180 {
1181 return PermissionPeerManager.checkExists(permission);
1182 }
1183
1184
1185 /**
1186 * Retrieves all groups defined in the system.
1187 *
1188 * @return the names of all groups defined in the system.
1189 * @throws DataBackendException if there was an error accessing the
1190 * data backend.
1191 */
1192 public GroupSet getAllGroups() throws DataBackendException
1193 {
1194 return getGroups(new Criteria());
1195 }
1196
1197
1198 /**
1199 * Retrieves all permissions defined in the system.
1200 *
1201 * @return the names of all roles defined in the system.
1202 * @throws DataBackendException if there was an error accessing the
1203 * data backend.
1204 */
1205 public PermissionSet getAllPermissions() throws DataBackendException
1206 {
1207 return getPermissions(new Criteria());
1208 }
1209
1210
1211 /**
1212 * Retrieves all roles defined in the system.
1213 *
1214 * @return the names of all roles defined in the system.
1215 * @throws DataBackendException if there was an error accessing the
1216 * data backend.
1217 */
1218 public RoleSet getAllRoles() throws DataBackendException
1219 {
1220 return getRoles(new Criteria());
1221 }
1222
1223
1224 /**
1225 * Retrieve a set of users that meet the specified criteria.
1226 *
1227 * As the keys for the criteria, you should use the constants that
1228 * are defined in {@link User} interface, plus the names
1229 * of the custom attributes you added to your user representation
1230 * in the data storage. Use verbatim names of the attributes -
1231 * without table name prefix in case of Torque implementation.
1232 *
1233 * @param criteria The criteria of selection.
1234 * @return a List of users meeting the criteria.
1235 * @throws DataBackendException if there is a problem accessing the
1236 * storage.
1237 */
1238 public List getUserList(Object criteria) throws DataBackendException
1239 {
1240 return getUserManager().retrieveList(criteria);
1241 }
1242
1243 }