| | |
| | | import java.util.Collection; |
| | | import java.util.concurrent.BlockingQueue; |
| | | import java.util.concurrent.LinkedBlockingQueue; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.TimeoutException; |
| | | |
| | | import org.forgerock.i18n.LocalizedIllegalArgumentException; |
| | | import org.forgerock.opendj.ldap.requests.Requests; |
| | | import org.forgerock.opendj.ldap.requests.SearchRequest; |
| | | import org.forgerock.opendj.ldap.requests.*; |
| | | import org.forgerock.opendj.ldap.responses.*; |
| | | import org.forgerock.opendj.ldif.ConnectionEntryReader; |
| | | |
| | |
| | | public abstract class AbstractConnection implements Connection |
| | | { |
| | | |
| | | private static final class SingleEntryHandler implements SearchResultHandler |
| | | private static final class SingleEntryFuture implements |
| | | FutureResult<SearchResultEntry>, SearchResultHandler |
| | | { |
| | | private final ResultHandler<? super SearchResultEntry> handler; |
| | | |
| | | private volatile SearchResultEntry firstEntry = null; |
| | | |
| | | private volatile SearchResultReference firstReference = null; |
| | | |
| | | private volatile int entryCount = 0; |
| | | |
| | | private volatile FutureResult<Result> future = null; |
| | | |
| | | |
| | | |
| | | private SingleEntryFuture( |
| | | final ResultHandler<? super SearchResultEntry> handler) |
| | | { |
| | | this.handler = handler; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean cancel(final boolean mayInterruptIfRunning) |
| | | { |
| | | return future.cancel(mayInterruptIfRunning); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public SearchResultEntry get() throws ErrorResultException, |
| | | InterruptedException |
| | | { |
| | | future.get(); |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public SearchResultEntry get(final long timeout, final TimeUnit unit) |
| | | throws ErrorResultException, TimeoutException, InterruptedException |
| | | { |
| | | future.get(timeout, unit); |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public int getRequestID() |
| | | { |
| | | return future.getRequestID(); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleEntry(final SearchResultEntry entry) |
| | | { |
| | | if (firstEntry == null) |
| | |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void handleErrorResult(final ErrorResultException error) |
| | | { |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(error); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleReference(final SearchResultReference reference) |
| | | { |
| | | if (firstReference == null) |
| | | { |
| | | firstReference = reference; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void handleResult(final Result result) |
| | | { |
| | | if (handler != null) |
| | | { |
| | | try |
| | | { |
| | | handler.handleResult(get0()); |
| | | } |
| | | catch (final ErrorResultException e) |
| | | { |
| | | handler.handleErrorResult(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean isCancelled() |
| | | { |
| | | return future.isCancelled(); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean isDone() |
| | | { |
| | | return future.isDone(); |
| | | } |
| | | |
| | | |
| | | |
| | | private SearchResultEntry get0() throws ErrorResultException |
| | | { |
| | | if (entryCount == 0) |
| | | { |
| | | // Did not find any entries. |
| | | throw newErrorResult(ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED, |
| | | ERR_NO_SEARCH_RESULT_ENTRIES.get().toString()); |
| | | } |
| | | else if (entryCount > 1) |
| | | { |
| | | // Got more entries than expected. |
| | | throw newErrorResult( |
| | | ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED, |
| | | ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount).toString()); |
| | | } |
| | | else if (firstReference != null) |
| | | { |
| | | // Got an unexpected search result reference. |
| | | throw newErrorResult( |
| | | ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED, |
| | | ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get( |
| | | firstReference.getURIs().iterator().next()).toString()); |
| | | } |
| | | else |
| | | { |
| | | return firstEntry; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private void setResultFuture(final FutureResult<Result> future) |
| | | { |
| | | this.future = future; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private static final class SingleEntryHandler implements SearchResultHandler |
| | | { |
| | | private volatile SearchResultEntry firstEntry = null; |
| | | |
| | | private volatile SearchResultReference firstReference = null; |
| | | |
| | | private volatile int entryCount = 0; |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleEntry(final SearchResultEntry entry) |
| | | { |
| | | if (firstEntry == null) |
| | | { |
| | | firstEntry = entry; |
| | | } |
| | | entryCount++; |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void handleErrorResult(final ErrorResultException error) |
| | | { |
| | | // Ignore. |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleReference(final SearchResultReference reference) |
| | | { |
| | | if (firstReference == null) |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | // Ignore. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleResult(Result result) |
| | | @Override |
| | | public void handleResult(final Result result) |
| | | { |
| | | // Ignore. |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result add(final Entry entry) throws ErrorResultException, |
| | | InterruptedException, UnsupportedOperationException, |
| | | IllegalStateException, NullPointerException |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result add(final String... ldifLines) throws ErrorResultException, |
| | | InterruptedException, UnsupportedOperationException, |
| | | LocalizedIllegalArgumentException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public BindResult bind(final String name, final char[] password) |
| | | throws ErrorResultException, InterruptedException, |
| | | LocalizedIllegalArgumentException, UnsupportedOperationException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void close() |
| | | { |
| | | close(Requests.newUnbindRequest(), null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public CompareResult compare(final String name, |
| | | final String attributeDescription, final String assertionValue) |
| | | throws ErrorResultException, InterruptedException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result delete(final String name) throws ErrorResultException, |
| | | InterruptedException, LocalizedIllegalArgumentException, |
| | | UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <R extends ExtendedResult> R extendedRequest( |
| | | final ExtendedRequest<R> request) throws ErrorResultException, |
| | | InterruptedException, UnsupportedOperationException, |
| | | IllegalStateException, NullPointerException |
| | | { |
| | | return extendedRequest(request, null); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public GenericExtendedResult extendedRequest(final String requestName, |
| | | final ByteString requestValue) throws ErrorResultException, |
| | | InterruptedException, UnsupportedOperationException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result modify(final String... ldifLines) throws ErrorResultException, |
| | | InterruptedException, UnsupportedOperationException, |
| | | LocalizedIllegalArgumentException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result modifyDN(final String name, final String newRDN) |
| | | throws ErrorResultException, InterruptedException, |
| | | LocalizedIllegalArgumentException, UnsupportedOperationException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SearchResultEntry readEntry(final DN baseObject, |
| | | final String... attributeDescriptions) throws ErrorResultException, |
| | | InterruptedException, UnsupportedOperationException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SearchResultEntry readEntry(final String baseObject, |
| | | final String... attributeDescriptions) throws ErrorResultException, |
| | | InterruptedException, LocalizedIllegalArgumentException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public FutureResult<SearchResultEntry> readEntryAsync(final DN name, |
| | | final Collection<String> attributeDescriptions, |
| | | final ResultHandler<? super SearchResultEntry> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = Requests.newSearchRequest(name, |
| | | SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter()); |
| | | if (attributeDescriptions != null) |
| | | { |
| | | request.getAttributes().addAll(attributeDescriptions); |
| | | } |
| | | return searchSingleEntryAsync(request, handler); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConnectionEntryReader search(final SearchRequest request, |
| | | final BlockingQueue<Response> entries) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | return new ConnectionEntryReader(this, request, entries); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result search(final SearchRequest request, |
| | | final Collection<? super SearchResultEntry> entries) |
| | | throws ErrorResultException, InterruptedException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Result search(final SearchRequest request, |
| | | final Collection<? super SearchResultEntry> entries, |
| | | final Collection<? super SearchResultReference> references) |
| | |
| | | final SearchResultHandler handler = new SearchResultHandler() |
| | | { |
| | | |
| | | @Override |
| | | public boolean handleEntry(final SearchResultEntry entry) |
| | | { |
| | | entries.add(entry); |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void handleErrorResult(final ErrorResultException error) |
| | | { |
| | | // Ignore. |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleReference(final SearchResultReference reference) |
| | | { |
| | | if (references != null) |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | // Ignore. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void handleResult(Result result) |
| | | @Override |
| | | public void handleResult(final Result result) |
| | | { |
| | | // Ignore. |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConnectionEntryReader search(final String baseObject, |
| | | final SearchScope scope, final String filter, |
| | | final String... attributeDescriptions) |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SearchResultEntry searchSingleEntry(final SearchRequest request) |
| | | throws ErrorResultException, InterruptedException, |
| | | UnsupportedOperationException, IllegalStateException, |
| | |
| | | if (handler.entryCount == 0) |
| | | { |
| | | // Did not find any entries. |
| | | throw newErrorResult( |
| | | ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED, |
| | | throw newErrorResult(ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED, |
| | | ERR_NO_SEARCH_RESULT_ENTRIES.get().toString()); |
| | | } |
| | | else if (handler.entryCount > 1) |
| | | { |
| | | // Got more entries than expected. |
| | | throw newErrorResult( |
| | | ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED, |
| | | ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES |
| | | .get(handler.entryCount).toString()); |
| | | throw newErrorResult(ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED, |
| | | ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(handler.entryCount) |
| | | .toString()); |
| | | } |
| | | else if (handler.firstReference != null) |
| | | { |
| | |
| | | throw newErrorResult( |
| | | ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED, |
| | | ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get( |
| | | handler.firstReference.getURIs().iterator().next()) |
| | | .toString()); |
| | | handler.firstReference.getURIs().iterator().next()).toString()); |
| | | } |
| | | else |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SearchResultEntry searchSingleEntry(final String baseObject, |
| | | final SearchScope scope, final String filter, |
| | | final String... attributeDescriptions) throws ErrorResultException, |
| | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public FutureResult<SearchResultEntry> searchSingleEntryAsync( |
| | | final SearchRequest request, |
| | | final ResultHandler<? super SearchResultEntry> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SingleEntryFuture innerFuture = new SingleEntryFuture(handler); |
| | | final FutureResult<Result> future = searchAsync(request, null, innerFuture); |
| | | innerFuture.setResultFuture(future); |
| | | return innerFuture; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * <p> |
| | | * Sub-classes should provide an implementation which returns an appropriate |
| | | * description of the connection which may be used for debugging purposes. |
| | | */ |
| | | @Override |
| | | public abstract String toString(); |
| | | |
| | | } |