All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.vgregion.ldapservice.search.LdapFinderService Maven / Gradle / Ivy

/**
 * Copyright 2010 Västra Götalandsregionen
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of version 2.1 of the GNU Lesser General Public
 *   License as published by the Free Software Foundation.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the
 *   Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 *   Boston, MA 02111-1307  USA
 */

package se.vgregion.ldapservice.search;

import org.apache.commons.lang.StringUtils;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.filter.Filter;
import org.springframework.ldap.filter.LikeFilter;
import se.vgregion.ldapservice.search.beanutil.BeanMap;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Pattern;

/**
 * Capablity to search in a ldap server on any field(s) and getting it back. The name of the fields that is used in
 * the search and that are present on the resulting beans are based the bean used for searching. What you search with
 * you will also get back, packaging the result in beans inside a list.
 * 

* Example of initilizating: *

* * *

*

* *

* * * * * * *

* *

* * * * * * * *

* * * *

* * * *

* * */ public class LdapFinderService { private LdapTemplate ldapTemplate; private static final ExecutorService executor = Executors.newCachedThreadPool(); /** * Finds data from the ldap server. Provide a structure (class instance) with the data to use as search criteria * and gets the answer as a list with the same format (class type) as the criteria. * * @param sample holds properties that (could) match fields in the db by the operator '=' or 'like' (in conjunction * with having a '*' character in a String value). * @param type of the param and type of the answers inside the resulting list. * @return a list of search hits. */ public List find(T sample) { return findImp(sample, newBeanAttributesMapper(sample.getClass())); } /** * Se se.vgregion.ldapservice.search.LdapFinderService#find(T) to understand this method. Except that it wraps * the return in a future object. * @param sample holds properties that (could) match fields in the db by the operator '=' or 'like' (in conjunction * with having a '*' character in a String value). * @param type of the param and type of the answers inside the resulting list. * @return a list of search hits, wraped in a future object. */ public Future> findFuture(final T sample) { return executor.submit(new Callable>() { @Override public List call() throws Exception { return find(sample); } }); } private List findImp(T sample, final AttributesMapper mapper) { final Filter searchFilter = toAndCondition(sample); final SearchControls searchControls = new SearchControls(); searchControls.setReturningAttributes(new String[]{"*"}); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); return ldapTemplate.search(StringUtils.EMPTY, searchFilter.encode(), searchControls, mapper); } /** * Creates @org.springframework.ldap.core.AttributesMapper that maps values from ldap search to a bean. * * @param type what type (of bean) to make the mapping functionality for. * @return A new instance of org.springframework.ldap.core.AttributesMapper. */ public static AttributesMapper newBeanAttributesMapper(final Class type) { return new BeanAttributesMapper(type); } static String toBeanPropertyName(String name) { name = removeSignFrom(name, ";"); name = removeSignFrom(name, "-"); return name; } static String removeSignFrom(String beanPropertyName, String sign) { if (beanPropertyName.contains(sign)) { String[] parts = beanPropertyName.split(Pattern.quote(sign)); StringBuilder sb = new StringBuilder(parts[0]); for (int i = 1; i < parts.length; i++) { char head = Character.toUpperCase(parts[i].charAt(0)); String tail = parts[i].substring(1); sb.append(head); sb.append(tail); } return sb.toString(); } return beanPropertyName; } Filter newAttributeFilter(final String name, final String value) { Filter filter; if (value.contains("*")) { filter = new LikeFilter(name, value); } else { filter = new EqualsFilter(name, value); } return filter; } AndFilter toAndCondition(Object obj) { AndFilter filter = new AndFilter(); BeanMap bm = new BeanMap(obj); Class type = obj.getClass(); for (Object entryObj : bm.entrySet()) { Map.Entry entry = (Map.Entry) entryObj; String property = entry.getKey(); if (bm.isWritable(property)) { Object value = entry.getValue(); if (value != null && !"".equals(value.toString().trim())) { String ldapPropertyName = getPlainNameOrExplicit(type, property); filter.and(newAttributeFilter(ldapPropertyName, value.toString())); } } } return filter; } static String getPlainNameOrExplicit(Class type, String propertyName) { try { return getPlainNameOrExplicitImpl(type, propertyName); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } } static String getPlainNameOrExplicitImpl(Class type, String propertyName) throws NoSuchFieldException { Field field = getField(type, propertyName); Annotation annotation = field.getAnnotation(ExplicitLdapName.class); if (annotation == null) { return propertyName; } ExplicitLdapName explicitLdapName = (ExplicitLdapName) annotation; return explicitLdapName.value(); } static Field getField(Class clazz, String fieldName) throws NoSuchFieldException { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { Class superClass = clazz.getSuperclass(); if (superClass == null) { throw e; } else { return getField(superClass, fieldName); } } } /** * Getter for ldapTemplate. * @return instance of mentioned var. */ public LdapTemplate getLdapTemplate() { return ldapTemplate; } /** * Setter for ldapTemplate. * @param ldapTemplate the new value. */ public void setLdapTemplate(LdapTemplate ldapTemplate) { this.ldapTemplate = ldapTemplate; } public String toBeanText(String sampleCn) { WebLdapPerson sample = new WebLdapPerson(); sample.setCn(sampleCn); StringBuilder sb = new StringBuilder(); findImp(sample, newBeanToJavaCodeAttributesMapper(sb)); return sb.toString(); } private AttributesMapper newBeanToJavaCodeAttributesMapper(final StringBuilder sb) { return new BeanAttributesMapper(WebLdapPerson.class) { @Override public Object mapFromAttributes(Attributes attributes) throws NamingException { NamingEnumeration all = attributes.getAll(); while (all.hasMore()) { Attribute attribute = all.next(); String name = toBeanPropertyName(attribute.getID()); Object value = attribute.get(); String className = "String"; if (value != null && !String.class.equals(value.getClass())) { Class clazz = value.getClass(); if (clazz.isArray()) { className = clazz.getComponentType().getName() + "[]"; } else { className = value.getClass().getName(); } } sb.append("@ExplicitLdapName(\"" + attribute.getID() + "\")\n"); sb.append("private " + className + " " + name + ";\n\n"); } return super.mapFromAttributes(attributes); } }; } public static class BeanAttributesMapper implements AttributesMapper { private final Class type; public BeanAttributesMapper(Class type) { super(); this.type = type; } @Override public Object mapFromAttributes(Attributes attributes) throws NamingException { try { return mapFromAttributesImpl(attributes); } catch (Exception e) { throw new RuntimeException(e); } } public Object mapFromAttributesImpl(Attributes attributes) throws NamingException, IllegalAccessException, InstantiationException { Object result = type.newInstance(); BeanMap bm = new BeanMap(result); NamingEnumeration all = attributes.getAll(); Map actualValues = new HashMap(); while (all.hasMore()) { Attribute attribute = all.next(); String name = toBeanPropertyName(attribute.getID()); actualValues.put(name, attribute.getID()); if (bm.containsKey(name) && bm.isWritable(name)) { bm.put(name, attribute.get()); } } return result; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy