org.jasig.schedassist.impl.ldap.LDAPDelegateCalendarAccountDaoImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.jasig.schedassist.impl.ldap.LDAPDelegateCalendarAccountDaoImpl.java

Source

/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you 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.jasig.schedassist.impl.ldap;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.naming.directory.SearchControls;

import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.schedassist.IDelegateCalendarAccountDao;
import org.jasig.schedassist.model.ICalendarAccount;
import org.jasig.schedassist.model.IDelegateCalendarAccount;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.ldap.SizeLimitExceededException;
import org.springframework.ldap.TimeLimitExceededException;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
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 org.springframework.ldap.filter.OrFilter;

/**
 * LDAP backed {@link IDelegateCalendarAccountDao} implementation.
 * Returns "Resource" (or delegate) calendar accounts, e.g. {@link LDAPDelegateCalendarAccountImpl} instances.
 *
 * @author Nicholas Blair
 */
public class LDAPDelegateCalendarAccountDaoImpl implements IDelegateCalendarAccountDao {

    private static final String OBJECTCLASS = "objectclass";
    private static final String WILDCARD = "*";

    private final Log log = LogFactory.getLog(this.getClass());

    private LdapOperations ldapTemplate;
    private LDAPAttributesKey ldapAttributesKey = new LDAPAttributesKeyImpl();
    private String baseDn = "o=isp";
    private long searchResultsLimit = 25L;
    private int searchTimeLimit = 10000;
    private boolean treatOwnerAttributeAsDistinguishedName = true;
    private boolean enforceSpecificObjectClass = false;
    private String requiredObjectClass = "inetresource";

    /**
     * @param ldapTemplate the ldapTemplate to set
     */
    @Autowired
    public void setLdapTemplate(LdapOperations ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }

    /**
     * @param ldapAttributesKey the ldapAttributesKey to set
     */
    @Autowired
    public void setLdapAttributesKey(LDAPAttributesKey ldapAttributesKey) {
        this.ldapAttributesKey = ldapAttributesKey;
    }

    /**
     * @param baseDn the baseDn to set
     */
    @Value("${ldap.resourceAccountBaseDn:o=isp}")
    public void setBaseDn(String baseDn) {
        this.baseDn = baseDn;
    }

    /**
     * @param searchResultsLimit the searchResultsLimit to set
     */
    @Value("${ldap.searchResultsLimit:25}")
    public void setSearchResultsLimit(long searchResultsLimit) {
        this.searchResultsLimit = searchResultsLimit;
    }

    /**
     * @param searchTimeLimit the searchTimeLimit to set (in milliseconds)
     */
    @Value("${ldap.searchTimeLimitMillis:5000}")
    public void setSearchTimeLimit(int searchTimeLimit) {
        this.searchTimeLimit = searchTimeLimit;
    }

    /**
     * @return the treatOwnerAttributeAsDistinguishedName
     */
    public boolean isTreatOwnerAttributeAsDistinguishedName() {
        return treatOwnerAttributeAsDistinguishedName;
    }

    /**
     * @param treatOwnerAttributeAsDistinguishedName the treatOwnerAttributeAsDistinguishedName to set
     */
    @Value("${ldap.treatResourceOwnerAttributeAsDistinguishedName:true}")
    public void setTreatOwnerAttributeAsDistinguishedName(boolean treatOwnerAttributeAsDistinguishedName) {
        this.treatOwnerAttributeAsDistinguishedName = treatOwnerAttributeAsDistinguishedName;
    }

    /**
     * @param enforceSpecificObjectClass the enforceSpecificObjectClass to set
     */
    @Value("${ldap.resources.enforceSpecificObjectClass:false}")
    public void setEnforceSpecificObjectClass(boolean enforceSpecificObjectClass) {
        this.enforceSpecificObjectClass = enforceSpecificObjectClass;
    }

