Java tutorial
/** * Copyright 2005-2014 The Kuali Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php * * 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.kuali.rice.kim.dao.impl; import org.apache.commons.lang.StringUtils; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kim.api.identity.entity.Entity; import org.kuali.rice.kim.api.identity.entity.EntityDefault; import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName; import org.kuali.rice.kim.api.identity.principal.Principal; import org.kuali.rice.kim.api.identity.privacy.EntityPrivacyPreferences; import org.kuali.rice.kim.dao.LdapPrincipalDao; import org.kuali.rice.kim.impl.identity.PersonImpl; import org.kuali.rice.kim.util.Constants; import org.springframework.ldap.SizeLimitExceededException; import org.springframework.ldap.core.ContextMapper; import org.springframework.ldap.core.ContextMapperCallbackHandler; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.filter.AndFilter; import org.springframework.ldap.filter.LikeFilter; import org.springframework.ldap.filter.NotFilter; import org.springframework.ldap.filter.OrFilter; import javax.naming.directory.SearchControls; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.kuali.rice.core.util.BufferedLogger.*; import static org.kuali.rice.kns.lookup.LookupUtils.getSearchResultsLimit; /** * Integrated Data Access via LDAP to EDS. Provides implementation to interface method * for using Spring-LDAP to communicate with EDS. * * @author Kuali Rice Team (rice.collab@kuali.org) */ public class LdapPrincipalDaoImpl implements LdapPrincipalDao { private Constants kimConstants; private LdapTemplate template; private ParameterService parameterService; private Map<String, ContextMapper> contextMappers; public LdapPrincipalDaoImpl() { } /** * In EDS, the principalId, principalName, and entityId will all be the same. */ public Principal getPrincipal(String principalId) { if (principalId == null) { return null; } Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapIdProperty(), principalId); List<Principal> results = search(Principal.class, criteria); if (results.size() > 0) { return results.get(0); } return null; } /** * Assuming he principalId, principalName, and entityId will all be the same. */ public Principal getPrincipalByName(String principalName) { if (principalName == null) { return null; } Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapNameProperty(), principalName); List<Principal> results = search(Principal.class, criteria); if (results.size() > 0) { return results.get(0); } return null; } public <T> List<T> search(Class<T> type, Map<String, Object> criteria) { AndFilter filter = new AndFilter(); for (Map.Entry<String, Object> entry : criteria.entrySet()) { //attempting to handle null values to prevent NPEs in this code. if (entry.getValue() == null) { entry.setValue("null"); } if (entry.getValue() instanceof Iterable) { OrFilter orFilter = new OrFilter(); for (String value : (Iterable<String>) entry.getValue()) { if (value.startsWith("!")) { orFilter.or(new NotFilter(new LikeFilter(entry.getKey(), value.substring(1)))); } else { orFilter.or(new LikeFilter(entry.getKey(), value)); } } filter.and(orFilter); } else { if (((String) entry.getValue()).startsWith("!")) { filter.and(new NotFilter( new LikeFilter(entry.getKey(), ((String) entry.getValue()).substring(1)))); } else { filter.and(new LikeFilter(entry.getKey(), (String) entry.getValue())); } } } ; info("Using filter ", filter); debug("Looking up mapper for ", type.getSimpleName()); final ContextMapper customMapper = contextMappers.get(type.getSimpleName()); ContextMapperCallbackHandler callbackHandler = new CustomContextMapperCallbackHandler(customMapper); try { getLdapTemplate().search(DistinguishedName.EMPTY_PATH, filter.encode(), getSearchControls(), callbackHandler); } catch (SizeLimitExceededException e) { // Ignore this. We want to limit our results. } return callbackHandler.getList(); } protected SearchControls getSearchControls() { SearchControls retval = new SearchControls(); retval.setCountLimit(getSearchResultsLimit(PersonImpl.class).longValue()); retval.setSearchScope(SearchControls.SUBTREE_SCOPE); return retval; } /** * FIND entity objects based on the given criteria. * * @param entityId of user/person to grab entity information for * @return {@link Entity} */ public Entity getEntity(String entityId) { if (entityId == null) { return null; } Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapIdProperty(), entityId); List<Entity> results = search(Entity.class, criteria); debug("Got results from info lookup ", results, " with size ", results.size()); if (results.size() > 0) { return results.get(0); } return null; } /** * Fetches full entity info, populated from EDS, based on the Entity's principal id * @param principalId the principal id to look the entity up for * @return the corresponding entity info */ public Entity getEntityByPrincipalId(String principalId) { if (principalId == null) { return null; } final Principal principal = getPrincipal(principalId); if (principal != null && !StringUtils.isBlank(principal.getEntityId())) { return getEntity(principal.getEntityId()); } return null; } public EntityDefault getEntityDefault(String entityId) { if (entityId == null) { return null; } Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapIdProperty(), entityId); List<EntityDefault> results = search(EntityDefault.class, criteria); debug("Got results from info lookup ", results, " with size ", results.size()); if (results.size() > 0) { return results.get(0); } return null; } /** * entityid and principalId are treated as the same. * * @see #getEntityDefaultInfo(String) */ public EntityDefault getEntityDefaultByPrincipalId(String principalId) { return getEntityDefault(principalId); } public EntityDefault getEntityDefaultByPrincipalName(String principalName) { Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapNameProperty(), principalName); List<EntityDefault> results = search(EntityDefault.class, criteria); if (results.size() > 0) { return results.get(0); } return null; } public Entity getEntityByPrincipalName(String principalName) { Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapNameProperty(), principalName); List<Entity> results = search(Entity.class, criteria); if (results.size() > 0) { return results.get(0); } return null; } public List<EntityDefault> lookupEntityDefault(Map<String, String> searchCriteria, boolean unbounded) { List<EntityDefault> results = new ArrayList(); Map<String, Object> criteria = getLdapLookupCriteria(searchCriteria); results = search(EntityDefault.class, criteria); return results; } public List<String> lookupEntityIds(Map<String, String> searchCriteria) { final List<String> results = new ArrayList<String>(); final Map<String, Object> criteria = getLdapLookupCriteria(searchCriteria); for (final Entity entity : search(Entity.class, criteria)) { results.add(entity.getId()); } return results; } /** * Converts Kuali Lookup parameters into LDAP query parameters * @param searchCriteria kuali lookup info * @return {@link Map} of LDAP query info */ protected Map<String, Object> getLdapLookupCriteria(Map<String, String> searchCriteria) { Map<String, Object> criteria = new HashMap(); boolean hasTaxId = false; for (Map.Entry<String, String> criteriaEntry : searchCriteria.entrySet()) { debug(String.format("Searching with criteria %s = %s", criteriaEntry.getKey(), criteriaEntry.getValue())); String valueName = criteriaEntry.getKey(); Object value = criteriaEntry.getValue(); if (!criteriaEntry.getValue().equals("*")) { valueName = String.format("%s.%s", criteriaEntry.getKey(), criteriaEntry.getValue()); } if (!value.equals("*") && isMapped(valueName)) { value = getLdapValue(valueName); debug(value, " mapped to valueName ", valueName); } if (isMapped(criteriaEntry.getKey())) { debug(String.format("Setting attribute to (%s, %s)", getLdapAttribute(criteriaEntry.getKey()), value)); final String key = getLdapAttribute(criteriaEntry.getKey()); if (!criteria.containsKey(key)) { criteria.put(key, value); } } else if (criteriaEntry.getKey().equalsIgnoreCase(getKimConstants().getExternalIdProperty())) { criteria.put(getKimConstants().getKimLdapIdProperty(), value); } else if (criteriaEntry.getKey().equalsIgnoreCase(getKimConstants().getExternalIdTypeProperty()) && value.toString().equals(getKimConstants().getTaxExternalIdTypeCode())) { hasTaxId = true; } } return criteria; } public EntityPrivacyPreferences getEntityPrivacyPreferences(String entityId) { if (entityId == null) { return null; } Map<String, Object> criteria = new HashMap(); criteria.put(getKimConstants().getKimLdapIdProperty(), entityId); List<EntityPrivacyPreferences> results = search(EntityPrivacyPreferences.class, criteria); if (results.size() > 0) { return results.get(0); } return null; } public Map<String, EntityNamePrincipalName> getDefaultNamesForPrincipalIds(List<String> principalIds) { Map<String, Object> criteria = new HashMap(); Map<String, EntityNamePrincipalName> retval = new HashMap(); criteria.put(getKimConstants().getKimLdapIdProperty(), principalIds); List<EntityNamePrincipalName> results = search(EntityNamePrincipalName.class, criteria); for (EntityNamePrincipalName nameInfo : results) { retval.put(nameInfo.getPrincipalName(), nameInfo); } return retval; } public Map<String, EntityNamePrincipalName> getDefaultNamesForEntityIds(List<String> entityIds) { return getDefaultNamesForPrincipalIds(entityIds); } protected Matcher getKimAttributeMatcher(String kimAttribute) { String mappedParamValue = getParameterService().getParameterValueAsString( getKimConstants().getParameterNamespaceCode(), getKimConstants().getParameterDetailTypeCode(), getKimConstants().getMappedParameterName()); String regexStr = String.format("(%s|.*;%s)=([^=;]*).*", kimAttribute, kimAttribute); debug("Matching KIM attribute with regex ", regexStr); Matcher retval = Pattern.compile(regexStr).matcher(mappedParamValue); if (!retval.matches()) { mappedParamValue = getParameterService().getParameterValueAsString( getKimConstants().getParameterNamespaceCode(), getKimConstants().getParameterDetailTypeCode(), getKimConstants().getMappedValuesName()); retval = Pattern.compile(regexStr).matcher(mappedParamValue); } return retval; } protected boolean isMapped(String kimAttribute) { debug("Matching " + kimAttribute); debug("Does ", kimAttribute, " match? ", getKimAttributeMatcher(kimAttribute).matches()); return getKimAttributeMatcher(kimAttribute).matches(); } protected String getLdapAttribute(String kimAttribute) { Matcher matcher = getKimAttributeMatcher(kimAttribute); debug("Does ", kimAttribute, " match? ", matcher.matches()); if (matcher.matches()) { return matcher.group(2); } else { return null; } } protected Object getLdapValue(String kimAttribute) { Matcher matcher = getKimAttributeMatcher(kimAttribute); debug("Does ", kimAttribute, " match? ", matcher.matches()); if (!matcher.matches()) { return null; } String value = matcher.group(2); // If it's actually a list. It can only be a list if there are commas if (value.contains(",")) { return Arrays.asList(value.split(",")); } return value; } public void setKimConstants(Constants constants) { this.kimConstants = constants; } public Constants getKimConstants() { return kimConstants; } public ParameterService getParameterService() { return this.parameterService; } public void setParameterService(ParameterService service) { this.parameterService = service; } public LdapTemplate getLdapTemplate() { return template; } public void setLdapTemplate(LdapTemplate template) { this.template = template; } public Map<String, ContextMapper> getContextMappers() { return this.contextMappers; } public void setContextMappers(final Map<String, ContextMapper> contextMappers) { this.contextMappers = contextMappers; } /** * Overrides the existing {@link ContextMapperCallbackHandler} because we want to * intercede when there is invalid results from EDS. * * @author Leo Przybylski (przybyls@arizona.edu) */ private static final class CustomContextMapperCallbackHandler extends ContextMapperCallbackHandler { public CustomContextMapperCallbackHandler(ContextMapper mapper) { super(mapper); } } }