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