001package org.apache.turbine.services.security;
002
003
004/*
005 * Licensed to the Apache Software Foundation (ASF) under one
006 * or more contributor license agreements.  See the NOTICE file
007 * distributed with this work for additional information
008 * regarding copyright ownership.  The ASF licenses this file
009 * to you under the Apache License, Version 2.0 (the
010 * "License"); you may not use this file except in compliance
011 * with the License.  You may obtain a copy of the License at
012 *
013 *   http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing,
016 * software distributed under the License is distributed on an
017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018 * KIND, either express or implied.  See the License for the
019 * specific language governing permissions and limitations
020 * under the License.
021 */
022
023
024import org.apache.commons.configuration.Configuration;
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.apache.fulcrum.security.GroupManager;
028import org.apache.fulcrum.security.PermissionManager;
029import org.apache.fulcrum.security.RoleManager;
030import org.apache.fulcrum.security.acl.AccessControlList;
031import org.apache.fulcrum.security.entity.Group;
032import org.apache.fulcrum.security.entity.Permission;
033import org.apache.fulcrum.security.entity.Role;
034import org.apache.fulcrum.security.model.turbine.TurbineModelManager;
035import org.apache.fulcrum.security.model.turbine.entity.TurbineRole;
036import org.apache.fulcrum.security.util.DataBackendException;
037import org.apache.fulcrum.security.util.EntityExistsException;
038import org.apache.fulcrum.security.util.GroupSet;
039import org.apache.fulcrum.security.util.PasswordMismatchException;
040import org.apache.fulcrum.security.util.PermissionSet;
041import org.apache.fulcrum.security.util.RoleSet;
042import org.apache.fulcrum.security.util.UnknownEntityException;
043import org.apache.turbine.om.security.User;
044import org.apache.turbine.services.InitializationException;
045import org.apache.turbine.services.ServiceManager;
046import org.apache.turbine.services.TurbineBaseService;
047import org.apache.turbine.services.TurbineServices;
048
049/**
050 * This is a common subset of SecurityService implementation.
051 *
052 * Provided functionality includes:
053 * <ul>
054 * <li> methods for retrieving User objects, that delegates functionality
055 *      to the pluggable implementations of the User interface.
056 * <li> synchronization mechanism for methods reading/modifying the security
057 *      information, that guarantees that multiple threads may read the
058 *      information concurrently, but threads that modify the information
059 *      acquires exclusive access.
060 * <li> implementation of convenience methods for retrieving security entities
061 *      that maintain in-memory caching of objects for fast access.
062 * </ul>
063 *
064 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
065 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
066 * @author <a href="mailto:marco@intermeta.de">Marco Kn&uuml;ttel</a>
067 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
068 * @version $Id: DefaultSecurityService.java 1524210 2013-09-17 20:22:56Z tv $
069 */
070public class DefaultSecurityService
071        extends TurbineBaseService
072        implements SecurityService
073{
074    /** The number of threads concurrently reading security information */
075    private int readerCount = 0;
076
077    /** The instance of UserManager the SecurityService uses */
078    private UserManager userManager = null;
079
080    /** The instance of GroupManager the SecurityService uses */
081    private GroupManager groupManager;
082
083    /** The instance of RoleManager the SecurityService uses */
084    private RoleManager roleManager;
085
086    /** The instance of PermissionManager the SecurityService uses */
087    private PermissionManager permissionManager;
088
089    /** The instance of ModelManager the SecurityService uses */
090    private TurbineModelManager modelManager;
091
092    /**
093     * The Group object that represents the <a href="#global">global group</a>.
094     */
095    private static Group globalGroup = null;
096
097    /** Logging */
098    private static Log log = LogFactory.getLog(DefaultSecurityService.class);
099
100    /**
101     * Initializes the SecurityService, locating the appropriate UserManager
102     * This is a zero parameter variant which queries the Turbine Servlet
103     * for its config.
104     *
105     * @throws InitializationException Something went wrong in the init stage
106     */
107    public void init()
108            throws InitializationException
109    {
110        ServiceManager manager = TurbineServices.getInstance();
111
112        this.groupManager = (GroupManager)manager.getService(GroupManager.ROLE);
113        this.roleManager = (RoleManager)manager.getService(RoleManager.ROLE);
114        this.permissionManager = (PermissionManager)manager.getService(PermissionManager.ROLE);
115        this.modelManager = (TurbineModelManager)manager.getService(TurbineModelManager.ROLE);
116
117        Configuration conf = getConfiguration();
118
119        String userManagerClassName = conf.getString(
120                SecurityService.USER_MANAGER_KEY,
121                SecurityService.USER_MANAGER_DEFAULT);
122
123        try
124        {
125            this.userManager =
126                    (UserManager) Class.forName(userManagerClassName).newInstance();
127
128            userManager.init(conf);
129        }
130        catch (Exception e)
131        {
132            throw new InitializationException("Failed to instantiate UserManager", e);
133        }
134
135        setInit(true);
136    }
137
138    /**
139     * Construct a blank User object.
140     *
141     * @return an object implementing User interface.
142     * @throws UnknownEntityException if the object could not be instantiated.
143     */
144    public <U extends User> U getUserInstance()
145            throws UnknownEntityException
146    {
147        U user;
148        try
149        {
150            user = getUserManager().getUserInstance();
151        }
152        catch (DataBackendException e)
153        {
154            throw new UnknownEntityException(
155                    "Failed instantiate an User implementation object", e);
156        }
157        return user;
158    }
159
160    /**
161     * Construct a blank User object.
162     *
163     * @param userName The name of the user.
164     *
165     * @return an object implementing User interface.
166     *
167     * @throws UnknownEntityException if the object could not be instantiated.
168     */
169    public <U extends User> U getUserInstance(String userName)
170            throws UnknownEntityException
171    {
172        U user;
173        try
174        {
175            user = getUserManager().getUserInstance(userName);
176        }
177        catch (DataBackendException e)
178        {
179            throw new UnknownEntityException(
180                    "Failed instantiate an User implementation object", e);
181        }
182        return user;
183    }
184
185    /**
186     * Construct a blank Group object.
187     *
188     * @return an object implementing Group interface.
189     * @throws UnknownEntityException if the object could not be instantiated.
190     */
191    public <G extends Group> G getGroupInstance()
192            throws UnknownEntityException
193    {
194        G group;
195        try
196        {
197            group = groupManager.getGroupInstance();
198        }
199        catch (Exception e)
200        {
201            throw new UnknownEntityException("Failed to instantiate a Group implementation object", e);
202        }
203        return group;
204    }
205
206    /**
207     * Construct a blank Group object.
208     *
209     * @param groupName The name of the Group
210     *
211     * @return an object implementing Group interface.
212     *
213     * @throws UnknownEntityException if the object could not be instantiated.
214     */
215    public <G extends Group> G getGroupInstance(String groupName)
216            throws UnknownEntityException
217    {
218        G group;
219        try
220        {
221            group = groupManager.getGroupInstance(groupName);
222        }
223        catch (Exception e)
224        {
225            throw new UnknownEntityException("Failed to instantiate a Group implementation object", e);
226        }
227        return group;
228    }
229
230    /**
231     * Construct a blank Permission object.
232     *
233     * @return an object implementing Permission interface.
234     * @throws UnknownEntityException if the object could not be instantiated.
235     */
236    public <P extends Permission> P getPermissionInstance()
237            throws UnknownEntityException
238    {
239        P permission;
240        try
241        {
242            permission = permissionManager.getPermissionInstance();
243        }
244        catch (Exception e)
245        {
246            throw new UnknownEntityException("Failed to instantiate a Permission implementation object", e);
247        }
248        return permission;
249    }
250
251    /**
252     * Construct a blank Permission object.
253     *
254     * @param permName The name of the permission.
255     *
256     * @return an object implementing Permission interface.
257     * @throws UnknownEntityException if the object could not be instantiated.
258     */
259    public <P extends Permission> P getPermissionInstance(String permName)
260            throws UnknownEntityException
261    {
262        P permission;
263        try
264        {
265            permission = permissionManager.getPermissionInstance(permName);
266        }
267        catch (Exception e)
268        {
269            throw new UnknownEntityException("Failed to instantiate a Permission implementation object", e);
270        }
271        return permission;
272    }
273
274    /**
275     * Construct a blank Role object.
276     *
277     * @return an object implementing Role interface.
278     * @throws UnknownEntityException if the object could not be instantiated.
279     */
280    public <R extends Role> R getRoleInstance()
281            throws UnknownEntityException
282    {
283        R role;
284        try
285        {
286            role = roleManager.getRoleInstance();
287        }
288        catch (Exception e)
289        {
290            throw new UnknownEntityException("Failed to instantiate a Role implementation object", e);
291        }
292        return role;
293    }
294
295    /**
296     * Construct a blank Role object.
297     *
298     * @param roleName The name of the role.
299     *
300     * @return an object implementing Role interface.
301     *
302     * @throws UnknownEntityException if the object could not be instantiated.
303     */
304    public <R extends Role> R getRoleInstance(String roleName)
305            throws UnknownEntityException
306    {
307        R role;
308        try
309        {
310            role = roleManager.getRoleInstance();
311        }
312        catch (Exception e)
313        {
314            throw new UnknownEntityException("Failed to instantiate a Role implementation object", e);
315        }
316        return role;
317    }
318
319    /**
320     * Returns the configured UserManager.
321     *
322     * @return An UserManager object
323     */
324    public UserManager getUserManager()
325    {
326        return userManager;
327    }
328
329    /**
330     * Check whether a specified user's account exists.
331     *
332     * The login name is used for looking up the account.
333     *
334     * @param user The user to be checked.
335     * @return true if the specified account exists
336     * @throws DataBackendException if there was an error accessing the data
337     *         backend.
338     */
339    public boolean accountExists(User user)
340            throws DataBackendException
341    {
342        return getUserManager().accountExists(user);
343    }
344
345    /**
346     * Check whether a specified user's account exists.
347     *
348     * The login name is used for looking up the account.
349     *
350     * @param userName The name of the user to be checked.
351     * @return true if the specified account exists
352     * @throws DataBackendException if there was an error accessing the data
353     *         backend.
354     */
355    public boolean accountExists(String userName)
356            throws DataBackendException
357    {
358        return getUserManager().accountExists(userName);
359    }
360
361    /**
362     * Authenticates an user, and constructs an User object to represent
363     * him/her.
364     *
365     * @param username The user name.
366     * @param password The user password.
367     * @return An authenticated Turbine User.
368     * @throws PasswordMismatchException if the supplied password was incorrect.
369     * @throws UnknownEntityException if the user's account does not
370     *            exist in the database.
371     * @throws DataBackendException if there is a problem accessing the storage.
372     */
373    public <U extends User> U getAuthenticatedUser(String username, String password)
374            throws DataBackendException, UnknownEntityException,
375                   PasswordMismatchException
376    {
377        return getUserManager().retrieve(username, password);
378    }
379
380    /**
381     * Constructs an User object to represent a registered user of the
382     * application.
383     *
384     * @param username The user name.
385     * @return A Turbine User.
386     * @throws UnknownEntityException if the user's account does not exist
387     * @throws DataBackendException if there is a problem accessing the storage.
388     */
389    public <U extends User> U getUser(String username)
390            throws DataBackendException, UnknownEntityException
391    {
392        return getUserManager().retrieve(username);
393    }
394
395    /**
396     * Constructs an User object to represent an anonymous user of the
397     * application.
398     *
399     * @return An anonymous Turbine User.
400     * @throws UnknownEntityException if the implementation of User interface
401     *         could not be determined, or does not exist.
402     */
403    public <U extends User> U getAnonymousUser()
404            throws UnknownEntityException
405    {
406        return getUserManager().getAnonymousUser();
407    }
408
409    /**
410     * Checks whether a passed user object matches the anonymous user pattern
411     * according to the configured user manager
412     *
413     * @param user An user object
414     *
415     * @return True if this is an anonymous user
416     *
417     */
418    public boolean isAnonymousUser(User user)
419    {
420        return getUserManager().isAnonymousUser(user);
421    }
422
423    /**
424     * Saves User's data in the permanent storage. The user account is required
425     * to exist in the storage.
426     *
427     * @param user the User object to save
428     * @throws UnknownEntityException if the user's account does not
429     *         exist in the database.
430     * @throws DataBackendException if there is a problem accessing the storage.
431     */
432    public void saveUser(User user)
433            throws UnknownEntityException, DataBackendException
434    {
435        getUserManager().store(user);
436    }
437
438    /**
439     * Saves User data when the session is unbound. The user account is required
440     * to exist in the storage.
441     *
442     * LastLogin, AccessCounter, persistent pull tools, and any data stored
443     * in the permData hashtable that is not mapped to a column will be saved.
444     *
445     * @exception UnknownEntityException if the user's account does not
446     *            exist in the database.
447     * @exception DataBackendException if there is a problem accessing the
448     *            storage.
449     */
450    public void saveOnSessionUnbind(User user)
451            throws UnknownEntityException, DataBackendException
452    {
453        getUserManager().saveOnSessionUnbind(user);
454    }
455
456    /**
457     * Creates new user account with specified attributes.
458     *
459     * @param user the object describing account to be created.
460     * @param password The password to use for the account.
461     *
462     * @throws DataBackendException if there was an error accessing the
463     *         data backend.
464     * @throws EntityExistsException if the user account already exists.
465     */
466    public void addUser(User user, String password)
467            throws DataBackendException, EntityExistsException
468    {
469        getUserManager().createAccount(user, password);
470    }
471
472    /**
473     * Removes an user account from the system.
474     *
475     * @param user the object describing the account to be removed.
476     * @throws DataBackendException if there was an error accessing the data
477     *         backend.
478     * @throws UnknownEntityException if the user account is not present.
479     */
480    public void removeUser(User user)
481            throws DataBackendException, UnknownEntityException
482    {
483        // revoke all roles form the user
484        modelManager.revokeAll(user);
485        getUserManager().removeAccount(user);
486    }
487
488    /**
489     * Change the password for an User.
490     *
491     * @param user an User to change password for.
492     * @param oldPassword the current password supplied by the user.
493     * @param newPassword the current password requested by the user.
494     * @throws PasswordMismatchException if the supplied password was incorrect.
495     * @throws UnknownEntityException if the user's record does not
496     *            exist in the database.
497     * @throws DataBackendException if there is a problem accessing the storage.
498     */
499    public void changePassword(User user, String oldPassword,
500            String newPassword)
501            throws PasswordMismatchException, UnknownEntityException,
502                   DataBackendException
503    {
504        getUserManager().changePassword(user, oldPassword, newPassword);
505    }
506
507    /**
508     * Forcibly sets new password for an User.
509     *
510     * This is supposed by the administrator to change the forgotten or
511     * compromised passwords. Certain implementatations of this feature
512     * would require administrative level access to the authenticating
513     * server / program.
514     *
515     * @param user an User to change password for.
516     * @param password the new password.
517     * @throws UnknownEntityException if the user's record does not
518     *            exist in the database.
519     * @throws DataBackendException if there is a problem accessing the storage.
520     */
521    public void forcePassword(User user, String password)
522            throws UnknownEntityException, DataBackendException
523    {
524        getUserManager().forcePassword(user, password);
525    }
526
527    /**
528     * Acquire a shared lock on the security information repository.
529     *
530     * Methods that read security information need to invoke this
531     * method at the beginning of their body.
532     */
533    protected synchronized void lockShared()
534    {
535        readerCount++;
536    }
537
538    /**
539     * Release a shared lock on the security information repository.
540     *
541     * Methods that read security information need to invoke this
542     * method at the end of their body.
543     */
544    protected synchronized void unlockShared()
545    {
546        readerCount--;
547        this.notify();
548    }
549
550    /**
551     * Acquire an exclusive lock on the security information repository.
552     *
553     * Methods that modify security information need to invoke this
554     * method at the beginning of their body. Note! Those methods must
555     * be <code>synchronized</code> themselves!
556     */
557    protected void lockExclusive()
558    {
559        while (readerCount > 0)
560        {
561            try
562            {
563                this.wait();
564            }
565            catch (InterruptedException e)
566            {
567                // ignore
568            }
569        }
570    }
571
572    /**
573     * Release an exclusive lock on the security information repository.
574     *
575     * This method is provided only for completeness. It does not really
576     * do anything. Note! Methods that modify security information
577     * must be <code>synchronized</code>!
578     */
579    protected void unlockExclusive()
580    {
581        // do nothing
582    }
583
584    /**
585     * Provides a reference to the Group object that represents the
586     * <a href="#global">global group</a>.
587     *
588     * @return a Group object that represents the global group.
589     */
590    public <G extends Group> G getGlobalGroup()
591    {
592        if (globalGroup == null)
593        {
594            synchronized (DefaultSecurityService.class)
595            {
596                if (globalGroup == null)
597                {
598                    try
599                    {
600                        globalGroup = modelManager.getGlobalGroup();
601                    }
602                    catch (DataBackendException e)
603                    {
604                        log.error("Failed to retrieve global group object: ", e);
605                    }
606                }
607            }
608        }
609        @SuppressWarnings("unchecked")
610        G g = (G)globalGroup;
611        return g;
612    }
613
614    /**
615     * Retrieve a Group object with specified name.
616     *
617     * @param name the name of the Group.
618     * @return an object representing the Group with specified name.
619     * @throws DataBackendException if there was an error accessing the
620     *         data backend.
621     * @throws UnknownEntityException if the group does not exist.
622     */
623    public <G extends Group> G getGroupByName(String name)
624            throws DataBackendException, UnknownEntityException
625    {
626        return groupManager.getGroupByName(name);
627    }
628
629    /**
630     * Retrieve a Group object with specified Id.
631     *
632     * @param id the id of the Group.
633     * @return an object representing the Group with specified name.
634     * @throws UnknownEntityException if the permission does not
635     *            exist in the database.
636     * @throws DataBackendException if there is a problem accessing the
637     *            storage.
638     */
639    public <G extends Group> G getGroupById(int id)
640            throws DataBackendException, UnknownEntityException
641    {
642        return groupManager.getGroupById(Integer.valueOf(id));
643    }
644
645    /**
646     * Retrieve a Role object with specified name.
647     *
648     * @param name the name of the Role.
649     * @return an object representing the Role with specified name.
650     * @throws DataBackendException if there was an error accessing the
651     *         data backend.
652     * @throws UnknownEntityException if the role does not exist.
653     */
654    public <R extends Role> R getRoleByName(String name)
655            throws DataBackendException, UnknownEntityException
656    {
657        R role = roleManager.getRoleByName(name);
658        if (role instanceof TurbineRole)
659        {
660            ((TurbineRole)role).setPermissions(getPermissions(role));
661        }
662        return role;
663    }
664
665    /**
666     * Retrieve a Role object with specified Id.
667     * @param id the id of the Role.
668     * @return an object representing the Role with specified name.
669     * @throws UnknownEntityException if the permission does not
670     *            exist in the database.
671     * @throws DataBackendException if there is a problem accessing the
672     *            storage.
673     */
674    public <R extends Role> R getRoleById(int id)
675            throws DataBackendException,
676                   UnknownEntityException
677    {
678        R role = roleManager.getRoleById(Integer.valueOf(id));
679        if (role instanceof TurbineRole)
680        {
681            ((TurbineRole)role).setPermissions(getPermissions(role));
682        }
683        return role;
684    }
685
686    /**
687     * Retrieve a Permission object with specified name.
688     *
689     * @param name the name of the Permission.
690     * @return an object representing the Permission with specified name.
691     * @throws DataBackendException if there was an error accessing the
692     *         data backend.
693     * @throws UnknownEntityException if the permission does not exist.
694     */
695    public <P extends Permission> P getPermissionByName(String name)
696            throws DataBackendException, UnknownEntityException
697    {
698        return permissionManager.getPermissionByName(name);
699    }
700
701    /**
702     * Retrieve a Permission object with specified Id.
703     *
704     * @param id the id of the Permission.
705     * @return an object representing the Permission with specified name.
706     * @throws UnknownEntityException if the permission does not
707     *            exist in the database.
708     * @throws DataBackendException if there is a problem accessing the
709     *            storage.
710     */
711    public <P extends Permission> P getPermissionById(int id)
712            throws DataBackendException,
713                   UnknownEntityException
714    {
715        return permissionManager.getPermissionById(Integer.valueOf(id));
716    }
717
718    /**
719     * Retrieves all groups defined in the system.
720     *
721     * @return the names of all groups defined in the system.
722     * @throws DataBackendException if there was an error accessing the
723     *         data backend.
724     */
725    public GroupSet getAllGroups() throws DataBackendException
726    {
727        return groupManager.getAllGroups();
728    }
729
730    /**
731     * Retrieves all roles defined in the system.
732     *
733     * @return the names of all roles defined in the system.
734     * @throws DataBackendException if there was an error accessing the
735     *         data backend.
736     */
737    public RoleSet getAllRoles() throws DataBackendException
738    {
739        return roleManager.getAllRoles();
740    }
741
742    /**
743     * Retrieves all permissions defined in the system.
744     *
745     * @return the names of all roles defined in the system.
746     * @throws DataBackendException if there was an error accessing the
747     *         data backend.
748     */
749    public PermissionSet getAllPermissions() throws DataBackendException
750    {
751        return permissionManager.getAllPermissions();
752    }
753
754    /*-----------------------------------------------------------------------
755    Creation of AccessControlLists
756    -----------------------------------------------------------------------*/
757
758    /**
759     * Constructs an AccessControlList for a specific user.
760     *
761     * @param user the user for whom the AccessControlList are to be retrieved
762     * @return The AccessControList object constructed from the user object.
763     * @throws DataBackendException if there was an error accessing the data
764     *         backend.
765     * @throws UnknownEntityException if user account is not present.
766     */
767    public <A extends AccessControlList> A getACL(User user)
768        throws DataBackendException, UnknownEntityException
769    {
770        return getUserManager().getACL(user);
771    }
772
773    /*-----------------------------------------------------------------------
774    Security management
775    -----------------------------------------------------------------------*/
776
777    /**
778     * Grant an User a Role in a Group.
779     *
780     * @param user the user.
781     * @param group the group.
782     * @param role the role.
783     * @throws DataBackendException if there was an error accessing the data
784     *         backend.
785     * @throws UnknownEntityException if user account, group or role is not
786     *         present.
787     */
788    public void grant(User user, Group group, Role role)
789    throws DataBackendException, UnknownEntityException
790    {
791        modelManager.grant(user, group, role);
792    }
793
794    /**
795     * Revoke a Role in a Group from an User.
796     *
797     * @param user the user.
798     * @param group the group.
799     * @param role the role.
800     * @throws DataBackendException if there was an error accessing the data
801     *         backend.
802     * @throws UnknownEntityException if user account, group or role is not
803     *         present.
804     */
805    public void revoke(User user, Group group, Role role)
806        throws DataBackendException, UnknownEntityException
807    {
808        modelManager.revoke(user, group, role);
809    }
810
811    /**
812     * Revokes all roles from an User.
813     *
814     * This method is used when deleting an account.
815     *
816     * @param user the User.
817     * @throws DataBackendException if there was an error accessing the data
818     *         backend.
819     * @throws UnknownEntityException if the account is not present.
820     */
821    public void revokeAll(User user)
822        throws DataBackendException, UnknownEntityException
823    {
824        modelManager.revokeAll(user);
825    }
826
827    /**
828     * Grants a Role a Permission
829     *
830     * @param role the Role.
831     * @param permission the Permission.
832     * @throws DataBackendException if there was an error accessing the data
833     *         backend.
834     * @throws UnknownEntityException if role or permission is not present.
835     */
836    public void grant(Role role, Permission permission)
837        throws DataBackendException, UnknownEntityException
838    {
839        modelManager.grant(role, permission);
840    }
841
842    /**
843     * Revokes a Permission from a Role.
844     *
845     * @param role the Role.
846     * @param permission the Permission.
847     * @throws DataBackendException if there was an error accessing the data
848     *         backend.
849     * @throws UnknownEntityException if role or permission is not present.
850     */
851    public void revoke(Role role, Permission permission)
852        throws DataBackendException, UnknownEntityException
853    {
854        modelManager.revoke(role, permission);
855    }
856
857    /**
858     * Revokes all permissions from a Role.
859     *
860     * This method is user when deleting a Role.
861     *
862     * @param role the Role
863     * @throws DataBackendException if there was an error accessing the data
864     *         backend.
865     * @throws  UnknownEntityException if the Role is not present.
866     */
867    public void revokeAll(Role role)
868        throws DataBackendException, UnknownEntityException
869    {
870        modelManager.revokeAll(role);
871    }
872
873    /**
874     * Retrieves all permissions associated with a role.
875     *
876     * @param role the role name, for which the permissions are to be retrieved.
877     * @return the Permissions for the specified role
878     * @throws DataBackendException if there was an error accessing the data
879     *         backend.
880     * @throws UnknownEntityException if the role is not present.
881     */
882    public PermissionSet getPermissions(Role role)
883            throws DataBackendException, UnknownEntityException
884    {
885        return ((TurbineRole)role).getPermissions();
886    }
887
888    /**
889     * Creates a new group with specified attributes.
890     *
891     * @param group the object describing the group to be created.
892     * @throws DataBackendException if there was an error accessing the data
893     *         backend.
894     * @throws EntityExistsException if the group already exists.
895     */
896    public <G extends Group> G addGroup(G group)
897            throws DataBackendException, EntityExistsException
898    {
899        return groupManager.addGroup(group);
900    }
901
902    /**
903     * Creates a new role with specified attributes.
904     *
905     * @param role the objects describing the role to be created.
906     * @throws DataBackendException if there was an error accessing the data
907     *         backend.
908     * @throws EntityExistsException if the role already exists.
909     */
910    public <R extends Role> R addRole(R role)
911            throws DataBackendException, EntityExistsException
912    {
913        return roleManager.addRole(role);
914    }
915
916    /**
917     * Creates a new permission with specified attributes.
918     *
919     * @param permission the objects describing the permission to be created.
920     * @throws DataBackendException if there was an error accessing the data
921     *         backend.
922     * @throws EntityExistsException if the permission already exists.
923     */
924    public <P extends Permission> P addPermission(P permission)
925            throws DataBackendException, EntityExistsException
926    {
927        return permissionManager.addPermission(permission);
928    }
929
930    /**
931     * Removes a Group from the system.
932     *
933     * @param group the object describing group to be removed.
934     * @throws DataBackendException if there was an error accessing the data
935     *         backend.
936     * @throws UnknownEntityException if the group does not exist.
937     */
938    public void removeGroup(Group group)
939            throws DataBackendException, UnknownEntityException
940    {
941        groupManager.removeGroup(group);
942    }
943
944    /**
945     * Removes a Role from the system.
946     *
947     * @param role The object describing the role to be removed.
948     * @throws DataBackendException if there was an error accessing the data backend.
949     * @throws UnknownEntityException if the role does not exist.
950     */
951    public void removeRole(Role role)
952            throws DataBackendException, UnknownEntityException
953    {
954        roleManager.removeRole(role);
955    }
956
957    /**
958     * Removes a Permission from the system.
959     *
960     * @param permission The object describing the permission to be removed.
961     * @throws DataBackendException if there was an error accessing the data
962     *         backend.
963     * @throws UnknownEntityException if the permission does not exist.
964     */
965    public void removePermission(Permission permission)
966            throws DataBackendException, UnknownEntityException
967    {
968        permissionManager.removePermission(permission);
969    }
970
971    /**
972     * Renames an existing Group.
973     *
974     * @param group The object describing the group to be renamed.
975     * @param name the new name for the group.
976     * @throws DataBackendException if there was an error accessing the data
977     *         backend.
978     * @throws UnknownEntityException if the group does not exist.
979     */
980    public void renameGroup(Group group, String name)
981            throws DataBackendException, UnknownEntityException
982    {
983        groupManager.renameGroup(group, name);
984    }
985
986    /**
987     * Renames an existing Role.
988     *
989     * @param role The object describing the role to be renamed.
990     * @param name the new name for the role.
991     * @throws DataBackendException if there was an error accessing the data
992     *         backend.
993     * @throws UnknownEntityException if the role does not exist.
994     */
995    public void renameRole(Role role, String name)
996            throws DataBackendException, UnknownEntityException
997    {
998        roleManager.renameRole(role, name);
999    }
1000
1001    /**
1002     * Renames an existing Permission.
1003     *
1004     * @param permission The object describing the permission to be renamed.
1005     * @param name the new name for the permission.
1006     * @throws DataBackendException if there was an error accessing the data
1007     *         backend.
1008     * @throws UnknownEntityException if the permission does not exist.
1009     */
1010    public void renamePermission(Permission permission, String name)
1011            throws DataBackendException, UnknownEntityException
1012    {
1013        permissionManager.renamePermission(permission, name);
1014    }
1015}