/* See LICENSE for licensing and NOTICE for copyright. */ package org.ldaptive.referral; import org.ldaptive.Connection; import org.ldaptive.LdapException; import org.ldaptive.LdapURL; import org.ldaptive.LdapUtils; import org.ldaptive.Operation; import org.ldaptive.Response; import org.ldaptive.SearchOperation; import org.ldaptive.SearchReference; import org.ldaptive.SearchRequest; import org.ldaptive.SearchResult; import org.ldaptive.handler.HandlerResult; /** * Provides handling of an ldap referral for search operations. Injects a {@link * org.ldaptive.handler.SearchReferenceHandler} so that both referrals and search references will be followed. * * @author Middleware Services */ public class SearchReferralHandler extends AbstractReferralHandler<SearchRequest, SearchResult> { /** Creates a new search referral handler. */ public SearchReferralHandler() { this(DEFAULT_REFERRAL_LIMIT, 0, DEFAULT_CONNECTION_FACTORY); } /** * Creates a new search referral handler. * * @param factory referral connection factory */ public SearchReferralHandler(final ReferralConnectionFactory factory) { this(DEFAULT_REFERRAL_LIMIT, 0, factory); } /** * Creates a new search referral handler. * * @param limit number of referrals to follow */ public SearchReferralHandler(final int limit) { this(limit, 0, DEFAULT_CONNECTION_FACTORY); } /** * Creates a new search referral handler. * * @param limit number of referrals to follow * @param factory referral connection factory */ public SearchReferralHandler(final int limit, final ReferralConnectionFactory factory) { this(limit, 0, factory); } /** * Creates a new search referral handler. * * @param limit number of referrals to follow * @param depth number of referrals followed * @param factory referral connection factory */ private SearchReferralHandler(final int limit, final int depth, final ReferralConnectionFactory factory) { super(limit, depth, factory); } @Override protected SearchRequest createReferralRequest(final SearchRequest request, final LdapURL url) { final SearchRequest referralRequest = new SearchRequest(); referralRequest.setControls(request.getControls()); referralRequest.setIntermediateResponseHandlers(request.getIntermediateResponseHandlers()); referralRequest.setReferralHandler( new SearchReferralHandler(getReferralLimit(), getReferralDepth() + 1, getReferralConnectionFactory())); if (!url.getEntry().isDefaultBaseDn()) { referralRequest.setBaseDn(url.getEntry().getBaseDn()); } else { referralRequest.setBaseDn(request.getBaseDn()); } referralRequest.setBinaryAttributes(request.getBinaryAttributes()); referralRequest.setDerefAliases(request.getDerefAliases()); referralRequest.setSearchEntryHandlers(request.getSearchEntryHandlers()); final org.ldaptive.handler.SearchReferenceHandler[] searchReferenceHandlers = request.getSearchReferenceHandlers(); if (searchReferenceHandlers != null) { for (int i = 0; i < searchReferenceHandlers.length; i++) { if (searchReferenceHandlers[i] instanceof SearchReferenceHandler) { final SearchReferenceHandler handler = (SearchReferenceHandler) searchReferenceHandlers[i]; searchReferenceHandlers[i] = new SearchReferenceHandler( handler.getReferralLimit(), handler.getReferralDepth() + 1, handler.getReferralConnectionFactory()); } } } referralRequest.setReturnAttributes(request.getReturnAttributes()); if (!url.getEntry().isDefaultFilter()) { referralRequest.setSearchFilter(url.getEntry().getFilter()); } else { referralRequest.setSearchFilter(request.getSearchFilter()); } if (!url.getEntry().isDefaultScope()) { referralRequest.setSearchScope(url.getEntry().getScope()); } else { referralRequest.setSearchScope(request.getSearchScope()); } referralRequest.setSizeLimit(request.getSizeLimit()); referralRequest.setSortBehavior(request.getSortBehavior()); referralRequest.setTimeLimit(request.getTimeLimit()); referralRequest.setTypesOnly(request.getTypesOnly()); return referralRequest; } @Override protected Operation<SearchRequest, SearchResult> createReferralOperation(final Connection conn) { return new SearchOperation(conn); } @Override public void initializeRequest(final SearchRequest request) { if (request.getSearchReferenceHandlers() != null) { request.setSearchReferenceHandlers( LdapUtils.concatArrays( request.getSearchReferenceHandlers(), new org.ldaptive.handler.SearchReferenceHandler[] {new SearchReferenceHandler(), })); } else { request.setSearchReferenceHandlers(new SearchReferenceHandler()); } } /** * Implementation of {@link org.ldaptive.handler.SearchReferenceHandler} that delegates to {@link * SearchReferralHandler}. */ public static class SearchReferenceHandler implements org.ldaptive.handler.SearchReferenceHandler { /** Referral limit. */ private final int referralLimit; /** Referral depth. */ private final int referralDepth; /** Referral connection factory. */ private final ReferralConnectionFactory connectionFactory; /** Creates a new search reference handler. */ public SearchReferenceHandler() { this(DEFAULT_REFERRAL_LIMIT, 0, DEFAULT_CONNECTION_FACTORY); } /** * Creates a new search reference handler. * * @param factory referral connection factory */ public SearchReferenceHandler(final ReferralConnectionFactory factory) { this(DEFAULT_REFERRAL_LIMIT, 0, factory); } /** * Creates a new search reference handler. * * @param limit number of referrals to follow */ public SearchReferenceHandler(final int limit) { this(limit, 0, DEFAULT_CONNECTION_FACTORY); } /** * Creates a new search reference handler. * * @param limit number of referrals to follow * @param factory referral connection factory */ public SearchReferenceHandler(final int limit, final ReferralConnectionFactory factory) { this(limit, 0, factory); } /** * Creates a new search reference handler. * * @param limit number of referrals to follow * @param depth number of referrals followed * @param factory referral connection factory */ private SearchReferenceHandler(final int limit, final int depth, final ReferralConnectionFactory factory) { referralLimit = limit; referralDepth = depth; connectionFactory = factory; } /** * Returns the maximum number of referrals to follow. * * @return referral limit */ public int getReferralLimit() { return referralLimit; } /** * Returns the referral depth of this handler. * * @return referral depth */ public int getReferralDepth() { return referralDepth; } /** * Returns the referral connection factory. * * @return referral connection factory */ public ReferralConnectionFactory getReferralConnectionFactory() { return connectionFactory; } @Override public HandlerResult<SearchReference> handle( final Connection conn, final SearchRequest request, final SearchReference reference) throws LdapException { if (reference == null) { return new HandlerResult<>(null); } final SearchReferralHandler handler = new SearchReferralHandler(referralLimit, referralDepth, connectionFactory); final HandlerResult<Response<SearchResult>> result = handler.handle(conn, request, reference.getReferralUrls()); final Response<SearchResult> response = result.getResult(); if (response != null) { reference.setReferenceResponse(response); } return new HandlerResult<>(reference); } @Override public void initializeRequest(final SearchRequest request) {} } }