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

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

The newest version!
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;

/**
 * This class have been deprecated. Use the {@link JndiFinderService} instead. It does not require Spring in order to
 * work. Causing less problems with versions of said framework.
 * 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.
 */
@Deprecated() // Please use the se.vgregion.ldapservice.search.JndiFinderService instead.
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 - 2024 Weber Informatics LLC | Privacy Policy