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