View Javadoc

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