View Javadoc

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