Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.picketlink.idm.ldap.internal.LDAPIdentityStore Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.picketlink.idm.ldap.internal;
import org.picketlink.common.constants.LDAPConstants;
import org.picketlink.common.properties.Property;
import org.picketlink.common.properties.query.NamedPropertyCriteria;
import org.picketlink.common.properties.query.PropertyQueries;
import org.picketlink.common.properties.query.TypedPropertyCriteria;
import org.picketlink.idm.IdentityManagementException;
import org.picketlink.idm.config.IdentityStoreConfiguration;
import org.picketlink.idm.config.LDAPIdentityStoreConfiguration;
import org.picketlink.idm.config.LDAPMappingConfiguration;
import org.picketlink.idm.credential.handler.annotations.CredentialHandlers;
import org.picketlink.idm.credential.storage.CredentialStorage;
import org.picketlink.idm.internal.AbstractIdentityStore;
import org.picketlink.idm.model.Account;
import org.picketlink.idm.model.AttributedType;
import org.picketlink.idm.model.IdentityType;
import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.query.AttributeParameter;
import org.picketlink.idm.query.Condition;
import org.picketlink.idm.query.IdentityQuery;
import org.picketlink.idm.query.QueryParameter;
import org.picketlink.idm.query.RelationshipQuery;
import org.picketlink.idm.query.RelationshipQueryParameter;
import org.picketlink.idm.query.internal.BetweenCondition;
import org.picketlink.idm.query.internal.EqualCondition;
import org.picketlink.idm.query.internal.GreaterThanCondition;
import org.picketlink.idm.query.internal.InCondition;
import org.picketlink.idm.query.internal.LessThanCondition;
import org.picketlink.idm.query.internal.LikeCondition;
import org.picketlink.idm.spi.CredentialStore;
import org.picketlink.idm.spi.IdentityContext;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.SearchResult;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import static java.util.Map.Entry;
import static org.picketlink.common.constants.LDAPConstants.COMMA;
import static org.picketlink.common.constants.LDAPConstants.CREATE_TIMESTAMP;
import static org.picketlink.common.constants.LDAPConstants.EQUAL;
import static org.picketlink.common.constants.LDAPConstants.GROUP_OF_ENTRIES;
import static org.picketlink.common.constants.LDAPConstants.GROUP_OF_NAMES;
import static org.picketlink.common.constants.LDAPConstants.MEMBER;
import static org.picketlink.common.constants.LDAPConstants.OBJECT_CLASS;
import static org.picketlink.common.properties.query.TypedPropertyCriteria.MatchOption;
import static org.picketlink.common.reflection.Reflections.newInstance;
import static org.picketlink.common.util.StringUtil.isNullOrEmpty;
import static org.picketlink.idm.IDMInternalLog.LDAP_STORE_LOGGER;
import static org.picketlink.idm.IDMInternalMessages.MESSAGES;
import static org.picketlink.idm.ldap.internal.LDAPUtil.formatDate;
import static org.picketlink.idm.ldap.internal.LDAPUtil.parseDate;
/**
* An IdentityStore implementation backed by an LDAP directory
*
* @author Shane Bryzak
* @author Anil Saldhana
* @author Pedro Silva
*/
@CredentialHandlers({LDAPPlainTextPasswordCredentialHandler.class})
public class LDAPIdentityStore extends AbstractIdentityStore
implements CredentialStore {
public static final String EMPTY_ATTRIBUTE_VALUE = " ";
public static final String ENTRY_DN_ATTRIBUTE_NAME = "org.picketlink.idm.ldap.entry.dn";
private LDAPOperationManager operationManager;
@Override
public void setup(LDAPIdentityStoreConfiguration config) {
super.setup(config);
if (config.isActiveDirectory()) {
LDAP_STORE_LOGGER.ldapActiveDirectoryConfiguration();
}
try {
this.operationManager = new LDAPOperationManager(getConfig());
} catch (NamingException e) {
throw MESSAGES.storeLdapCouldNotCreateContext(e);
}
}
@Override
public void addAttributedType(IdentityContext context, AttributedType attributedType) {
if (Relationship.class.isInstance(attributedType)) {
addRelationship((Relationship) attributedType);
} else {
this.operationManager.createSubContext(getBindingDN(attributedType, true), extractAttributes(attributedType, true));
addToParentAsMember(attributedType);
attributedType.setId(getEntryIdentifier(attributedType));
}
}
@Override
public void updateAttributedType(IdentityContext context, AttributedType attributedType) {
// this store does not support updation of relationship types
if (Relationship.class.isInstance(attributedType)) {
LDAP_STORE_LOGGER.ldapRelationshipUpdateNotSupported(attributedType);
} else {
BasicAttributes updatedAttributes = extractAttributes(attributedType, false);
NamingEnumeration attributes = updatedAttributes.getAll();
this.operationManager.modifyAttributes(getBindingDN(attributedType, true), attributes);
}
}
@Override
public void removeAttributedType(IdentityContext context, AttributedType attributedType) {
if (Relationship.class.isInstance(attributedType)) {
removeRelationship((Relationship) attributedType);
} else {
LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
this.operationManager.removeEntryById(getBaseDN(attributedType), attributedType.getId(), mappingConfig);
}
}
@Override
protected void removeFromRelationships(final IdentityContext context, final IdentityType identityType) {
String bindingDN = getBindingDN(identityType, true);
for (LDAPMappingConfiguration relationshipConfig : getConfig().getRelationshipConfigs()) {
for (String attributeName : relationshipConfig.getMappedProperties().values()) {
StringBuilder filter = new StringBuilder();
filter.append("(&(").append(attributeName).append(EQUAL).append("").append(bindingDN).append("))");
try {
List search = this.operationManager.search(getMappingConfig(relationshipConfig.getRelatedAttributedType()).getBaseDN(), filter.toString(), getMappingConfig(relationshipConfig.getRelatedAttributedType()));
for (SearchResult result : search) {
Attributes attributes = result.getAttributes();
Attribute relationshipAttribute = attributes.get(attributeName);
if (relationshipAttribute != null && relationshipAttribute.contains(bindingDN)) {
relationshipAttribute.remove(bindingDN);
if (relationshipAttribute.size() == 0) {
relationshipAttribute.add(EMPTY_ATTRIBUTE_VALUE);
}
this.operationManager.modifyAttribute(result.getNameInNamespace(), relationshipAttribute);
}
}
} catch (NamingException e) {
throw new IdentityManagementException("Could not remove " + identityType + " from relationship " + relationshipConfig.getMappedClass(), e);
}
}
}
}
@Override
public List fetchQueryResults(IdentityContext context, IdentityQuery identityQuery) {
List results = new ArrayList();
try {
if (identityQuery.getSorting() != null && !identityQuery.getSorting().isEmpty()) {
throw new IdentityManagementException("LDAP Identity Store does not support sorted queries.");
}
for (Condition condition : identityQuery.getConditions()) {
if (identityQuery.getConditions().size() == 1 && IdentityType.PARTITION.equals(condition.getParameter())) {
// we don't query the ldap tree using only the partition as a parameter due to the cost of doing so.
return results;
}
if (IdentityType.ID.equals(condition.getParameter())) {
if (EqualCondition.class.isInstance(condition)) {
EqualCondition equalCondition = (EqualCondition) condition;
SearchResult search = this.operationManager
.lookupById(getConfig().getBaseDN(), equalCondition.getValue().toString(), null);
if (search != null) {
results.add((V) populateAttributedType(search, null));
}
}
return results;
}
}
if (!IdentityType.class.equals(identityQuery.getIdentityType())) {
// the ldap store does not support queries based on root types. Except if based on the identifier.
LDAPMappingConfiguration ldapEntryConfig = getMappingConfig(identityQuery.getIdentityType());
StringBuilder filter = createIdentityTypeSearchFilter(identityQuery, ldapEntryConfig);
List search;
if (getConfig().isPagination() && identityQuery.getLimit() > 0) {
search = this.operationManager.searchPaginated(getBaseDN(ldapEntryConfig), filter.toString(), ldapEntryConfig, identityQuery);
} else {
search = this.operationManager.search(getBaseDN(ldapEntryConfig), filter.toString(), ldapEntryConfig);
}
for (SearchResult result : search) {
results.add((V) populateAttributedType(result, null));
}
}
} catch (Exception e) {
throw MESSAGES.queryIdentityTypeFailed(identityQuery, e);
}
return results;
}
@Override
public List fetchQueryResults(IdentityContext context, RelationshipQuery query) {
List results = new ArrayList();
if (Relationship.class.equals(query.getRelationshipClass())) {
for (LDAPMappingConfiguration configuration : getConfig().getRelationshipConfigs()) {
results.addAll(fetchRelationships(query, configuration));
}
} else {
results.addAll(fetchRelationships(query, getMappingConfig(query.getRelationshipClass())));
}
return results;
}
private String getRelationshipMappedProperty(Class extends IdentityType> identityType, LDAPMappingConfiguration mappingConfig) {
final Property property = PropertyQueries.createQuery(mappingConfig.getMappedClass()).addCriteria(new TypedPropertyCriteria(identityType, MatchOption.ALL)).getFirstResult();
if (property == null) {
return null;
}
return mappingConfig.getMappedProperties().get(property.getName());
}
private List fetchRelationships(final RelationshipQuery query, final LDAPMappingConfiguration mappingConfig) {
List results = new ArrayList();
Class relationshipClass = (Class) mappingConfig.getMappedClass();
Map parameters = query.getParameters();
LDAPMappingConfiguration relatedTypeConfig = getMappingConfig(mappingConfig.getRelatedAttributedType());
StringBuilder filter = new StringBuilder();
filter.append("(&").append(getObjectClassesFilter(relatedTypeConfig));
List entriesToFilter = new ArrayList();
for (QueryParameter queryParameter : parameters.keySet()) {
Object[] values = parameters.get(queryParameter);
RelationshipQueryParameter relationshipQueryParameter = null;
String attributeName = null;
if (RelationshipQueryParameter.class.isInstance(queryParameter)) {
relationshipQueryParameter = (RelationshipQueryParameter) queryParameter;
attributeName = mappingConfig.getMappedProperties().get(relationshipQueryParameter.getName());
} else if (Relationship.IDENTITY.equals(queryParameter)) {
IdentityType identityType = (IdentityType) values[0];
if (!mappingConfig.getRelatedAttributedType().isInstance(identityType)) {
attributeName = getRelationshipMappedProperty(identityType.getClass(), mappingConfig);
}
} else {
continue;
}
for (Object value : values) {
AttributedType attributedType = (AttributedType) value;
if (!getConfig().supportsType(attributedType.getClass(), IdentityStoreConfiguration.IdentityOperation.read)) {
return results;
}
String bindingDN = null;
SearchResult result = this.operationManager.lookupById(getBaseDN(attributedType), attributedType.getId(), getMappingConfig(attributedType.getClass()));
if (result != null) {
bindingDN = result.getNameInNamespace();
if (!attributedType.getClass().equals(relatedTypeConfig.getMappedClass())) {
entriesToFilter.add(bindingDN);
}
}
boolean filterByOwner = attributedType.getClass().equals(relatedTypeConfig.getMappedClass());
if (attributeName != null) {
Property property = PropertyQueries
.createQuery(relationshipClass)
.addCriteria(new NamedPropertyCriteria(attributeName))
.getFirstResult();
if (property != null) {
filterByOwner = property.getJavaClass().equals(relatedTypeConfig.getMappedClass());
}
}
if (filterByOwner) {
filter.append(this.operationManager.getFilterById(getBaseDN(attributedType), attributedType.getId()));
} else {
filter.append("(").append(attributeName).append(EQUAL).append(bindingDN).append(")");
}
}
}
filter.append(")");
try {
if (filter.length() > 0) {
String baseDN = getBaseDN(relatedTypeConfig);
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Search relationships for type [%s] using filter [%] and baseDN [%s]", relationshipClass, filter.toString(), baseDN);
}
List search = this.operationManager.search(baseDN, filter.toString(), relatedTypeConfig);
for (SearchResult entry : search) {
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Found entry [%s] for relationship ", entry.getNameInNamespace(), relationshipClass);
}
Attributes ownerAttributes = entry.getAttributes();
AttributedType ownerType = populateAttributedType(entry, null);
for (Entry memberAttribute : mappingConfig.getMappedProperties().entrySet()) {
String attributeName = memberAttribute.getValue();
Attribute attribute = ownerAttributes.get(attributeName);
if (attribute != null) {
NamingEnumeration> attributeValues = attribute.getAll();
while (attributeValues.hasMore()) {
String attributeValue = attributeValues.next().toString();
if (!entriesToFilter.isEmpty() && !entriesToFilter.contains(attributeValue)) {
continue;
}
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER
.tracef("Processing relationship [%s] from attribute [%s] with attributeValue [%s]", relationshipClass, attributeName, attributeValue);
}
if (!isNullOrEmpty(attributeValue.trim())) {
Property associatedProperty = PropertyQueries
.createQuery(relationshipClass)
.addCriteria(new NamedPropertyCriteria(memberAttribute.getKey()))
.getSingleResult();
String memberBaseDN = attributeValue.substring(attributeValue.indexOf(",") + 1);
String dn = attributeValue.substring(0, attributeValue.indexOf(","));
List result = this.operationManager.search(memberBaseDN, dn, null);
if (result.isEmpty()) {
throw new IdentityManagementException("Associated entry does not exists [" + attributeValue + "].");
}
Property property = PropertyQueries
.createQuery(relationshipClass)
.addCriteria(new TypedPropertyCriteria(mappingConfig.getRelatedAttributedType()))
.getSingleResult();
if (property.getJavaClass().isAssignableFrom(ownerType.getClass())) {
V relationship = newInstance(relationshipClass);
property.setValue(relationship, ownerType);
SearchResult member = result.get(0);
AttributedType relType = populateAttributedType(member, null);
if (associatedProperty.getJavaClass().isAssignableFrom(relType.getClass())) {
associatedProperty.setValue(relationship, relType);
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER
.tracef("Relationship [%s] created from attribute [%s] with attributeValue [%s]", relationshipClass, attributeName, attributeValue);
}
results.add(relationship);
}
}
}
}
}
}
}
}
} catch (Exception e) {
throw MESSAGES.queryRelationshipFailed(query, e);
}
return results;
}
@Override
public void storeCredential(IdentityContext context, Account account, CredentialStorage storage) {
//no-op. operation no supported by this store
}
@Override
public T retrieveCurrentCredential(IdentityContext context, Account
account, Class storageClass) {
//no-op. operation no supported by this store
return null;
}
@Override
public List retrieveCredentials(IdentityContext context, Account
account, Class storageClass) {
//no-op. operation no supported by this store
return null;
}
@Override
public void removeCredential(IdentityContext context, Account account, Class extends CredentialStorage> storageClass) {
// does not makes sense remove credentials in LDAP. You probably want to disable an account ?
throw MESSAGES.notImplemented();
}
@Override
protected void removeCredentials(final IdentityContext context, final Account account) {
// not supported
}
private String getBaseDN(final LDAPMappingConfiguration ldapEntryConfig) {
String baseDN = getConfig().getBaseDN();
if (ldapEntryConfig.getBaseDN() != null) {
baseDN = ldapEntryConfig.getBaseDN();
}
return baseDN;
}
protected StringBuilder createIdentityTypeSearchFilter(final IdentityQuery identityQuery, final LDAPMappingConfiguration ldapEntryConfig) {
StringBuilder filter = new StringBuilder();
for (Condition condition : identityQuery.getConditions()) {
QueryParameter queryParameter = condition.getParameter();
if (!IdentityType.ID.equals(queryParameter)) {
if (AttributeParameter.class.isInstance(queryParameter)) {
AttributeParameter attributeParameter = (AttributeParameter) queryParameter;
String attributeName = ldapEntryConfig.getMappedProperties().get(attributeParameter.getName());
if (attributeName != null) {
if (EqualCondition.class.isInstance(condition)) {
EqualCondition equalCondition = (EqualCondition) condition;
Object parameterValue = equalCondition.getValue();
if (Date.class.isInstance(parameterValue)) {
parameterValue = formatDate((Date) parameterValue);
}
filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(parameterValue).append(")");
} else if (LikeCondition.class.isInstance(condition)) {
LikeCondition likeCondition = (LikeCondition) condition;
String parameterValue = (String) likeCondition.getValue();
} else if (GreaterThanCondition.class.isInstance(condition)) {
GreaterThanCondition greaterThanCondition = (GreaterThanCondition) condition;
Comparable parameterValue = (Comparable) greaterThanCondition.getValue();
if (Date.class.isInstance(parameterValue)) {
parameterValue = formatDate((Date) parameterValue);
}
if (greaterThanCondition.isOrEqual()) {
filter.append("(").append(attributeName).append(">=").append(parameterValue).append(")");
} else {
filter.append("(").append(attributeName).append(">").append(parameterValue).append(")");
}
} else if (LessThanCondition.class.isInstance(condition)) {
LessThanCondition lessThanCondition = (LessThanCondition) condition;
Comparable parameterValue = (Comparable) lessThanCondition.getValue();
if (Date.class.isInstance(parameterValue)) {
parameterValue = formatDate((Date) parameterValue);
}
if (lessThanCondition.isOrEqual()) {
filter.append("(").append(attributeName).append("<=").append(parameterValue).append(")");
} else {
filter.append("(").append(attributeName).append("<").append(parameterValue).append(")");
}
} else if (BetweenCondition.class.isInstance(condition)) {
BetweenCondition betweenCondition = (BetweenCondition) condition;
Comparable x = betweenCondition.getX();
Comparable y = betweenCondition.getY();
if (Date.class.isInstance(x)) {
x = formatDate((Date) x);
}
if (Date.class.isInstance(y)) {
y = formatDate((Date) y);
}
filter.append("(").append(x).append("<=").append(attributeName).append("<=").append(y).append(")");
} else if (InCondition.class.isInstance(condition)) {
InCondition inCondition = (InCondition) condition;
Object[] valuesToCompare = inCondition.getValue();
filter.append("(&(");
for (int i = 0; i< valuesToCompare.length; i++) {
Object value = valuesToCompare[i];
filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(value).append(")");
}
filter.append("))");
} else {
throw new IdentityManagementException("Unsupported query condition [" + condition + "].");
}
}
}
}
}
filter.insert(0, "(&(");
if (ldapEntryConfig != null) {
filter.append(getObjectClassesFilter(ldapEntryConfig));
} else {
filter.append("(").append(OBJECT_CLASS).append(EQUAL).append("*").append(")");
}
filter.append("))");
return filter;
}
private StringBuilder getObjectClassesFilter(final LDAPMappingConfiguration ldapEntryConfig) {
StringBuilder builder = new StringBuilder();
for (String objectClass : ldapEntryConfig.getObjectClasses()) {
builder.append("(objectClass=").append(objectClass).append(")");
}
return builder;
}
private void addRelationship(Relationship relationship) {
LDAPMappingConfiguration mappingConfig = getMappingConfig(relationship.getClass());
AttributedType ownerType = getRelationshipOwner(relationship);
Attributes entryAttributes = this.operationManager.getAttributes(ownerType.getId(), getBaseDN(ownerType), mappingConfig);
for (String relationshipTypeProperty : mappingConfig.getMappedProperties().keySet()) {
Property relationshipProperty = PropertyQueries
.createQuery(relationship.getClass())
.addCriteria(new NamedPropertyCriteria(relationshipTypeProperty))
.getSingleResult();
Attribute attribute = entryAttributes.get(mappingConfig.getMappedProperties().get(relationshipTypeProperty));
if (attribute != null) {
List membersToRemove = new ArrayList();
String memberDN = getBindingDN(relationshipProperty.getValue(relationship), true);
try {
NamingEnumeration attributeValues = attribute.getAll();
while (attributeValues.hasMore()) {
Object value = attributeValues.next();
if (value.toString().trim().equals(EMPTY_ATTRIBUTE_VALUE.trim())) {
membersToRemove.add(EMPTY_ATTRIBUTE_VALUE);
membersToRemove.add(EMPTY_ATTRIBUTE_VALUE.trim());
}
if (value.toString().toLowerCase().equals(memberDN.toLowerCase())) {
membersToRemove.add(value.toString());
}
}
for (String memberToRemove : membersToRemove) {
attribute.remove(memberToRemove);
}
} catch (NamingException ne) {
throw new IdentityManagementException("Could not iterate over members for relationship [" + relationship + "].", ne);
}
attribute.add(memberDN);
this.operationManager.modifyAttribute(getBindingDN(ownerType, true), attribute);
}
}
}
private AttributedType getRelationshipOwner(final Relationship relationship) {
Class extends AttributedType> ownertType = getMappingConfig(relationship.getClass()).getRelatedAttributedType();
Property property = PropertyQueries
.createQuery(relationship.getClass())
.addCriteria(new TypedPropertyCriteria(ownertType))
.getSingleResult();
return property.getValue(relationship);
}
private void removeRelationship(final Relationship relationship) {
LDAPMappingConfiguration mappingConfig = getMappingConfig(relationship.getClass());
AttributedType ownerType = getRelationshipOwner(relationship);
Attributes ownerAttributes = this.operationManager.getAttributes(ownerType.getId(), getBaseDN(ownerType), mappingConfig);
for (String typeProperty : mappingConfig.getMappedProperties().keySet()) {
Property relProperty = PropertyQueries
.createQuery(relationship.getClass())
.addCriteria(new NamedPropertyCriteria(typeProperty))
.getSingleResult();
Attribute mappedAttribute = ownerAttributes.get(mappingConfig.getMappedProperties().get(typeProperty));
if (mappedAttribute != null) {
String childDN = getBindingDN(relProperty.getValue(relationship), true);
NamingEnumeration> members = null;
try {
members = mappedAttribute.getAll();
while (members.hasMoreElements()) {
Object next = members.next();
if (next.toString().equalsIgnoreCase(childDN)) {
mappedAttribute.remove(next);
}
}
} catch (Exception e) {
throw new IdentityManagementException("Could not remove relationship [" + relationship + "].", e);
} finally {
if (members != null) {
try {
members.close();
} catch (NamingException ignore) {
}
}
}
}
if (mappedAttribute != null) {
if (mappedAttribute.size() == 0) {
mappedAttribute.add(EMPTY_ATTRIBUTE_VALUE);
}
this.operationManager.modifyAttribute(getBindingDN(ownerType, true), mappedAttribute);
}
}
}
private AttributedType populateAttributedType(SearchResult searchResult, AttributedType attributedType) {
return populateAttributedType(searchResult, attributedType, 0);
}
private AttributedType populateAttributedType(SearchResult searchResult, AttributedType attributedType, int hierarchyDepthCount) {
try {
String entryDN = searchResult.getNameInNamespace();
String entryBaseDN = entryDN.substring(entryDN.indexOf(COMMA) + 1);
Attributes attributes = searchResult.getAttributes();
if (attributedType == null) {
attributedType = newInstance(getConfig().getSupportedTypeByBaseDN(entryBaseDN, getEntryObjectClasses(attributes)));
}
attributedType.setAttribute(new org.picketlink.idm.model.Attribute(ENTRY_DN_ATTRIBUTE_NAME, entryDN));
LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
if (hierarchyDepthCount > mappingConfig.getHierarchySearchDepth()) {
return null;
}
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Populating attributed type [%s] from DN [%s]", attributedType, entryDN);
}
NamingEnumeration extends Attribute> ldapAttributes = attributes.getAll();
while (ldapAttributes.hasMore()) {
Attribute ldapAttribute = ldapAttributes.next();
Object attributeValue;
try {
attributeValue = ldapAttribute.get();
} catch (NoSuchElementException nsee) {
continue;
}
String ldapAttributeName = ldapAttribute.getID();
if (ldapAttributeName.toLowerCase().equals(getConfig().getUniqueIdentifierAttributeName().toLowerCase())) {
attributedType.setId(this.operationManager.decodeEntryUUID(attributeValue));
} else {
String attributeName = findAttributeName(mappingConfig.getMappedProperties(), ldapAttributeName);
if (attributeName != null) {
// Find if it's java property or attribute
Property property = PropertyQueries
.createQuery(attributedType.getClass())
.addCriteria(new NamedPropertyCriteria(attributeName)).getFirstResult();
if (property != null) {
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Populating property [%s] from ldap attribute [%s] with value [%s] from DN [%s].", property.getName(), ldapAttributeName, attributeValue, entryBaseDN);
}
if (property.getJavaClass().equals(Date.class)) {
property.setValue(attributedType, parseDate(attributeValue.toString()));
} else {
property.setValue(attributedType, attributeValue);
}
} else {
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Populating attribute [%s] from ldap attribute [%s] with value [%s] from DN [%s].", attributeName, ldapAttributeName, attributeValue, entryBaseDN);
}
attributedType.setAttribute(new org.picketlink.idm.model.Attribute(attributeName, (Serializable) attributeValue));
}
}
}
}
if (IdentityType.class.isInstance(attributedType)) {
IdentityType identityType = (IdentityType) attributedType;
String createdTimestamp = attributes.get(CREATE_TIMESTAMP).get().toString();
identityType.setCreatedDate(parseDate(createdTimestamp));
}
LDAPMappingConfiguration entryConfig = getMappingConfig(attributedType.getClass());
if (mappingConfig.getParentMembershipAttributeName() != null) {
StringBuilder filter = new StringBuilder("(&");
filter
.append("(")
.append(getObjectClassesFilter(entryConfig))
.append(")")
.append("(")
.append(mappingConfig.getParentMembershipAttributeName())
.append(EQUAL).append("")
.append(getBindingDN(attributedType, false))
.append(COMMA)
.append(entryBaseDN)
.append(")");
filter.append(")");
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Searching parent entry for DN [%s] using filter [%s].", entryDN, filter.toString());
}
List search = this.operationManager.search(getConfig().getBaseDN(), filter.toString(), entryConfig);
if (!search.isEmpty()) {
SearchResult next = search.get(0);
Property parentProperty = PropertyQueries
.createQuery(attributedType.getClass())
.addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult();
if (parentProperty != null) {
String parentDN = next.getNameInNamespace();
String parentBaseDN = parentDN.substring(parentDN.indexOf(",") + 1);
Class extends AttributedType> baseDNType = getConfig().getSupportedTypeByBaseDN(parentBaseDN, getEntryObjectClasses(attributes));
if (parentProperty.getJavaClass().isAssignableFrom(baseDNType)) {
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("Found parent [%s] for entry for DN [%s].", parentDN, entryDN);
}
int hierarchyDepthCount1 = ++hierarchyDepthCount;
parentProperty.setValue(attributedType, populateAttributedType(next, null, hierarchyDepthCount1));
}
}
} else {
if (LDAP_STORE_LOGGER.isTraceEnabled()) {
LDAP_STORE_LOGGER.tracef("No parent entry found for DN [%s] using filter [%s].", entryDN, filter.toString());
}
}
}
} catch (Exception e) {
throw new IdentityManagementException("Could not populate attribute type " + attributedType + ".", e);
}
return attributedType;
}
private String findAttributeName(Map attrMapping, String ldapAttributeName) {
for (Map.Entry currentAttr : attrMapping.entrySet()) {
if (currentAttr.getValue().equalsIgnoreCase(ldapAttributeName)) {
return currentAttr.getKey();
}
}
return null;
}
private List getEntryObjectClasses(final Attributes attributes) throws NamingException {
Attribute objectClassesAttribute = attributes.get(OBJECT_CLASS);
List objectClasses = new ArrayList();
if (objectClassesAttribute == null) {
return objectClasses;
}
NamingEnumeration> all = objectClassesAttribute.getAll();
while (all.hasMore()) {
objectClasses.add(all.next().toString());
}
return objectClasses;
}
protected BasicAttributes extractAttributes(AttributedType attributedType, boolean isCreate) {
BasicAttributes entryAttributes = new BasicAttributes();
LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
Map mappedProperties = mappingConfig.getMappedProperties();
for (String propertyName : mappedProperties.keySet()) {
if (!mappingConfig.getReadOnlyAttributes().contains(propertyName) && (isCreate || !mappingConfig.getBindingProperty().getName().equals(propertyName))) {
Property property = PropertyQueries
.createQuery(attributedType.getClass())
.addCriteria(new NamedPropertyCriteria(propertyName)).getFirstResult();
Object propertyValue = null;
if (property != null) {
// Mapped Java property on the object
propertyValue = property.getValue(attributedType);
} else {
// Not mapped property. So fallback to attribute
org.picketlink.idm.model.Attribute> attribute = attributedType.getAttribute(propertyName);
if (attribute != null) {
propertyValue = attribute.getValue();
}
}
if (AttributedType.class.isInstance(propertyValue)) {
AttributedType referencedType = (AttributedType) propertyValue;
propertyValue = getBindingDN(referencedType, true);
} else {
if (propertyValue == null || isNullOrEmpty(propertyValue.toString())) {
propertyValue = EMPTY_ATTRIBUTE_VALUE;
}
}
entryAttributes.put(mappedProperties.get(propertyName), propertyValue);
}
}
// Don't extract object classes for update
if (isCreate) {
LDAPMappingConfiguration ldapEntryConfig = getMappingConfig(attributedType.getClass());
BasicAttribute objectClassAttribute = new BasicAttribute(OBJECT_CLASS);
for (String objectClassValue : ldapEntryConfig.getObjectClasses()) {
objectClassAttribute.add(objectClassValue);
if (objectClassValue.equals(GROUP_OF_NAMES)
|| objectClassValue.equals(GROUP_OF_ENTRIES)
|| objectClassValue.equals(LDAPConstants.GROUP_OF_UNIQUE_NAMES)) {
entryAttributes.put(MEMBER, EMPTY_ATTRIBUTE_VALUE);
}
}
entryAttributes.put(objectClassAttribute);
}
return entryAttributes;
}
private LDAPMappingConfiguration getMappingConfig(Class extends AttributedType> attributedType) {
LDAPMappingConfiguration mappingConfig = getConfig().getMappingConfig(attributedType);
if (mappingConfig == null) {
throw new IdentityManagementException("Not mapped type [" + attributedType + "].");
}
return mappingConfig;
}
public LDAPOperationManager getOperationManager() {
return this.operationManager;
}
public String getBindingDN(AttributedType attributedType, boolean appendBaseDN) {
LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
Property idProperty = mappingConfig.getIdProperty();
String baseDN;
if (mappingConfig.getBaseDN() == null || !appendBaseDN) {
baseDN = "";
} else {
baseDN = COMMA + getBaseDN(attributedType);
}
Property bindingProperty = mappingConfig.getBindingProperty();
String bindingAttribute;
String dn;
if (bindingProperty == null) {
bindingAttribute = mappingConfig.getMappedProperties().get(idProperty.getName());
dn = idProperty.getValue(attributedType);
} else {
bindingAttribute = mappingConfig.getMappedProperties().get(bindingProperty.getName());
dn = mappingConfig.getBindingProperty().getValue(attributedType);
}
return bindingAttribute + EQUAL + dn + baseDN;
}
private String getBaseDN(AttributedType attributedType) {
LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
String baseDN = mappingConfig.getBaseDN();
String parentDN = mappingConfig.getParentMapping().get(mappingConfig.getIdProperty().getValue(attributedType));
if (parentDN != null) {
baseDN = parentDN;
} else {
Property parentProperty = PropertyQueries
.createQuery(attributedType.getClass())
.addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult();
if (parentProperty != null) {
AttributedType parentType = parentProperty.getValue(attributedType);
if (parentType != null) {
Property parentIdProperty = getMappingConfig(parentType.getClass()).getIdProperty();
String parentId = parentIdProperty.getValue(parentType);
String parentBaseDN = mappingConfig.getParentMapping().get(parentId);
if (parentBaseDN != null) {
baseDN = parentBaseDN;
} else {
baseDN = getBaseDN(parentType);
}
}
}
}
if (baseDN == null) {
baseDN = getConfig().getBaseDN();
}
return baseDN;
}
protected void addToParentAsMember(final AttributedType attributedType) {
LDAPMappingConfiguration entryConfig = getMappingConfig(attributedType.getClass());
if (entryConfig.getParentMembershipAttributeName() != null) {
Property parentProperty = PropertyQueries
.createQuery(attributedType.getClass())
.addCriteria(new TypedPropertyCriteria(attributedType.getClass()))
.getFirstResult();
if (parentProperty != null) {
AttributedType parentType = parentProperty.getValue(attributedType);
if (parentType != null) {
Attributes attributes = this.operationManager.getAttributes(parentType.getId(), getBaseDN(parentType), entryConfig);
Attribute attribute = attributes.get(entryConfig.getParentMembershipAttributeName());
attribute.add(getBindingDN(attributedType, true));
this.operationManager.modifyAttribute(getBindingDN(parentType, true), attribute);
}
}
}
}
protected String getEntryIdentifier(final AttributedType attributedType) {
try {
// we need this to retrieve the entry's identifier from the ldap server
List search = this.operationManager.search(getBaseDN(attributedType), "(" + getBindingDN(attributedType, false) + ")", getMappingConfig(attributedType.getClass()));
Attribute id = search.get(0).getAttributes().get(getConfig().getUniqueIdentifierAttributeName());
if (id == null) {
throw new IdentityManagementException("Could not retrieve identifier for entry [" + getBindingDN(attributedType, true) + "].");
}
return this.operationManager.decodeEntryUUID(id.get());
} catch (NamingException ne) {
throw new IdentityManagementException("Could not add type [" + attributedType + "].", ne);
}
}
}