001package org.apache.fulcrum.security.model.dynamic;
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 */
021import java.util.HashMap;
022import java.util.HashSet;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.fulcrum.security.acl.AccessControlList;
027import org.apache.fulcrum.security.entity.Group;
028import org.apache.fulcrum.security.entity.Role;
029import org.apache.fulcrum.security.entity.User;
030import org.apache.fulcrum.security.model.ACLFactory;
031import org.apache.fulcrum.security.model.dynamic.entity.DynamicGroup;
032import org.apache.fulcrum.security.model.dynamic.entity.DynamicRole;
033import org.apache.fulcrum.security.model.dynamic.entity.DynamicUser;
034import org.apache.fulcrum.security.spi.AbstractManager;
035import org.apache.fulcrum.security.util.PermissionSet;
036import org.apache.fulcrum.security.util.RoleSet;
037import org.apache.fulcrum.security.util.UnknownEntityException;
038
039/**
040 *
041 * This factory creates instance of the DynamicAccessControlList
042 *
043 * @author <a href="mailto:epugh@upstate.com">Eric Pugh </a>
044 * @author <a href="mailto:ben@gidley.co.uk">Ben Gidley </a>
045 * @version $Id$
046 */
047public class DynamicACLFactory extends AbstractManager implements ACLFactory
048{
049    /**
050     * @see org.apache.fulcrum.security.model.ACLFactory#getAccessControlList(org.apache.fulcrum.security.entity.User)
051     */
052    public <T extends AccessControlList> T getAccessControlList(User user)
053    {
054        Map<Group, RoleSet> roleSets = new HashMap<Group, RoleSet>();
055        Map<Role, PermissionSet> permissionSets = new HashMap<Role, PermissionSet>();
056
057        Set<DynamicUser> users = new HashSet<DynamicUser>();
058
059        // add the root user
060        users.add((DynamicUser) user);
061        addDelegators((DynamicUser) user, users);
062
063        for (DynamicUser aUser : users)
064        {
065            addRolesAndPermissions(aUser, roleSets, permissionSets);
066        }
067
068        try
069        {
070            @SuppressWarnings("unchecked")
071                        T aclInstance = (T) getAclInstance(roleSets, permissionSets);
072                        return aclInstance;
073        }
074        catch (UnknownEntityException uue)
075        {
076            throw new RuntimeException(uue.getMessage(), uue);
077        }
078    }
079
080    /**
081     * Construct a new ACL object.
082     *
083     * This constructs a new ACL object from the configured class and
084     * initializes it with the supplied roles and permissions.
085     *
086     * @param roles
087     *            The roles that this ACL should contain
088     * @param permissions
089     *            The permissions for this ACL
090     *
091     * @return an object implementing ACL interface.
092     * @throws UnknownEntityException
093     *             if the object could not be instantiated.
094     */
095    private DynamicAccessControlList getAclInstance(Map<? extends Group, ? extends RoleSet> roles,
096            Map<? extends Role, ? extends PermissionSet> permissions) throws UnknownEntityException
097    {
098        DynamicAccessControlList accessControlList;
099        try
100        {
101            accessControlList = new DynamicAccessControlListImpl(roles, permissions);
102        }
103        catch (Exception e)
104        {
105            throw new UnknownEntityException("Failed to instantiate an ACL implementation object", e);
106        }
107        return accessControlList;
108    }
109
110    /**
111     * Add delegators to the user list
112     *
113     * @param user
114     *            the user to add to
115     * @param users
116     *            the set of delegators
117     */
118    public <T extends DynamicUser> void addDelegators(DynamicUser user, Set<T> users)
119    {
120        for (User u : user.getDelegators())
121        {
122            @SuppressWarnings("unchecked")
123            T delegatorUser = (T) u;
124
125            if (users.add(delegatorUser))
126            {
127                // Only come here if user NOT in users
128                addDelegators(delegatorUser, users);
129            }
130        }
131    }
132
133    /**
134     * Adds the passed users roles and permissions to the sets As maps overwrite
135     * duplicates we just put it in an let it overwrite it is probably quicker
136     * than checking for duplicates
137     *
138     * @param user
139     * @param roleSets
140     * @param permissionSets
141     */
142    private void addRolesAndPermissions(User user, Map<Group, RoleSet> roleSets, Map<Role, PermissionSet> permissionSets)
143    {
144        for (Group group : ((DynamicUser) user).getGroups())
145        {
146            RoleSet roleSet = ((DynamicGroup) group).getRoles();
147            roleSets.put(group, roleSet);
148            for (Role r : roleSet)
149            {
150                DynamicRole role = (DynamicRole) r;
151                permissionSets.put(role, role.getPermissions());
152            }
153        }
154    }
155}