se.vgregion.service.innovationsslussen.ldap.LdapService.java Source code

Java tutorial

Introduction

Here is the source code for se.vgregion.service.innovationsslussen.ldap.LdapService.java

Source

/**
 * Copyright 2010 Vstra Gtalandsregionen
 *
 *   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.service.innovationsslussen.ldap;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;

import org.apache.commons.collections.BeanMap;
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;

/**
 * Created with IntelliJ IDEA.
 * User: portaldev
 * Date: 2013-08-13
 * Time: 11:01
 * To change this template use File | Settings | File Templates.
 */
public class LdapService {

    private LdapTemplate ldapTemplate;

    public LdapTemplate getLdapTemplate() {
        return ldapTemplate;
    }

    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }

    /**
     * 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 <T> type of the param and type of the answers inside the resulting list.
     * @return a list of search hits.
     */
    public <T> List<T> find(T sample) {
        final AttributesMapper mapper = newAttributesMapper(sample.getClass());
        final Filter searchFilter = toAndCondition(sample);
        final SearchControls searchControls = new SearchControls();
        searchControls.setReturningAttributes(new String[] { "*" });
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        @SuppressWarnings("unchecked")
        List<T> result = ldapTemplate.search(StringUtils.EMPTY, searchFilter.encode(), searchControls, mapper);

        return result;
    }

    AttributesMapper newAttributesMapper(final Class type) {
        return new AttributesMapper() {
            @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<? extends Attribute> all = attributes.getAll();

                while (all.hasMore()) {
                    Attribute attribute = all.next();

                    String name = toBeanPropertyName(attribute.getID());
                    if (bm.containsKey(name) && bm.getWriteMethod(name) != null) {
                        bm.put(name, attribute.get());
                    }
                }
                return result;
            }
        };
    }

    String toBeanPropertyName(String name) {
        name = removeSignFrom(name, ";");
        name = removeSignFrom(name, "-");
        return name;
    }

    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<String, Object> entry = (Map.Entry<String, Object>) entryObj;
            String property = entry.getKey();
            if (bm.getWriteMethod(property) != null) {
                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);
            }
        }
    }

}