Java tutorial
/* * Adito * * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.adito.activedirectory; import java.io.IOException; import java.util.Collection; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.PartialResultException; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.Control; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.PagedResultsControl; import javax.naming.ldap.PagedResultsResponseControl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; final class PagedResultTemplate { private static final Log logger = LogFactory.getLog(PagedResultTemplate.class); private final Collection<String> includedOuBasesList; private final Collection<String> excludedOuBasesList; private final Collection<String> ouSearchBase; private final int pageSize; PagedResultTemplate(Collection<String> includedOuBasesList, Collection<String> excludedOuBasesList, Collection<String> ouSearchBase, int pageSize) { this.includedOuBasesList = includedOuBasesList; this.excludedOuBasesList = excludedOuBasesList; this.ouSearchBase = ouSearchBase; this.pageSize = pageSize; } boolean searchForResult(InitialLdapContext context, String searchBase, String filter) throws NamingException { SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration<SearchResult> results = context.search(searchBase, filter, constraints); return results.hasMore(); } /** * @param context * @param filter * @param attributes * @param mapper * @throws NamingException * @throws Exception */ void search(InitialLdapContext context, String filter, String[] attributes, PagedResultMapper mapper) throws NamingException { if (pageSize == 0) { doSearch(context, filter, attributes, mapper); } else { doPagedSearch(context, filter, attributes, mapper); } assertExceptions(mapper); } private void assertExceptions(PagedResultMapper mapper) throws NamingException { if (mapper.containsExceptions()) { Exception e = mapper.getLastException(); logger.error(mapper.getExceptionCount() + " exceptions occurred, throwing the last one", e); throw e instanceof NamingException ? (NamingException) e : new NamingException(e.getMessage()); } } private void doSearch(InitialLdapContext context, String filter, String[] attributes, PagedResultMapper mapper) throws NamingException { SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); for (String searchBase : ouSearchBase) { if (logger.isDebugEnabled()) { logger.debug("Looking for items starting at " + searchBase + " (filter = " + filter + ")"); } try { constraints.setReturningAttributes(attributes); NamingEnumeration<SearchResult> results = context.search(searchBase, filter, constraints); mapResults(mapper, results); } catch (PartialResultException e) { // ignore } catch (NamingException e) { mapper.processException(e); logger.error("Possible configuration error! Did you enter your OUs correctly? [" + searchBase + "]", e); } } } private void doPagedSearch(InitialLdapContext context, String filter, String[] attributes, PagedResultMapper mapper) throws NamingException { SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); applyControls(context, pageSize); for (String searchBase : ouSearchBase) { if (logger.isDebugEnabled()) { logger.debug("Looking for items starting at " + searchBase + " (filter = " + filter + ")"); } try { int currentPage = 1; int startPosition = 0; int endPosition = pageSize - 1; byte[] cookie = null; do { String range = startPosition + "-" + endPosition; if (logger.isDebugEnabled()) { logger.debug("Starting search on page " + currentPage + " " + range); } constraints.setReturningAttributes(attributes); NamingEnumeration<SearchResult> results = context.search(searchBase, filter, constraints); try { mapResults(mapper, results); } catch (PartialResultException pre) { // We're paging so we dont care and don't log anymore } // Examine the paged results control response Control[] controls = context.getResponseControls(); if (controls != null) { for (int index = 0; index < controls.length; index++) { if (controls[index] instanceof PagedResultsResponseControl) { PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[index]; cookie = prrc.getCookie(); } } } applyControls(context, pageSize, cookie); startPosition = startPosition + pageSize; endPosition = endPosition + pageSize; currentPage++; } while ((cookie != null) && (cookie.length != 0)); } catch (NamingException e) { mapper.processException(e); logger.error("Possible configuration error! Did you enter your OUs correctly? [" + searchBase + "]", e); } } } private void mapResults(PagedResultMapper mapper, NamingEnumeration<SearchResult> results) throws NamingException { while (results != null && results.hasMore()) { SearchResult searchResult = results.next(); String dn = searchResult.getNameInNamespace(); try { if (isDnValid(dn)) { if (logger.isDebugEnabled()) { logger.debug("Included result " + dn); } mapper.mapSearchResult(searchResult); } else { if (logger.isDebugEnabled()) { logger.debug("Excluding result " + dn); } } } catch (Exception e) { mapper.processSearchResultException(searchResult, e); } } } boolean isDnValid(String dn) { boolean included = isInOuList(includedOuBasesList, dn); boolean notExcluded = !isInOuList(excludedOuBasesList, dn); return included && notExcluded; } private static boolean isInOuList(Collection<String> basesList, String dn) { for (String dnToCheck : basesList) { if (dn.toLowerCase().endsWith(dnToCheck.toLowerCase())) { return true; } } return false; } private void applyControls(InitialLdapContext context, int pageSize) throws NamingException { try { Control[] control = new Control[] { new PagedResultsControl(pageSize, Control.CRITICAL) }; context.setRequestControls(control); } catch (IOException e) { logger.warn("Tried to configure paged search but got error", e); } } private void applyControls(InitialLdapContext context, int pageSize, byte[] cookie) throws NamingException { try { context.setRequestControls( new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) }); } catch (IOException ex) { logger.warn("Tried to reconfigure paged result controls with error", ex); } } }