/* See LICENSE for licensing and NOTICE for copyright. */ package org.ldaptive.servlets; import java.io.IOException; import java.util.Arrays; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.ldaptive.LdapException; import org.ldaptive.SearchResult; import org.ldaptive.concurrent.AggregatePooledSearchExecutor; import org.ldaptive.pool.PooledConnectionFactory; import org.ldaptive.templates.Query; import org.ldaptive.templates.SearchTemplates; import org.ldaptive.templates.SearchTemplatesExecutor; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Searches an LDAP using a defined set of search templates. For each term count some number of templates are defined * and used for searching. * * @author Middleware Services */ public abstract class AbstractServletSearchTemplatesExecutor extends SearchTemplatesExecutor implements ServletSearchExecutor { /** Spring context path. */ private static final String SPRING_CONTEXT_PATH = "springContextPath"; /** Default spring context path. */ private static final String DEFAULT_SPRING_CONTEXT_PATH = "/templates-context.xml"; /** Ignore pattern. */ private static final String IGNORE_PATTERN = "ignorePattern"; /** Minimum query term length. */ private static final String MINIMUM_QUERY_TERM_LENGTH = "minimumQueryTermLength"; /** Regex pattern to ignore a query. */ private Pattern ignorePattern; /** Minimum length for at least one query term. */ private int minimumQueryTermLength; @Override public void initialize(final ServletConfig config) { final String springContextPath = config.getInitParameter(SPRING_CONTEXT_PATH) != null ? config.getInitParameter(SPRING_CONTEXT_PATH) : DEFAULT_SPRING_CONTEXT_PATH; logger.debug("{} = {}", SPRING_CONTEXT_PATH, springContextPath); final ApplicationContext context = new ClassPathXmlApplicationContext(springContextPath); setSearchExecutor(context.getBean(AggregatePooledSearchExecutor.class)); logger.debug("searchExecutor = {}", getSearchExecutor()); final Map<String, PooledConnectionFactory> factories = context.getBeansOfType(PooledConnectionFactory.class); setConnectionFactories(factories.values().toArray(new PooledConnectionFactory[factories.size()])); logger.debug("connectionFactories = {}", Arrays.toString(getConnectionFactories())); final Map<String, SearchTemplates> templates = context.getBeansOfType(SearchTemplates.class); setSearchTemplates(templates.values().toArray(new SearchTemplates[templates.size()])); logger.debug("searchTemplates = {}", Arrays.toString(getSearchTemplates())); ignorePattern = config.getInitParameter(IGNORE_PATTERN) != null ? Pattern.compile(config.getInitParameter(IGNORE_PATTERN)) : null; logger.debug("{} = {}", IGNORE_PATTERN, ignorePattern); minimumQueryTermLength = config.getInitParameter(MINIMUM_QUERY_TERM_LENGTH) != null ? Integer.parseInt(config.getInitParameter(MINIMUM_QUERY_TERM_LENGTH)) : 0; logger.debug("{} = {}", MINIMUM_QUERY_TERM_LENGTH, minimumQueryTermLength); } @Override public void search(final HttpServletRequest request, final HttpServletResponse response) throws LdapException, IOException { Integer fromResult = null; if (request.getParameter("from-result") != null) { try { fromResult = Integer.valueOf(request.getParameter("from-result")); } catch (NumberFormatException e) { logger.warn("Received invalid fromResult parameter: {}", request.getParameter("from-result")); } } Integer toResult = null; if (request.getParameter("to-result") != null) { try { toResult = Integer.valueOf(request.getParameter("to-result")); } catch (NumberFormatException e) { logger.warn("Received invalid toResult parameter: {}", request.getParameter("to-result")); } } boolean doSearch = true; final String queryString = request.getParameter("query"); if (queryString == null || queryString.length() == 0) { logger.info("Ignoring empty query"); doSearch = false; } if (doSearch && ignorePattern != null) { final Matcher matcher = ignorePattern.matcher(queryString); if (matcher.matches()) { logger.info("Ignoring query {}", queryString); doSearch = false; } } if (doSearch) { final Query query = new Query(queryString); if (minimumQueryTermLength > 0) { boolean hasMinimumLengthQueryTerm = false; for (String term : query.getTerms()) { if (term.length() >= minimumQueryTermLength) { hasMinimumLengthQueryTerm = true; break; } } if (!hasMinimumLengthQueryTerm) { logger.info("Does not meet minimum query term length {}", queryString); doSearch = false; } } if (doSearch) { query.setReturnAttributes(request.getParameterValues("attrs")); query.setSearchRestrictions(request.getParameter("search-restrictions")); query.setFromResult(fromResult); query.setToResult(toResult); logger.info("Performing query {}", query); final SearchResult result = search(query); writeResponse(result, response); } } } /** * Writes the supplied search result to the servlet response output stream. * * @param result search result to write * @param response to write to * * @throws IOException if an error occurs writing to the response */ protected abstract void writeResponse(final SearchResult result, final HttpServletResponse response) throws IOException; }