* @see org.rhq.enterprise.server.authz.RoleManagerLocal#updateRole(Subject, Role)
*/
@Override
@RequiredPermission(Permission.MANAGE_SECURITY)
public Role updateRole(Subject whoami, Role role) {
Role attachedRole = entityManager.find(Role.class, role.getId());
if (attachedRole == null) {
throw new IllegalStateException("Cannot update " + role + ", since no role exists with that id.");
}
// First update the simple fields and the permissions.
attachedRole.setName(role.getName());
attachedRole.setDescription(role.getDescription());
attachedRole.setPermissions(role.getPermissions());
processDependentPermissions(attachedRole);
// Then update the subjects, resourceGroups, ldapGroups, and/or bundle groups, but only if those fields are
// non-null on the passed-in Role.
Set<Subject> newSubjects = role.getSubjects();
if (newSubjects != null) {
Set<Subject> currentSubjects = attachedRole.getSubjects();
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<Subject> subjectsToRemove = new HashSet<Subject>(currentSubjects);
for (Subject subject : currentSubjects) {
// Never remove a system user.
if (subject.getFsystem()) {
subjectsToRemove.remove(subject);
}
}
for (Subject subject : subjectsToRemove) {
attachedRole.removeSubject(subject);
}
for (Subject subject : newSubjects) {
Subject attachedSubject = entityManager.find(Subject.class, subject.getId());
attachedRole.addSubject(attachedSubject);
}
}
Set<ResourceGroup> newResourceGroups = role.getResourceGroups();
if (newResourceGroups != null) {
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<ResourceGroup> currentResourceGroups = new HashSet<ResourceGroup>(attachedRole.getResourceGroups());
for (ResourceGroup resourceGroup : currentResourceGroups) {
attachedRole.removeResourceGroup(resourceGroup);
}
for (ResourceGroup resourceGroup : newResourceGroups) {
ResourceGroup attachedResourceGroup = entityManager.find(ResourceGroup.class, resourceGroup.getId());
attachedRole.addResourceGroup(attachedResourceGroup);
}
}
Set<LdapGroup> newLdapGroups = role.getLdapGroups();
if (newLdapGroups != null) {
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<LdapGroup> currentLdapGroups = new HashSet<LdapGroup>(attachedRole.getLdapGroups());
for (LdapGroup ldapGroup : currentLdapGroups) {
// Delete removed groups
if (!newLdapGroups.contains(ldapGroup)) {
attachedRole.removeLdapGroup(ldapGroup);
entityManager.remove(ldapGroup);
}
}
// Add new groups, but filter those that are still attached
for (LdapGroup ldapGroup : newLdapGroups) {
LdapGroup attachedLdapGroup = (ldapGroup.getId() != 0) ? entityManager.find(LdapGroup.class,
ldapGroup.getId()) : null;
if (attachedLdapGroup == null && !currentLdapGroups.contains(ldapGroup)) {
ldapGroup.setRole(attachedRole);
entityManager.persist(ldapGroup);
attachedLdapGroup = ldapGroup;
}
if (attachedLdapGroup!=null) {
attachedRole.addLdapGroup(attachedLdapGroup);
}
}
}
Set<BundleGroup> newBundleGroups = role.getBundleGroups();
if (newBundleGroups != null) {
// wrap in new HashSet to avoid ConcurrentModificationExceptions.
Set<BundleGroup> currentBundleGroups = attachedRole.getBundleGroups();
Set<BundleGroup> bundleGroupsToRemove = new HashSet<BundleGroup>(currentBundleGroups);
for (BundleGroup bg : newBundleGroups) {
bundleGroupsToRemove.remove(bg);
}
for (BundleGroup bg : bundleGroupsToRemove) {
attachedRole.removeBundleGroup(bg);
}
for (BundleGroup bg : newBundleGroups) {
BundleGroup attachedBundleGroup = entityManager.find(BundleGroup.class, bg.getId());
attachedRole.addBundleGroup(attachedBundleGroup);
}
}
// Fetch the lazy Sets on the Role to be returned.
attachedRole.getResourceGroups().size();
attachedRole.getSubjects().size();
attachedRole.getLdapGroups().size();
attachedRole.getBundleGroups().size();
return attachedRole;
}