    /**
     * @param requiredObjectClass the requiredObjectClass to set
     */
    @Value("${ldap.resources.requiredObjectClass:inetresource}")
    public void setRequiredObjectClass(String requiredObjectClass) {
        this.requiredObjectClass = requiredObjectClass;
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#searchForDelegates(java.lang.String, org.jasig.schedassist.model.ICalendarAccount)
     */
    @Override
    public List<IDelegateCalendarAccount> searchForDelegates(String searchText, ICalendarAccount owner) {
        String searchTextInternal = searchText.replace(" ", WILDCARD);
        if (!searchTextInternal.endsWith(WILDCARD)) {
            searchTextInternal += WILDCARD;
        }

        AndFilter searchFilter = new AndFilter();

        // inner orFilter searches on displayName and username
        OrFilter orFilter = new OrFilter();
        orFilter.or(new LikeFilter(ldapAttributesKey.getDisplayNameAttributeName(), searchTextInternal));
        orFilter.or(new LikeFilter(ldapAttributesKey.getUsernameAttributeName(), searchTextInternal));

        // if the owner isn't null and owner attribute is NOT a DN, include the owner id in the search
        if (owner != null && !isTreatOwnerAttributeAsDistinguishedName()) {
            // TODO assumes delegateOwnerAttributeName has values of ICalendarAccount#getUsername
            searchFilter
                    .and(new EqualsFilter(ldapAttributesKey.getDelegateOwnerAttributeName(), owner.getUsername()));
        }
        // and the orFilter with filter to assert our results have calendar unique ids 
        searchFilter.and(orFilter);
        searchFilter.and(new LikeFilter(ldapAttributesKey.getUniqueIdentifierAttributeName(), WILDCARD));

        if (enforceSpecificObjectClass) {
            searchFilter.and(new EqualsFilter(OBJECTCLASS, requiredObjectClass));
        }
        List<IDelegateCalendarAccount> results = new ArrayList<IDelegateCalendarAccount>(
                executeSearchReturnList(searchFilter, owner));
        return results;
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#searchForDelegates(java.lang.String)
     */
    @Override
    public List<IDelegateCalendarAccount> searchForDelegates(String searchText) {
        return searchForDelegates(searchText, null);
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#getDelegate(java.lang.String)
     */
    @Override
    public IDelegateCalendarAccount getDelegate(String accountName) {
        return getDelegate(accountName, (ICalendarAccount) null);
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#getDelegate(java.lang.String, org.jasig.schedassist.model.ICalendarAccount)
     */
    @Override
    public IDelegateCalendarAccount getDelegate(String accountName, ICalendarAccount owner) {
        AndFilter searchFilter = new AndFilter();
        searchFilter.and(new EqualsFilter(ldapAttributesKey.getDisplayNameAttributeName(), accountName));
        if (owner != null && !isTreatOwnerAttributeAsDistinguishedName()) {
            // TODO assumes delegateOwnerAttributeName has values of ICalendarAccount#getUsername
            searchFilter
                    .and(new EqualsFilter(ldapAttributesKey.getDelegateOwnerAttributeName(), owner.getUsername()));
        }
        searchFilter.and(new LikeFilter(ldapAttributesKey.getUniqueIdentifierAttributeName(), WILDCARD));

        if (enforceSpecificObjectClass) {
            searchFilter.and(new EqualsFilter(OBJECTCLASS, requiredObjectClass));
        }
        List<IDelegateCalendarAccount> results = executeSearchReturnList(searchFilter, owner);
        IDelegateCalendarAccount delegate = (IDelegateCalendarAccount) DataAccessUtils.singleResult(results);
        return delegate;
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#getDelegateByUniqueId(java.lang.String)
     */
    @Override
    public IDelegateCalendarAccount getDelegateByUniqueId(String accountUniqueId) {
        return getDelegateByUniqueId(accountUniqueId, null);
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#getDelegateByUniqueId(java.lang.String, org.jasig.schedassist.model.ICalendarAccount)
     */
    @Override
    public IDelegateCalendarAccount getDelegateByUniqueId(String accountUniqueId, ICalendarAccount owner) {
        AndFilter searchFilter = new AndFilter();
        searchFilter.and(new EqualsFilter(ldapAttributesKey.getUniqueIdentifierAttributeName(), accountUniqueId));
        if (owner != null && !isTreatOwnerAttributeAsDistinguishedName()) {
            // TODO assumes delegateOwnerAttributeName has values of ICalendarAccount#getUsername
            searchFilter
                    .and(new EqualsFilter(ldapAttributesKey.getDelegateOwnerAttributeName(), owner.getUsername()));
        }
        if (enforceSpecificObjectClass) {
            searchFilter.and(new EqualsFilter(OBJECTCLASS, requiredObjectClass));
        }
        List<IDelegateCalendarAccount> results = executeSearchReturnList(searchFilter, owner);
        IDelegateCalendarAccount delegate = (IDelegateCalendarAccount) DataAccessUtils.singleResult(results);
        return delegate;
    }

    /* (non-Javadoc)
     * @see org.jasig.schedassist.IDelegateCalendarAccountDao#getDelegate(java.lang.String, java.lang.String)
     */
    @Override
    public IDelegateCalendarAccount getDelegate(String attributeName, String attributeValue) {
        Filter filter = new EqualsFilter(attributeName, attributeValue);
        if (enforceSpecificObjectClass) {
            AndFilter andFilter = new AndFilter();
            andFilter.and(filter);
            andFilter.and(new EqualsFilter(OBJECTCLASS, requiredObjectClass));
            filter = andFilter;
        }
        List<IDelegateCalendarAccount> results = executeSearchReturnList(filter, null);
        IDelegateCalendarAccount delegate = (IDelegateCalendarAccount) DataAccessUtils.singleResult(results);
        return delegate;
    }

    /**
     * 
     * @param searchFilter
     * @param owner
     * @return
     */
    @SuppressWarnings("unchecked")
    protected List<IDelegateCalendarAccount> executeSearchReturnList(final Filter searchFilter,
            final ICalendarAccount owner) {
        SearchControls searchControls = new SearchControls();
        searchControls.setCountLimit(searchResultsLimit);
        searchControls.setTimeLimit(searchTimeLimit);
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        List<IDelegateCalendarAccount> results = Collections.emptyList();
        try {
            results = ldapTemplate.search(baseDn, searchFilter.toString(), searchControls,
                    new DefaultDelegateAccountAttributesMapperImpl(ldapAttributesKey, owner));
            if (log.isDebugEnabled()) {
                log.debug("search " + searchFilter + " returned " + results.size() + " results");
            }

            if (isTreatOwnerAttributeAsDistinguishedName() && owner != null
                    && owner instanceof HasDistinguishedName) {
                HasDistinguishedName ldapOwnerAccount = (HasDistinguishedName) owner;
                enforceDistinguishedNameMatch(results, ldapOwnerAccount);
            }
            Collections.sort(results, new DelegateDisplayNameComparator());
        } catch (SizeLimitExceededException e) {
            log.debug("search filter exceeded size limit (" + searchResultsLimit + "): " + searchFilter);
        } catch (TimeLimitExceededException e) {
            log.debug("search filter exceeded time limit(" + searchTimeLimit + " milliseconds): " + searchFilter);
        }
        return results;
    }

    /**
     * Iterate over delegates, removing elements that have mismatched DN to owner
     * @param delegates
     * @param desiredOwnerAccount
     */
    protected void enforceDistinguishedNameMatch(List<IDelegateCalendarAccount> delegates,
            HasDistinguishedName desiredOwnerAccount) {
        for (Iterator<IDelegateCalendarAccount> i = delegates.iterator(); i.hasNext();) {
            IDelegateCalendarAccount delegate = i.next();
            String ownerAttributeValue = delegate.getAccountOwnerAttribute();
            if (!desiredOwnerAccount.getDistinguishedName().equals(new DistinguishedName(ownerAttributeValue))) {
                if (log.isDebugEnabled()) {
                    log.debug(ownerAttributeValue + " does not match desired owner ICalendarAccount dn: "
                            + desiredOwnerAccount.getDistinguishedName());
                }
                i.remove();
            }
        }
    }

    /**
     * Simple {@link Comparator} for {@link IDelegateCalendarAccount} that compares
     * on the displayName field.
     *
     * @author Nicholas Blair
     * @version $Id: LDAPDelegateCalendarAccountDaoImpl $
     */
    private static class DelegateDisplayNameComparator implements Comparator<IDelegateCalendarAccount> {
        @Override
        public int compare(IDelegateCalendarAccount o1, IDelegateCalendarAccount o2) {
            return new CompareToBuilder().append(o1.getDisplayName(), o2.getDisplayName()).toComparison();
        }
    }
}