
org.connid.bundles.ldap.commons.GroupHelper Maven / Gradle / Ivy
The newest version!
/**
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright 2011-2013 Tirasa. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at https://oss.oracle.com/licenses/CDDL
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at https://oss.oracle.com/licenses/CDDL.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
*/
package org.connid.bundles.ldap.commons;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static java.util.Collections.singletonList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.AttributeInUseException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapName;
import org.connid.bundles.ldap.LdapConnection;
import static org.connid.bundles.ldap.commons.LdapUtil.escapeAttrValue;
import org.connid.bundles.ldap.search.LdapSearches;
import org.connid.bundles.ldap.search.SearchResultsHandler;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
public class GroupHelper {
// This must be sorted in ascending order for Arrays.binarySearch to work properly!
private static final String[] OBJECT_CLASSES_WITH_MANDATORY_MEMB_ATTR = {"groupOfNames", "groupOfUniqueNames"};
private static final Log log = Log.getLog(GroupHelper.class);
private final LdapConnection conn;
public GroupHelper(LdapConnection conn) {
this.conn = conn;
}
/**
* Returns the attribute which POSIX group references its members. The members of a POSIX groups are held in the
* memberUid
attributes, and the values of this attributes are the
* uid
attributes of the group members. So this method returns
* "uid"
.
*/
public static String getPosixRefAttribute() {
return "uid";
}
private String getLdapGroupMemberAttribute() {
String memberAttr = conn.getConfiguration().getGroupMemberAttribute();
if (memberAttr == null) {
memberAttr = "uniqueMember"; // For groupOfUniqueNames.
}
return memberAttr;
}
public List getLdapGroups(String entryDN) {
log.ok("Retrieving LDAP groups for {0}", entryDN);
String filter = createAttributeFilter(getLdapGroupMemberAttribute(), singletonList(entryDN));
ToDNHandler handler = new ToDNHandler();
LdapSearches.findEntries(handler, conn, filter);
return handler.getResults();
}
public Set getLdapGroupMemberships(String entryDN) {
log.ok("Retrieving LDAP group memberships for {0}", entryDN);
String filter = createAttributeFilter(getLdapGroupMemberAttribute(), singletonList(entryDN));
ToGroupMembershipHandler handler = new ToGroupMembershipHandler();
handler.setMemberRef(entryDN);
LdapSearches.findEntries(handler, conn, filter);
return handler.getResults();
}
public void addLdapGroupMemberships(String entryDN, Collection groupDNs) {
log.ok("Adding {0} to LDAP groups {1}", entryDN, groupDNs);
String ldapGroupMemberAttribute = getLdapGroupMemberAttribute();
for (String groupDN : groupDNs) {
addMemberToGroup(ldapGroupMemberAttribute, entryDN, groupDN);
}
}
public void removeLdapGroupMemberships(String entryDN, Collection groupDNs) {
log.ok("Removing {0} from LDAP groups {1}", entryDN, groupDNs);
String ldapGroupMemberAttribute = getLdapGroupMemberAttribute();
for (String groupDN : groupDNs) {
removeMemberFromGroup(ldapGroupMemberAttribute, entryDN, groupDN);
}
}
public void modifyLdapGroupMemberships(Modification mod) {
log.ok("Modifying LDAP group memberships: removing {0}, adding {1}", mod.getRemoved(), mod.getAdded());
String ldapGroupMemberAttribute = getLdapGroupMemberAttribute();
for (GroupMembership membership : mod.getRemoved()) {
removeMemberFromGroup(ldapGroupMemberAttribute, membership.getMemberRef(), membership.getGroupDN());
}
for (GroupMembership membership : mod.getAdded()) {
addMemberToGroup(ldapGroupMemberAttribute, membership.getMemberRef(), membership.getGroupDN());
}
}
public List getPosixGroups(Collection posixRefAttrs) {
log.ok("Retrieving POSIX groups for {0}", posixRefAttrs);
String filter = createAttributeFilter("memberUid", posixRefAttrs);
ToDNHandler handler = new ToDNHandler();
LdapSearches.findEntries(handler, conn, filter);
return handler.getResults();
}
public Set getPosixGroupMemberships(Collection posixRefAttrs) {
log.ok("Retrieving POSIX group memberships for ", posixRefAttrs);
ToGroupMembershipHandler handler = new ToGroupMembershipHandler();
for (String posixRefAttr : posixRefAttrs) {
String filter = createAttributeFilter("memberUid", singletonList(posixRefAttr));
handler.setMemberRef(posixRefAttr);
LdapSearches.findEntries(handler, conn, filter);
}
return handler.getResults();
}
public void addPosixGroupMemberships(String posixRefAttr, Collection groupDNs) {
log.ok("Adding {0} to POSIX groups {1}", posixRefAttr, groupDNs);
for (String groupDN : groupDNs) {
addMemberToGroup("memberUid", posixRefAttr, groupDN);
}
}
public void removePosixGroupMemberships(Set memberships) {
log.ok("Removing POSIX group memberships {0}", memberships);
for (GroupMembership membership : memberships) {
removeMemberFromGroup("memberUid", membership.getMemberRef(), membership.getGroupDN());
}
}
public void modifyPosixGroupMemberships(Modification mod) {
log.ok("Modifying POSIX group memberships: removing {0}, adding {1}",
mod.getRemoved(), mod.getAdded());
for (GroupMembership membership : mod.getRemoved()) {
removeMemberFromGroup("memberUid", membership.getMemberRef(), membership.getGroupDN());
}
for (GroupMembership membership : mod.getAdded()) {
addMemberToGroup("memberUid", membership.getMemberRef(), membership.getGroupDN());
}
}
public void addMemberAttributeIfMissing(final BasicAttributes ldapAttrs) {
String[] groupObjectClasses = conn.getConfiguration().getGroupObjectClasses();
boolean found = false;
for (int i = 0; i < groupObjectClasses.length; i++) {
found = Arrays.binarySearch(OBJECT_CLASSES_WITH_MANDATORY_MEMB_ATTR, groupObjectClasses[i]) >= 0;
if (found) {
break;
}
}
if (!found) {
return;
}
javax.naming.directory.Attribute memberAttr = null;
final NamingEnumeration attrEnum = ldapAttrs.getAll();
while (attrEnum.hasMoreElements()) {
javax.naming.directory.Attribute attr = attrEnum.nextElement();
if (conn.getConfiguration().getGroupMemberAttribute().equals(attr.getID())) {
memberAttr = attr;
}
}
if (memberAttr == null) {
memberAttr = new BasicAttribute(conn.getConfiguration().getGroupMemberAttribute());
ldapAttrs.put(memberAttr);
}
if (memberAttr.size() == 0) {
memberAttr.add(conn.getConfiguration().getPrincipal());
}
}
private String createAttributeFilter(String memberAttr, Collection> memberValues) {
StringBuilder builder = new StringBuilder();
boolean multi = memberValues.size() > 1;
if (multi) {
builder.append("(|");
}
for (Object memberValue : memberValues) {
builder.append('(');
builder.append(memberAttr);
builder.append('=');
escapeAttrValue(memberValue, builder);
builder.append(')');
}
if (multi) {
builder.append(")");
}
return builder.toString();
}
private void addMemberToGroup(String memberAttr, String memberValue, String groupDN) {
BasicAttribute attr = new BasicAttribute(memberAttr, memberValue);
ModificationItem item = new ModificationItem(DirContext.ADD_ATTRIBUTE,
attr);
try {
conn.getInitialContext().modifyAttributes(groupDN, new ModificationItem[]{item});
} catch (AttributeInUseException e) {
throw new ConnectorException(conn.format("memberAlreadyInGroup", null, memberValue, groupDN), e);
} catch (NamingException e) {
throw new ConnectorException(e);
}
}
private void removeMemberFromGroup(String memberAttr, String memberValue, String groupDN) {
BasicAttribute attr = new BasicAttribute(memberAttr, memberValue);
ModificationItem item = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attr);
try {
conn.getInitialContext().modifyAttributes(groupDN, new ModificationItem[]{item});
} catch (NamingException e) {
throw new ConnectorException(e);
}
}
public static final class GroupMembership {
private final String memberRef;
private final String groupDN;
public GroupMembership(String memberRef, String groupDn) {
this.memberRef = memberRef;
this.groupDN = groupDn;
}
public String getMemberRef() {
return memberRef;
}
public String getGroupDN() {
return groupDN;
}
@Override
public int hashCode() {
return memberRef.hashCode() ^ groupDN.hashCode();
}
@Override
public boolean equals(Object o) {
if (o instanceof GroupMembership) {
GroupMembership that = (GroupMembership) o;
if (!memberRef.equals(that.memberRef)) {
return false;
}
if (!groupDN.equals(that.groupDN)) {
return false;
}
return true;
}
return false;
}
@Override
public String toString() {
return "GroupMembership[memberRef: " + memberRef + "; groupDN: " + groupDN + "]";
}
}
public static final class Modification {
private final Set removed = new LinkedHashSet();
private final Set added = new LinkedHashSet();
private Set effectiveAdded;
private Set effectiveRemoved;
public void add(T item) {
added.add(item);
invalidate();
}
public void addAll(Collection extends T> items) {
for (T item : items) {
added.add(item);
}
invalidate();
}
public void clearAdded() {
added.clear();
invalidate();
}
public Set getAdded() {
if (effectiveAdded == null) {
effectiveAdded = new LinkedHashSet(added);
effectiveAdded.removeAll(removed);
}
return effectiveAdded;
}
public void remove(T item) {
removed.add(item);
invalidate();
}
public void removeAll(Collection extends T> items) {
for (T item : items) {
removed.add(item);
}
invalidate();
}
public Set getRemoved() {
if (effectiveRemoved == null) {
effectiveRemoved = new LinkedHashSet(removed);
effectiveRemoved.removeAll(added);
}
return effectiveRemoved;
}
private void invalidate() {
effectiveAdded = null;
effectiveRemoved = null;
}
}
private static final class ToDNHandler implements SearchResultsHandler {
private final List results = new ArrayList();
@Override
public boolean handle(String baseDN, SearchResult searchResult)
throws NamingException {
results.add(LdapEntry.create(baseDN, searchResult).getDN().toString());
return true;
}
public List getResults() {
return results;
}
}
private static final class ToGroupMembershipHandler implements SearchResultsHandler {
private final Set results = new HashSet();
private String memberRef;
public void setMemberRef(String memberRef) {
this.memberRef = memberRef;
}
@Override
public boolean handle(String baseDN, SearchResult searchResult)
throws NamingException {
LdapName groupDN = LdapEntry.create(baseDN, searchResult).getDN();
results.add(new GroupMembership(memberRef, groupDN.toString()));
return true;
}
public Set getResults() {
return results;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy