package com.hwlcn.ldap.ldap.sdk.migrate.ldapjdk; import java.util.Enumeration; import java.util.NoSuchElementException; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import com.hwlcn.ldap.ldap.sdk.AsyncRequestID; import com.hwlcn.ldap.ldap.sdk.AsyncSearchResultListener; import com.hwlcn.ldap.ldap.sdk.Control; import com.hwlcn.ldap.ldap.sdk.ResultCode; import com.hwlcn.ldap.ldap.sdk.SearchResult; import com.hwlcn.ldap.ldap.sdk.SearchResultEntry; import com.hwlcn.ldap.ldap.sdk.SearchResultReference; import com.hwlcn.core.annotation.InternalUseOnly; import com.hwlcn.core.annotation.Mutable; import com.hwlcn.core.annotation.NotExtensible; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.util.Debug.*; @Mutable() @NotExtensible() @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) public class LDAPSearchResults implements Enumeration<Object>, AsyncSearchResultListener { private static final long serialVersionUID = 7884355145560496230L; private final AtomicBoolean searchDone; private final AtomicInteger count; private final AtomicReference<Control[]> lastControls; private final AtomicReference<Object> nextResult; private final AtomicReference<SearchResult> searchResult; private final long maxWaitTime; private final LinkedBlockingQueue<Object> resultQueue; public LDAPSearchResults() { this(0L); } public LDAPSearchResults(final long maxWaitTime) { this.maxWaitTime = maxWaitTime; searchDone = new AtomicBoolean(false); count = new AtomicInteger(0); lastControls = new AtomicReference<Control[]>(); nextResult = new AtomicReference<Object>(); searchResult = new AtomicReference<SearchResult>(); resultQueue = new LinkedBlockingQueue<Object>(50); } private Object nextObject() { Object o = nextResult.get(); if (o != null) { return o; } o = resultQueue.poll(); if (o != null) { nextResult.set(o); return o; } if (searchDone.get()) { return null; } try { if (maxWaitTime > 0) { o = resultQueue.poll(maxWaitTime, TimeUnit.MILLISECONDS); if (o == null) { o = new SearchResult(-1, ResultCode.TIMEOUT, null, null, null, 0, 0, null); count.incrementAndGet(); } } else { o = resultQueue.take(); } } catch (Exception e) { debugException(e); o = new SearchResult(-1, ResultCode.USER_CANCELED, null, null, null, 0, 0, null); count.incrementAndGet(); } nextResult.set(o); return o; } public boolean hasMoreElements() { final Object o = nextObject(); if (o == null) { return false; } if (o instanceof SearchResult) { final SearchResult r = (SearchResult) o; if (r.getResultCode().equals(ResultCode.SUCCESS)) { lastControls.set(r.getResponseControls()); searchDone.set(true); nextResult.set(null); return false; } } return true; } public Object nextElement() throws NoSuchElementException { final Object o = nextObject(); if (o == null) { throw new NoSuchElementException(); } nextResult.set(null); count.decrementAndGet(); if (o instanceof SearchResultEntry) { final SearchResultEntry e = (SearchResultEntry) o; lastControls.set(e.getControls()); return new LDAPEntry(e); } else if (o instanceof SearchResultReference) { final SearchResultReference r = (SearchResultReference) o; lastControls.set(r.getControls()); return new LDAPReferralException(r); } else { final SearchResult r = (SearchResult) o; searchDone.set(true); nextResult.set(null); lastControls.set(r.getResponseControls()); return new LDAPException(r.getDiagnosticMessage(), r.getResultCode().intValue(), r.getDiagnosticMessage(), r.getMatchedDN()); } } public LDAPEntry next() throws LDAPException { if (! hasMoreElements()) { throw new LDAPException(null, ResultCode.NO_RESULTS_RETURNED_INT_VALUE); } final Object o = nextElement(); if (o instanceof LDAPEntry) { return (LDAPEntry) o; } throw (LDAPException) o; } public int getCount() { return count.get(); } public LDAPControl[] getResponseControls() { final Control[] controls = lastControls.get(); if ((controls == null) || (controls.length == 0)) { return null; } return LDAPControl.toLDAPControls(controls); } @InternalUseOnly() public void searchEntryReturned(final SearchResultEntry searchEntry) { if (searchDone.get()) { return; } try { resultQueue.put(searchEntry); count.incrementAndGet(); } catch (Exception e) { debugException(e); searchDone.set(true); } } @InternalUseOnly() public void searchReferenceReturned( final SearchResultReference searchReference) { if (searchDone.get()) { return; } try { resultQueue.put(searchReference); count.incrementAndGet(); } catch (Exception e) { debugException(e); searchDone.set(true); } } @InternalUseOnly() public void searchResultReceived(final AsyncRequestID requestID, final SearchResult searchResult) { if (searchDone.get()) { return; } try { resultQueue.put(searchResult); if (! searchResult.getResultCode().equals(ResultCode.SUCCESS)) { count.incrementAndGet(); } } catch (Exception e) { debugException(e); searchDone.set(true); } } }