Various changes:
* fix command line tools so that they exit
* remove ConnectionFuture and ConnectionResultHandler and use ResultFuture/ResultHandler instead
* rename ResultFuture -> FutureResult to align with FutureTask name format
* provide AbstractFutureResult which can be used for handling asynchronous results
* fix FutureResultTransformer so that it does not create a new result for each invocation of get()
* fix ResultChain - remove race conditions, simplify, improve APIs, etc...
* rename ResultChain -> RecursiveFutureResult
* rename ResultTransformer -> FutureResultTransformer
* add getSchemaName() to Schema class for retrieving a user friendly name of a schema (for use in debugging).
3 files deleted
29 files modified
2 files added
2 files renamed
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.*; |
| | | import java.util.logging.Level; |
| | | |
| | | import org.opends.sdk.ErrorResultException; |
| | | import org.opends.sdk.ResultCode; |
| | | import org.opends.sdk.ResultFuture; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | import org.opends.sdk.requests.Requests; |
| | | import org.opends.sdk.responses.Responses; |
| | | import org.opends.sdk.responses.Result; |
| | | |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | | import com.sun.opends.sdk.util.AbstractFutureResult; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Abstract result future implementation. |
| | | * |
| | | * @param <S> |
| | | * The type of result returned by this future. |
| | | */ |
| | | public abstract class AbstractResultFutureImpl<R extends Result> |
| | | implements ResultFuture<R>, Runnable |
| | | abstract class AbstractResultFutureImpl<S extends Result> extends |
| | | AbstractFutureResult<S> implements FutureResult<S> |
| | | { |
| | | private final LDAPConnection connection; |
| | | |
| | | private final ResultHandler<? super R> handler; |
| | | |
| | | private final ExecutorService handlerExecutor; |
| | | |
| | | private final int messageID; |
| | | |
| | | // Use a semaphore instead of a lock because semaphores can be |
| | | // released by different thread to acquirer. |
| | | private final Semaphore invokerLock; |
| | | |
| | | private final CountDownLatch latch = new CountDownLatch(1); |
| | | |
| | | private volatile boolean isCancelled = false; |
| | | |
| | | private volatile R result = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new LDAP result future. |
| | | * |
| | | * @param messageID |
| | | * The request message ID. |
| | | * @param handler |
| | | * The result handler, maybe {@code null}. |
| | | * @param connection |
| | | * The client connection. |
| | | */ |
| | | AbstractResultFutureImpl(int messageID, |
| | | ResultHandler<? super R> handler, LDAPConnection connection, |
| | | ExecutorService handlerExecutor) |
| | | ResultHandler<? super S> handler, LDAPConnection connection) |
| | | { |
| | | super(handler); |
| | | this.messageID = messageID; |
| | | this.handler = handler; |
| | | this.connection = connection; |
| | | this.handlerExecutor = handlerExecutor; |
| | | if (handlerExecutor == null) |
| | | { |
| | | invokerLock = null; |
| | | } |
| | | else |
| | | { |
| | | invokerLock = new Semaphore(1); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public synchronized boolean cancel(boolean b) |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | protected final ErrorResultException handleCancelRequest() |
| | | { |
| | | if (!isDone()) |
| | | { |
| | | isCancelled = true; |
| | | connection.abandon(Requests.newAbandonRequest(messageID)); |
| | | latch.countDown(); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | |
| | | public R get() throws InterruptedException, ErrorResultException |
| | | { |
| | | latch.await(); |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | | |
| | | public R get(long timeout, TimeUnit unit) |
| | | throws InterruptedException, TimeoutException, |
| | | ErrorResultException |
| | | { |
| | | if (!latch.await(timeout, unit)) |
| | | { |
| | | throw new TimeoutException(); |
| | | } |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | | |
| | | public int getMessageID() |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final int getRequestID() |
| | | { |
| | | return messageID; |
| | | } |
| | | |
| | | |
| | | |
| | | public boolean isCancelled() |
| | | final void adaptErrorResult(Result result) |
| | | { |
| | | return isCancelled; |
| | | S errorResult = newErrorResult(result.getResultCode(), result |
| | | .getDiagnosticMessage(), result.getCause()); |
| | | setResultOrError(errorResult); |
| | | } |
| | | |
| | | |
| | | |
| | | public boolean isDone() |
| | | { |
| | | return latch.getCount() == 0; |
| | | } |
| | | |
| | | |
| | | |
| | | public void run() |
| | | final void setResultOrError(S result) |
| | | { |
| | | if (result.getResultCode().isExceptional()) |
| | | { |
| | | ErrorResultException e = ErrorResultException.wrap(result); |
| | | handler.handleErrorResult(e); |
| | | handleErrorResult(ErrorResultException.wrap(result)); |
| | | } |
| | | else |
| | | { |
| | | handler.handleResult(result); |
| | | handleResult(result); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | final void handleErrorResult(Result result) |
| | | { |
| | | R errorResult = newErrorResult(result.getResultCode(), result |
| | | .getDiagnosticMessage(), result.getCause()); |
| | | handleResult(errorResult); |
| | | } |
| | | |
| | | |
| | | |
| | | abstract R newErrorResult(ResultCode resultCode, |
| | | abstract S newErrorResult(ResultCode resultCode, |
| | | String diagnosticMessage, Throwable cause); |
| | | |
| | | |
| | | |
| | | final void handleResult(R result) |
| | | { |
| | | if (!isDone()) |
| | | { |
| | | this.result = result; |
| | | if (handler != null) |
| | | { |
| | | invokeHandler(this); |
| | | } |
| | | latch.countDown(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | final void invokeHandler(final Runnable runnable) |
| | | { |
| | | try |
| | | { |
| | | if (handlerExecutor == null) |
| | | { |
| | | runnable.run(); |
| | | } |
| | | else |
| | | { |
| | | invokerLock.acquire(); |
| | | |
| | | try |
| | | { |
| | | handlerExecutor.submit(new Runnable() |
| | | { |
| | | public void run() |
| | | { |
| | | try |
| | | { |
| | | runnable.run(); |
| | | } |
| | | finally |
| | | { |
| | | invokerLock.release(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | invokerLock.release(); |
| | | } |
| | | } |
| | | } |
| | | catch (InterruptedException e) |
| | | { |
| | | // Thread has been interrupted so give up. |
| | | if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING)) |
| | | { |
| | | StaticUtils.DEBUG_LOG.warning(String.format( |
| | | "Invoke thread interrupted: %s", StaticUtils |
| | | .getExceptionMessage(e))); |
| | | } |
| | | |
| | | // Reset interrupt status. |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private R get0() throws ErrorResultException |
| | | { |
| | | if (isCancelled()) |
| | | { |
| | | throw ErrorResultException.wrap(Responses |
| | | .newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)); |
| | | } |
| | | else if (result.getResultCode().isExceptional()) |
| | | { |
| | | throw ErrorResultException.wrap(result); |
| | | } |
| | | else |
| | | { |
| | | return result; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | | |
| | | import org.opends.sdk.ResultCode; |
| | | import org.opends.sdk.ResultFuture; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | import org.opends.sdk.requests.BindRequest; |
| | | import org.opends.sdk.responses.BindResult; |
| | |
| | | /** |
| | | * Bind result future implementation. |
| | | */ |
| | | public final class BindResultFutureImpl extends |
| | | final class BindResultFutureImpl extends |
| | | AbstractResultFutureImpl<BindResult> implements |
| | | ResultFuture<BindResult> |
| | | FutureResult<BindResult> |
| | | { |
| | | private final BindRequest request; |
| | | |
| | |
| | | |
| | | BindResultFutureImpl(int messageID, BindRequest request, |
| | | ResultHandler<? super BindResult> handler, |
| | | LDAPConnection connection, ExecutorService handlerExecutor) |
| | | LDAPConnection connection) |
| | | { |
| | | super(messageID, handler, connection, handlerExecutor); |
| | | super(messageID, handler, connection); |
| | | this.request = request; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | | |
| | | import org.opends.sdk.ResultCode; |
| | | import org.opends.sdk.ResultFuture; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | import org.opends.sdk.requests.CompareRequest; |
| | | import org.opends.sdk.responses.CompareResult; |
| | |
| | | /** |
| | | * Compare result future implementation. |
| | | */ |
| | | public final class CompareResultFutureImpl extends |
| | | final class CompareResultFutureImpl extends |
| | | AbstractResultFutureImpl<CompareResult> implements |
| | | ResultFuture<CompareResult> |
| | | FutureResult<CompareResult> |
| | | { |
| | | private final CompareRequest request; |
| | | |
| | |
| | | |
| | | CompareResultFutureImpl(int messageID, CompareRequest request, |
| | | ResultHandler<? super CompareResult> handler, |
| | | LDAPConnection connection, ExecutorService handlerExecutor) |
| | | LDAPConnection connection) |
| | | { |
| | | super(messageID, handler, connection, handlerExecutor); |
| | | super(messageID, handler, connection); |
| | | this.request = request; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | | |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.requests.ExtendedRequest; |
| | | import org.opends.sdk.responses.Result; |
| | |
| | | /** |
| | | * Extended result future implementation. |
| | | */ |
| | | public final class ExtendedResultFutureImpl<R extends Result> extends |
| | | AbstractResultFutureImpl<R> implements ResultFuture<R> |
| | | final class ExtendedResultFutureImpl<R extends Result> extends |
| | | AbstractResultFutureImpl<R> implements FutureResult<R> |
| | | { |
| | | private final ExtendedRequest<R> request; |
| | | |
| | | |
| | | |
| | | ExtendedResultFutureImpl(int messageID, ExtendedRequest<R> request, |
| | | ResultHandler<? super R> handler, |
| | | LDAPConnection connection, ExecutorService handlerExecutor) |
| | | ResultHandler<? super R> handler, LDAPConnection connection) |
| | | { |
| | | super(messageID, handler, connection, handlerExecutor); |
| | | super(messageID, handler, connection); |
| | | this.request = request; |
| | | } |
| | | |
| | |
| | | ResultFutureImpl future = (ResultFutureImpl) pendingRequest; |
| | | if (future.getRequest() instanceof AddRequest) |
| | | { |
| | | future.handleResult(result); |
| | | future.setResultOrError(result); |
| | | return; |
| | | } |
| | | } |
| | |
| | | .setDiagnosticMessage( |
| | | "An error occurred during SASL authentication") |
| | | .setCause(e); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | return; |
| | | } |
| | | } |
| | |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR) |
| | | .setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | pendingBindOrStartTLS = -1; |
| | | future.handleResult(result); |
| | | future.setResultOrError(result); |
| | | } |
| | | else |
| | | { |
| | |
| | | if (pendingRequest instanceof CompareResultFutureImpl) |
| | | { |
| | | CompareResultFutureImpl future = (CompareResultFutureImpl) pendingRequest; |
| | | future.handleResult(result); |
| | | future.setResultOrError(result); |
| | | } |
| | | else |
| | | { |
| | |
| | | ResultFutureImpl future = (ResultFutureImpl) pendingRequest; |
| | | if (future.getRequest() instanceof DeleteRequest) |
| | | { |
| | | future.handleResult(result); |
| | | future.setResultOrError(result); |
| | | return; |
| | | } |
| | | } |
| | |
| | | ResultCode.CLIENT_SIDE_DECODING_ERROR) |
| | | .setDiagnosticMessage(de.getLocalizedMessage()).setCause( |
| | | de); |
| | | extendedFuture.handleErrorResult(errorResult); |
| | | extendedFuture.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | else |
| | |
| | | ResultFutureImpl future = (ResultFutureImpl) pendingRequest; |
| | | if (future.getRequest() instanceof ModifyDNRequest) |
| | | { |
| | | future.handleResult(result); |
| | | future.setResultOrError(result); |
| | | return; |
| | | } |
| | | } |
| | |
| | | ResultFutureImpl future = (ResultFutureImpl) pendingRequest; |
| | | if (future.getRequest() instanceof ModifyRequest) |
| | | { |
| | | future.handleResult(result); |
| | | future.setResultOrError(result); |
| | | return; |
| | | } |
| | | } |
| | |
| | | if (pendingRequest instanceof SearchResultFutureImpl) |
| | | { |
| | | ((SearchResultFutureImpl) pendingRequest) |
| | | .handleResult(result); |
| | | .setResultOrError(result); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | private final Object writeLock = new Object(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new LDAP connection. |
| | | * |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Result> add(AddRequest request, |
| | | public FutureResult<Result> add(AddRequest request, |
| | | ResultHandler<Result> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | ResultFutureImpl future = new ResultFutureImpl(messageID, request, |
| | | handler, this, connFactory.getHandlerInvokers()); |
| | | handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newResult( |
| | | future.setResultOrError(Responses.newResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<BindResult> bind(BindRequest request, |
| | | public FutureResult<BindResult> bind(BindRequest request, |
| | | ResultHandler<? super BindResult> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | BindResultFutureImpl future = new BindResultFutureImpl(messageID, |
| | | request, handler, this, connFactory.getHandlerInvokers()); |
| | | request, handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newBindResult( |
| | | future.setResultOrError(Responses.newBindResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | | } |
| | | if (!pendingRequests.isEmpty()) |
| | | { |
| | | future.handleResult(Responses.newBindResult( |
| | | future.setResultOrError(Responses.newBindResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "There are other operations pending on this connection")); |
| | | return future; |
| | |
| | | .setDiagnosticMessage( |
| | | "An error occurred during SASL authentication") |
| | | .setCause(e); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | return future; |
| | | } |
| | | } |
| | |
| | | else |
| | | { |
| | | pendingRequests.remove(messageID); |
| | | future.handleResult(Responses.newBindResult( |
| | | future.setResultOrError(Responses.newBindResult( |
| | | ResultCode.CLIENT_SIDE_AUTH_UNKNOWN) |
| | | .setDiagnosticMessage("Auth type not supported")); |
| | | } |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<CompareResult> compare(CompareRequest request, |
| | | public FutureResult<CompareResult> compare(CompareRequest request, |
| | | ResultHandler<? super CompareResult> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | CompareResultFutureImpl future = new CompareResultFutureImpl( |
| | | messageID, request, handler, this, connFactory |
| | | .getHandlerInvokers()); |
| | | messageID, request, handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newCompareResult( |
| | | future.setResultOrError(Responses.newCompareResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Result> delete(DeleteRequest request, |
| | | public FutureResult<Result> delete(DeleteRequest request, |
| | | ResultHandler<Result> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | ResultFutureImpl future = new ResultFutureImpl(messageID, request, |
| | | handler, this, connFactory.getHandlerInvokers()); |
| | | handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newResult( |
| | | future.setResultOrError(Responses.newResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public <R extends Result> ResultFuture<R> extendedRequest( |
| | | public <R extends Result> FutureResult<R> extendedRequest( |
| | | ExtendedRequest<R> request, ResultHandler<? super R> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | ExtendedResultFutureImpl<R> future = new ExtendedResultFutureImpl<R>( |
| | | messageID, request, handler, this, connFactory |
| | | .getHandlerInvokers()); |
| | | messageID, request, handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(request.getExtendedOperation() |
| | | future.setResultOrError(request.getExtendedOperation() |
| | | .decodeResponse(ResultCode.OPERATIONS_ERROR, "", |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | { |
| | | if (!pendingRequests.isEmpty()) |
| | | { |
| | | future.handleResult(request.getExtendedOperation() |
| | | future.setResultOrError(request.getExtendedOperation() |
| | | .decodeResponse(ResultCode.OPERATIONS_ERROR, "", |
| | | "There are pending operations on this connection")); |
| | | return future; |
| | | } |
| | | if (isTLSEnabled()) |
| | | { |
| | | future.handleResult(request.getExtendedOperation() |
| | | future.setResultOrError(request.getExtendedOperation() |
| | | .decodeResponse(ResultCode.OPERATIONS_ERROR, "", |
| | | "This connection is already TLS enabled")); |
| | | } |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Result> modify(ModifyRequest request, |
| | | public FutureResult<Result> modify(ModifyRequest request, |
| | | ResultHandler<Result> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | ResultFutureImpl future = new ResultFutureImpl(messageID, request, |
| | | handler, this, connFactory.getHandlerInvokers()); |
| | | handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newResult( |
| | | future.setResultOrError(Responses.newResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Result> modifyDN(ModifyDNRequest request, |
| | | public FutureResult<Result> modifyDN(ModifyDNRequest request, |
| | | ResultHandler<Result> handler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | ResultFutureImpl future = new ResultFutureImpl(messageID, request, |
| | | handler, this, connFactory.getHandlerInvokers()); |
| | | handler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newResult( |
| | | future.setResultOrError(Responses.newResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Result> search(SearchRequest request, |
| | | public FutureResult<Result> search(SearchRequest request, |
| | | ResultHandler<Result> resultHandler, |
| | | SearchResultHandler searchResulthandler) |
| | | { |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | SearchResultFutureImpl future = new SearchResultFutureImpl( |
| | | messageID, request, resultHandler, searchResulthandler, this, |
| | | connFactory.getHandlerInvokers()); |
| | | messageID, request, resultHandler, searchResulthandler, this); |
| | | ASN1StreamWriter asn1Writer = connFactory |
| | | .getASN1Writer(streamWriter); |
| | | |
| | |
| | | { |
| | | if (connectionInvalidReason != null) |
| | | { |
| | | future.handleErrorResult(connectionInvalidReason); |
| | | future.adaptErrorResult(connectionInvalidReason); |
| | | return future; |
| | | } |
| | | if (pendingBindOrStartTLS > 0) |
| | | { |
| | | future.handleResult(Responses.newResult( |
| | | future.setResultOrError(Responses.newResult( |
| | | ResultCode.OPERATIONS_ERROR).setDiagnosticMessage( |
| | | "Bind or Start TLS operation in progress")); |
| | | return future; |
| | |
| | | Result errorResult = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e); |
| | | connectionErrorOccurred(errorResult); |
| | | future.handleErrorResult(errorResult); |
| | | future.adaptErrorResult(errorResult); |
| | | } |
| | | } |
| | | } |
| | |
| | | .getASN1Writer(streamWriter); |
| | | int messageID = nextMsgID.getAndIncrement(); |
| | | AbandonRequest abandon = Requests.newAbandonRequest(future |
| | | .getMessageID()); |
| | | .getRequestID()); |
| | | try |
| | | { |
| | | LDAPEncoder.encodeAbandonRequest(asn1Writer, messageID, |
| | |
| | | } |
| | | } |
| | | |
| | | future.handleErrorResult(reason); |
| | | future.adaptErrorResult(reason); |
| | | } |
| | | pendingRequests.clear(); |
| | | |
| | |
| | | } |
| | | catch (ErrorResultException e) |
| | | { |
| | | future.handleErrorResult(e.getResult()); |
| | | future.adaptErrorResult(e.getResult()); |
| | | return; |
| | | } |
| | | } |
| | | pendingBindOrStartTLS = -1; |
| | | } |
| | | |
| | | future.handleResult(decodedResponse); |
| | | future.setResultOrError(decodedResponse); |
| | | } |
| | | |
| | | |
| | |
| | | ResultCode.CLIENT_SIDE_DECODING_ERROR).setDiagnosticMessage( |
| | | "LDAP response message did not match request"); |
| | | |
| | | pendingRequest.handleErrorResult(errorResult); |
| | | pendingRequest.adaptErrorResult(errorResult); |
| | | connectionErrorOccurred(errorResult); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | private static class FailedImpl implements |
| | | ConnectionFuture<AsynchronousConnection> |
| | | FutureResult<AsynchronousConnection> |
| | | { |
| | | private volatile ErrorResultException exception; |
| | | |
| | |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | public int getRequestID() |
| | | { |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private class ConnectionFutureImpl implements |
| | | ConnectionFuture<AsynchronousConnection>, |
| | | private class ResultFutureImpl implements |
| | | FutureResult<AsynchronousConnection>, |
| | | com.sun.grizzly.CompletionHandler<com.sun.grizzly.Connection>, |
| | | ResultHandler<Result> |
| | | { |
| | |
| | | |
| | | private volatile Future<com.sun.grizzly.Connection> connectFuture; |
| | | |
| | | private volatile ResultFuture<?> sslFuture; |
| | | private volatile FutureResult<?> sslFuture; |
| | | |
| | | private final CountDownLatch latch = new CountDownLatch(1); |
| | | |
| | | private final ConnectionResultHandler<? super AsynchronousConnection> handler; |
| | | private final ResultHandler<? super AsynchronousConnection> handler; |
| | | |
| | | private boolean cancelled; |
| | | |
| | | |
| | | |
| | | private ConnectionFutureImpl( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | private ResultFutureImpl( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | this.handler = handler; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public int getRequestID() |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(this.connection); |
| | | handler.handleResult(this.connection); |
| | | } |
| | | } |
| | | catch (CancellationException ce) |
| | |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnectionError(exception); |
| | | handler.handleErrorResult(exception); |
| | | } |
| | | } |
| | | } |
| | |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(this.connection); |
| | | handler.handleResult(this.connection); |
| | | } |
| | | } |
| | | } |
| | |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnectionError(exception); |
| | | handler.handleErrorResult(exception); |
| | | } |
| | | } |
| | | |
| | |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(connection); |
| | | handler.handleResult(connection); |
| | | } |
| | | } |
| | | |
| | |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnectionError(exception); |
| | | handler.handleErrorResult(exception); |
| | | } |
| | | } |
| | | } |
| | |
| | | if (TCP_NIO_TRANSPORT == null) |
| | | { |
| | | // Create a default transport using the Grizzly framework. |
| | | // |
| | | TCP_NIO_TRANSPORT = TransportFactory.getInstance() |
| | | .createTCPTransport(); |
| | | try |
| | |
| | | @Override |
| | | public void run() |
| | | { |
| | | ShutdownTCPNIOTransport(); |
| | | } |
| | | |
| | | }); |
| | | } |
| | | return TCP_NIO_TRANSPORT; |
| | | } |
| | | |
| | | |
| | | |
| | | private synchronized static void ShutdownTCPNIOTransport() |
| | | { |
| | | if (TCP_NIO_TRANSPORT != null) |
| | | { |
| | | try |
| | | { |
| | | TCP_NIO_TRANSPORT.stop(); |
| | |
| | | // Ignore. |
| | | } |
| | | |
| | | try |
| | | { |
| | | TCP_NIO_TRANSPORT.getWorkerThreadPool().shutdown(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // Ignore. |
| | | } |
| | | } |
| | | // try |
| | | // { |
| | | // TCP_NIO_TRANSPORT.getWorkerThreadPool().shutdown(); |
| | | // } |
| | | // catch (Exception e) |
| | | // { |
| | | // // Ignore. |
| | | // } |
| | | |
| | | }); |
| | | TCP_NIO_TRANSPORT = null; |
| | | } |
| | | return TCP_NIO_TRANSPORT; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConnectionFuture<AsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | public FutureResult<AsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | ConnectionFutureImpl future = new ConnectionFutureImpl(handler); |
| | | ResultFutureImpl future = new ResultFutureImpl(handler); |
| | | |
| | | try |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | | |
| | | import org.opends.sdk.ResultCode; |
| | | import org.opends.sdk.ResultFuture; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | import org.opends.sdk.requests.Request; |
| | | import org.opends.sdk.responses.Responses; |
| | |
| | | * Result future implementation. |
| | | */ |
| | | public final class ResultFutureImpl extends |
| | | AbstractResultFutureImpl<Result> implements ResultFuture<Result> |
| | | AbstractResultFutureImpl<Result> implements FutureResult<Result> |
| | | { |
| | | private final Request request; |
| | | |
| | | |
| | | |
| | | ResultFutureImpl(int messageID, Request request, |
| | | ResultHandler<Result> handler, LDAPConnection connection, |
| | | ExecutorService handlerExecutor) |
| | | ResultHandler<Result> handler, LDAPConnection connection) |
| | | { |
| | | super(messageID, handler, connection, handlerExecutor); |
| | | super(messageID, handler, connection); |
| | | this.request = request; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.ExecutorService; |
| | | |
| | | import org.opends.sdk.ResultCode; |
| | | import org.opends.sdk.ResultFuture; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | import org.opends.sdk.SearchResultHandler; |
| | | import org.opends.sdk.requests.SearchRequest; |
| | |
| | | /** |
| | | * Search result future implementation. |
| | | */ |
| | | public final class SearchResultFutureImpl extends |
| | | AbstractResultFutureImpl<Result> implements ResultFuture<Result> |
| | | final class SearchResultFutureImpl extends |
| | | AbstractResultFutureImpl<Result> implements FutureResult<Result> |
| | | { |
| | | |
| | | private final SearchResultHandler searchResultHandler; |
| | |
| | | |
| | | SearchResultFutureImpl(int messageID, SearchRequest request, |
| | | ResultHandler<Result> resultHandler, |
| | | SearchResultHandler searchResultHandler, |
| | | LDAPConnection connection, ExecutorService handlerExecutor) |
| | | SearchResultHandler searchResultHandler, LDAPConnection connection) |
| | | { |
| | | super(messageID, resultHandler, connection, handlerExecutor); |
| | | super(messageID, resultHandler, connection); |
| | | this.request = request; |
| | | this.searchResultHandler = searchResultHandler; |
| | | } |
| | | |
| | | |
| | | |
| | | void handleSearchResultEntry( |
| | | final SearchResultEntry entry) |
| | | void handleSearchResultEntry(SearchResultEntry entry) |
| | | { |
| | | // FIXME: there's a potential race condition here - the future could |
| | | // get cancelled between the isDone() call and the handler |
| | | // invocation. We'd need to add support for intermediate handlers in |
| | | // the synchronizer. |
| | | if (!isDone()) |
| | | { |
| | | if (searchResultHandler != null) |
| | | { |
| | | invokeHandler(new Runnable() |
| | | { |
| | | public void run() |
| | | { |
| | | searchResultHandler.handleEntry(entry); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | void handleSearchResultReference( |
| | | final SearchResultReference reference) |
| | | void handleSearchResultReference(SearchResultReference reference) |
| | | { |
| | | // FIXME: there's a potential race condition here - the future could |
| | | // get cancelled between the isDone() call and the handler |
| | | // invocation. We'd need to add support for intermediate handlers in |
| | | // the synchronizer. |
| | | if (!isDone()) |
| | | { |
| | | if (searchResultHandler != null) |
| | | { |
| | | invokeHandler(new Runnable() |
| | | { |
| | | public void run() |
| | | { |
| | | searchResultHandler.handleReference(reference); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConnectionFuture<? extends AsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | public FutureResult<? extends AsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | return connFactory.getAsynchronousConnection(handler); |
| | | } |
| | |
| | | public static void main(String[] args) |
| | | { |
| | | int retCode = mainCompare(args, System.in, System.out, System.err); |
| | | |
| | | if (retCode != 0) |
| | | { |
| | | System.exit(filterExitCode(retCode)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | public static void main(String[] args) |
| | | { |
| | | int retCode = mainModify(args, System.in, System.out, System.err); |
| | | |
| | | if (retCode != 0) |
| | | { |
| | | System.exit(filterExitCode(retCode)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | public static void main(String[] args) |
| | | { |
| | | int retCode = mainPasswordModify(args, System.in, System.out, System.err); |
| | | |
| | | if (retCode != 0) |
| | | { |
| | | System.exit(filterExitCode(retCode)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | |
| | | import static com.sun.opends.sdk.messages.Messages.*; |
| | | import static com.sun.opends.sdk.tools.ToolConstants.*; |
| | | import static com.sun.opends.sdk.tools.Utils.*; |
| | | |
| | | import java.io.*; |
| | | import java.util.ArrayList; |
| | |
| | | { |
| | | int retCode = mainSearch(args, false, System.in, System.out, |
| | | System.err); |
| | | |
| | | if (retCode != 0) |
| | | { |
| | | System.exit(Utils.filterExitCode(retCode)); |
| | | } |
| | | System.exit(filterExitCode(retCode)); |
| | | } |
| | | |
| | | |
| | |
| | | public static void main(String[] args) |
| | | { |
| | | int retCode = mainModRate(args, System.in, System.out, System.err); |
| | | |
| | | if (retCode != 0) |
| | | { |
| | | System.exit(filterExitCode(retCode)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<?> performOperation( |
| | | public FutureResult<?> performOperation( |
| | | AsynchronousConnection connection, |
| | | ResultHandler<Result> handler, DataSource[] dataSources) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | public abstract ResultFuture<?> performOperation( |
| | | public abstract FutureResult<?> performOperation( |
| | | AsynchronousConnection connection, R handler, |
| | | DataSource[] dataSources); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | ResultFuture<?> future; |
| | | FutureResult<?> future; |
| | | AsynchronousConnection connection; |
| | | R handler; |
| | | |
| | |
| | | { |
| | | int retCode = mainSearchRate(args, System.in, System.out, |
| | | System.err); |
| | | |
| | | if (retCode != 0) |
| | | { |
| | | System.exit(filterExitCode(retCode)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<?> performOperation( |
| | | public FutureResult<?> performOperation( |
| | | AsynchronousConnection connection, |
| | | SearchStatsHandler handler, DataSource[] dataSources) |
| | | { |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package com.sun.opends.sdk.util; |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.TimeoutException; |
| | | import java.util.concurrent.locks.AbstractQueuedSynchronizer; |
| | | |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.responses.Responses; |
| | | import org.opends.sdk.responses.Result; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class provides a skeletal implementation of the {@code |
| | | * FutureResult} interface, to minimize the effort required to implement |
| | | * this interface. |
| | | * <p> |
| | | * This {@code FutureResult} implementation provides the following |
| | | * features: |
| | | * <ul> |
| | | * <li>The {@link #get} methods throw {@link ErrorResultException}s |
| | | * instead of the more generic {@code ExecutionException}s. |
| | | * <li>The {@link #get} methods never throw {@code |
| | | * CancellationException} since requests in this SDK can usually be |
| | | * cancelled via other external means (e.g. the {@code Cancel} extended |
| | | * operation) for which there are well defined error results. Therefore |
| | | * cancellation is always signalled by throwing a |
| | | * {@link CancelledResultException} in order to be consistent with other |
| | | * error results. |
| | | * <li>A {@link ResultHandler} can be provided to the constructor. The |
| | | * result handler will be invoked immediately after the result or error |
| | | * is received but before threads blocked on {@link #get} are released. |
| | | * More specifically, result handler invocation <i>happens-before</i> a |
| | | * call to {@link #get}. <b>NOTE:</b> a result handler which attempts to |
| | | * call {@link #get} will deadlock. |
| | | * <li>Sub-classes may choose to implement specific cancellation cleanup |
| | | * by implementing the {@link #handleCancelRequest} method. |
| | | * </ul> |
| | | * |
| | | * @param <M> |
| | | * The type of result returned by this completion future. |
| | | */ |
| | | public abstract class AbstractFutureResult<M> implements |
| | | FutureResult<M>, ResultHandler<M> |
| | | { |
| | | @SuppressWarnings("serial") |
| | | private final class Sync extends AbstractQueuedSynchronizer |
| | | { |
| | | // State value representing the initial state before a result has |
| | | // been received. |
| | | private static final int WAITING = 0; |
| | | |
| | | // State value representing that a result has been received and is |
| | | // being processed. |
| | | private static final int PENDING = 1; |
| | | |
| | | // State value representing that the request was cancelled. |
| | | private static final int CANCELLED = 2; |
| | | |
| | | // State value representing that the request has failed. |
| | | private static final int FAIL = 3; |
| | | |
| | | // State value representing that the request has succeeded. |
| | | private static final int SUCCESS = 4; |
| | | |
| | | // These do not need to be volatile since their values are published |
| | | // by updating the state after they are set and reading the state |
| | | // immediately before they are read. |
| | | private ErrorResultException errorResult = null; |
| | | |
| | | private M result = null; |
| | | |
| | | |
| | | |
| | | private M get0() throws ErrorResultException |
| | | { |
| | | if (errorResult != null) |
| | | { |
| | | // State must be FAILED or CANCELLED. |
| | | throw errorResult; |
| | | } |
| | | else |
| | | { |
| | | // State must be SUCCESS. |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private boolean setStatePending() |
| | | { |
| | | for (;;) |
| | | { |
| | | final int s = getState(); |
| | | if (s != WAITING) |
| | | { |
| | | return false; |
| | | } |
| | | if (compareAndSetState(s, PENDING)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Allow all threads to acquire if future has completed. |
| | | */ |
| | | protected int tryAcquireShared(int ignore) |
| | | { |
| | | return innerIsDone() ? 1 : -1; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Signal that the future has completed and threads waiting on get() |
| | | * can be released. |
| | | */ |
| | | protected boolean tryReleaseShared(int finalState) |
| | | { |
| | | // Ensures that errorResult/result is published. |
| | | setState(finalState); |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | boolean innerCancel(boolean mayInterruptIfRunning) |
| | | { |
| | | if (!setStatePending()) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // Perform implementation defined cancellation. |
| | | ErrorResultException errorResult = handleCancelRequest(mayInterruptIfRunning); |
| | | if (errorResult == null) |
| | | { |
| | | final Result result = Responses |
| | | .newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED); |
| | | errorResult = ErrorResultException.wrap(result); |
| | | } |
| | | this.errorResult = errorResult; |
| | | |
| | | try |
| | | { |
| | | // Invoke error result completion handler. |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(errorResult); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | releaseShared(CANCELLED); // Publishes errorResult. |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | M innerGet() throws ErrorResultException, InterruptedException |
| | | { |
| | | acquireSharedInterruptibly(0); |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | | |
| | | M innerGet(long nanosTimeout) throws ErrorResultException, |
| | | TimeoutException, InterruptedException |
| | | { |
| | | if (!tryAcquireSharedNanos(0, nanosTimeout)) |
| | | { |
| | | throw new TimeoutException(); |
| | | } |
| | | else |
| | | { |
| | | return get0(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | boolean innerIsCancelled() |
| | | { |
| | | return getState() == CANCELLED; |
| | | } |
| | | |
| | | |
| | | |
| | | boolean innerIsDone() |
| | | { |
| | | return getState() > 1; |
| | | } |
| | | |
| | | |
| | | |
| | | void innerSetErrorResult(ErrorResultException errorResult) |
| | | { |
| | | if (setStatePending()) |
| | | { |
| | | this.errorResult = errorResult; |
| | | |
| | | try |
| | | { |
| | | // Invoke error result completion handler. |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(errorResult); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | releaseShared(FAIL); // Publishes errorResult. |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | void innerSetResult(M result) |
| | | { |
| | | if (setStatePending()) |
| | | { |
| | | this.result = result; |
| | | |
| | | try |
| | | { |
| | | // Invoke result completion handler. |
| | | if (handler != null) |
| | | { |
| | | handler.handleResult(result); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | releaseShared(SUCCESS); // Publishes result. |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private final Sync sync = new Sync(); |
| | | |
| | | private final ResultHandler<? super M> handler; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new abstract future result with the provided result |
| | | * handler. |
| | | * |
| | | * @param handler |
| | | * A result handler which will be forwarded the result or |
| | | * error when it arrives. |
| | | */ |
| | | protected AbstractFutureResult(ResultHandler<? super M> handler) |
| | | { |
| | | this.handler = handler; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean cancel(boolean mayInterruptIfRunning) |
| | | { |
| | | return sync.innerCancel(mayInterruptIfRunning); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final M get() throws ErrorResultException, |
| | | InterruptedException |
| | | { |
| | | return sync.innerGet(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final M get(long timeout, TimeUnit unit) |
| | | throws ErrorResultException, TimeoutException, |
| | | InterruptedException |
| | | { |
| | | return sync.innerGet(unit.toNanos(timeout)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the error result associated with this future. If ({@code |
| | | * isDone() == true}) then the error result will be ignored, otherwise |
| | | * the result handler will be invoked if one was provided and, on |
| | | * return, any threads waiting on {@link #get} will be released and |
| | | * the provided error result will be thrown. |
| | | * |
| | | * @param errorResult |
| | | * The error result. |
| | | */ |
| | | public final void handleErrorResult(ErrorResultException errorResult) |
| | | { |
| | | sync.innerSetErrorResult(errorResult); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the result associated with this future. If ({@code isDone() == |
| | | * true}) then the result will be ignored, otherwise the result |
| | | * handler will be invoked if one was provided and, on return, any |
| | | * threads waiting on {@link #get} will be released and the provided |
| | | * result will be returned. |
| | | * |
| | | * @param result |
| | | * The result. |
| | | */ |
| | | public final void handleResult(M result) |
| | | { |
| | | sync.innerSetResult(result); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean isCancelled() |
| | | { |
| | | return sync.innerIsCancelled(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean isDone() |
| | | { |
| | | return sync.innerIsDone(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Invoked when {@link #cancel} is called and {@code isDone() == |
| | | * false} and immediately before any threads waiting on {@link #get} |
| | | * are released. Implementations may choose to return a custom error |
| | | * result if needed or return {@code null} if the following default |
| | | * error result is acceptable: |
| | | * |
| | | * <pre> |
| | | * Result result = Responses |
| | | * .newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED); |
| | | * </pre> |
| | | * |
| | | * In addition, implementations may perform other cleanup, for |
| | | * example, by issuing an LDAP abandon request. The default |
| | | * implementation is to do nothing. |
| | | * |
| | | * @param mayInterruptIfRunning |
| | | * {@code true} if the thread executing executing the |
| | | * response handler should be interrupted; otherwise, |
| | | * in-progress response handlers are allowed to complete. |
| | | * @return The custom error result, or {@code null} if the default is |
| | | * acceptable. |
| | | */ |
| | | protected ErrorResultException handleCancelRequest( |
| | | boolean mayInterruptIfRunning) |
| | | { |
| | | // Do nothing by default. |
| | | return null; |
| | | } |
| | | |
| | | } |
| File was renamed from sdk/src/com/sun/opends/sdk/util/ResultTransformer.java |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.CancellationException; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.TimeoutException; |
| | | |
| | | import org.opends.sdk.ErrorResultException; |
| | | import org.opends.sdk.ResultFuture; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A base class which can be used to transform the result of an inner |
| | | * asynchronous request to another result type. |
| | | * An implementation of the {@code FutureResult} interface which |
| | | * transforms the result of an asynchronous operation from one type to |
| | | * another. The implementation ensures that the transformed is computed |
| | | * only once. |
| | | * |
| | | * @param <M> |
| | | * The type of the inner result. |
| | | * @param <N> |
| | | * The type of the outer result. |
| | | */ |
| | | public abstract class ResultTransformer<M, N> implements |
| | | ResultFuture<N>, ResultHandler<M> |
| | | public abstract class FutureResultTransformer<M, N> implements |
| | | FutureResult<N>, ResultHandler<M> |
| | | { |
| | | |
| | | private final ResultHandler<? super N> handler; |
| | | |
| | | private volatile ResultFuture<M> future = null; |
| | | private volatile FutureResult<M> future = null; |
| | | |
| | | // These do not need to be volatile since the future acts as a memory |
| | | // barrier. |
| | | private N transformedResult = null; |
| | | |
| | | |
| | | /** |
| | | * Sets the inner future for this result transformer. This must be |
| | | * done before this future is published. |
| | | * |
| | | * @param future |
| | | * The inner future. |
| | | */ |
| | | public final void setResultFuture(ResultFuture<M> future) |
| | | { |
| | | this.future = future; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Transforms the inner result to an outer result, possibly throwing |
| | | * an {@code ErrorResultException} if the transformation fails for |
| | | * some reason. |
| | | * |
| | | * @param result |
| | | * The inner result. |
| | | * @return The outer result. |
| | | * @throws ErrorResultException |
| | | * If the transformation fails for some reason. |
| | | */ |
| | | protected abstract N transformResult(M result) |
| | | throws ErrorResultException; |
| | | private ErrorResultException transformedErrorResult = null; |
| | | |
| | | |
| | | |
| | |
| | | * @param handler |
| | | * The outer result handler. |
| | | */ |
| | | protected ResultTransformer(ResultHandler<? super N> handler) |
| | | protected FutureResultTransformer(ResultHandler<? super N> handler) |
| | | { |
| | | this.handler = handler; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void handleErrorResult(ErrorResultException error) |
| | | { |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(error); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void handleResult(M result) |
| | | { |
| | | if (handler != null) |
| | | { |
| | | try |
| | | { |
| | | handler.handleResult(transformResult(result)); |
| | | } |
| | | catch (ErrorResultException e) |
| | | { |
| | | handler.handleErrorResult(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean cancel(boolean mayInterruptIfRunning) |
| | | { |
| | | return future.cancel(mayInterruptIfRunning); |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public final N get() throws ErrorResultException, |
| | | CancellationException, InterruptedException |
| | | InterruptedException |
| | | { |
| | | return transformResult(future.get()); |
| | | future.get(); |
| | | |
| | | // The handlers are guaranteed to have been invoked at this point. |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public final N get(long timeout, TimeUnit unit) |
| | | throws ErrorResultException, TimeoutException, |
| | | CancellationException, InterruptedException |
| | | InterruptedException |
| | | { |
| | | return transformResult(future.get(timeout, unit)); |
| | | future.get(timeout, unit); |
| | | |
| | | // The handlers are guaranteed to have been invoked at this point. |
| | | return get0(); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final int getMessageID() |
| | | public final int getRequestID() |
| | | { |
| | | return future.getMessageID(); |
| | | return future.getRequestID(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void handleErrorResult(ErrorResultException error) |
| | | { |
| | | transformedErrorResult = transformErrorResult(error); |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(transformedErrorResult); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void handleResult(M result) |
| | | { |
| | | try |
| | | { |
| | | transformedResult = transformResult(result); |
| | | if (handler != null) |
| | | { |
| | | handler.handleResult(transformedResult); |
| | | } |
| | | } |
| | | catch (final ErrorResultException e) |
| | | { |
| | | transformedErrorResult = e; |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(transformedErrorResult); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | return future.isDone(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the inner future for this result transformer. This must be |
| | | * done before this future is published. |
| | | * |
| | | * @param future |
| | | * The inner future. |
| | | */ |
| | | public final void setFutureResult(FutureResult<M> future) |
| | | { |
| | | this.future = future; |
| | | } |
| | | |
| | | |
| | | |
| | | private N get0() throws ErrorResultException |
| | | { |
| | | if (transformedErrorResult != null) |
| | | { |
| | | throw transformedErrorResult; |
| | | } |
| | | else |
| | | { |
| | | return transformedResult; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Transforms the inner error result to an outer error result. The |
| | | * default implementation is to return the inner error result. |
| | | * |
| | | * @param errorResult |
| | | * The inner error result. |
| | | * @return The outer error result. |
| | | */ |
| | | protected ErrorResultException transformErrorResult( |
| | | ErrorResultException errorResult) |
| | | { |
| | | return errorResult; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Transforms the inner result to an outer result, possibly throwing |
| | | * an {@code ErrorResultException} if the transformation fails for |
| | | * some reason. |
| | | * |
| | | * @param result |
| | | * The inner result. |
| | | * @return The outer result. |
| | | * @throws ErrorResultException |
| | | * If the transformation fails for some reason. |
| | | */ |
| | | protected abstract N transformResult(M result) |
| | | throws ErrorResultException; |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE |
| | | * or https://OpenDS.dev.java.net/OpenDS.LICENSE. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package com.sun.opends.sdk.util; |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.TimeoutException; |
| | | |
| | | import org.opends.sdk.ErrorResultException; |
| | | import org.opends.sdk.FutureResult; |
| | | import org.opends.sdk.ResultHandler; |
| | | |
| | | |
| | | |
| | | /** |
| | | * An implementation of the {@code FutureResult} interface which can be |
| | | * used to combine a sequence of two asynchronous operations into a |
| | | * single future result. Implementations should override the methods |
| | | * {@link #chainResult} and {@link #chainErrorResult} in order to define |
| | | * the second asynchronous operation. |
| | | * |
| | | * @param <M> |
| | | * The type of the inner result. |
| | | * @param <N> |
| | | * The type of the outer result. |
| | | */ |
| | | public abstract class RecursiveFutureResult<M, N> implements |
| | | FutureResult<N>, ResultHandler<M> |
| | | { |
| | | private final class FutureResultImpl extends AbstractFutureResult<N> |
| | | { |
| | | private FutureResultImpl(ResultHandler<? super N> handler) |
| | | { |
| | | super(handler); |
| | | } |
| | | |
| | | |
| | | |
| | | public int getRequestID() |
| | | { |
| | | return innerFuture.getRequestID(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | protected ErrorResultException handleCancelRequest( |
| | | boolean mayInterruptIfRunning) |
| | | { |
| | | innerFuture.cancel(mayInterruptIfRunning); |
| | | if (outerFuture != null) |
| | | { |
| | | outerFuture.cancel(mayInterruptIfRunning); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | private final FutureResultImpl impl; |
| | | |
| | | private volatile FutureResult<M> innerFuture = null; |
| | | |
| | | // This does not need to be volatile since the inner future acts as a |
| | | // memory barrier. |
| | | private FutureResult<N> outerFuture = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new asynchronous result chain which will chain an outer |
| | | * asynchronous request once the inner asynchronous request completes. |
| | | * |
| | | * @param handler |
| | | * The outer result handler. |
| | | */ |
| | | protected RecursiveFutureResult(ResultHandler<? super N> handler) |
| | | { |
| | | this.impl = new FutureResultImpl(handler); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean cancel(boolean mayInterruptIfRunning) |
| | | { |
| | | return impl.cancel(mayInterruptIfRunning); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final N get() throws ErrorResultException, |
| | | InterruptedException |
| | | { |
| | | return impl.get(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final N get(long timeout, TimeUnit unit) |
| | | throws ErrorResultException, TimeoutException, |
| | | InterruptedException |
| | | { |
| | | return impl.get(timeout, unit); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final int getRequestID() |
| | | { |
| | | return impl.getRequestID(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void handleErrorResult(ErrorResultException error) |
| | | { |
| | | try |
| | | { |
| | | outerFuture = chainErrorResult(error, impl); |
| | | } |
| | | catch (final ErrorResultException e) |
| | | { |
| | | impl.handleErrorResult(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final void handleResult(M result) |
| | | { |
| | | try |
| | | { |
| | | outerFuture = chainResult(result, impl); |
| | | } |
| | | catch (final ErrorResultException e) |
| | | { |
| | | impl.handleErrorResult(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean isCancelled() |
| | | { |
| | | return impl.isCancelled(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public final boolean isDone() |
| | | { |
| | | return impl.isDone(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the inner future for this result chain. This must be done |
| | | * before this future is published. |
| | | * |
| | | * @param future |
| | | * The inner future. |
| | | */ |
| | | public final void setFutureResult(FutureResult<M> future) |
| | | { |
| | | this.innerFuture = future; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Invokes the outer request based on the error result of the inner |
| | | * request and returns a future representing the result of the outer |
| | | * request. |
| | | * <p> |
| | | * The default implementation is to terminate further processing by |
| | | * re-throwing the inner error result. |
| | | * |
| | | * @param innerError |
| | | * The error result of the inner request. |
| | | * @param handler |
| | | * The result handler to be used for the outer request. |
| | | * @return A future representing the result of the outer request. |
| | | * @throws ErrorResultException |
| | | * If the outer request could not be invoked and processing |
| | | * should terminate. |
| | | */ |
| | | protected FutureResult<N> chainErrorResult( |
| | | ErrorResultException innerError, ResultHandler<? super N> handler) |
| | | throws ErrorResultException |
| | | { |
| | | throw innerError; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Invokes the outer request based on the result of the inner request |
| | | * and returns a future representing the result of the outer request. |
| | | * |
| | | * @param innerResult |
| | | * The result of the inner request. |
| | | * @param handler |
| | | * The result handler to be used for the outer request. |
| | | * @return A future representing the result of the outer request. |
| | | * @throws ErrorResultException |
| | | * If the outer request could not be invoked and processing |
| | | * should terminate. |
| | | */ |
| | | protected abstract FutureResult<N> chainResult(M innerResult, |
| | | ResultHandler<? super N> handler) throws ErrorResultException; |
| | | |
| | | } |
| | |
| | | import static com.sun.opends.sdk.messages.Messages.*; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.concurrent.CancellationException; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.TimeoutException; |
| | | |
| | |
| | | { |
| | | |
| | | private static final class SingleEntryFuture implements |
| | | ResultFuture<SearchResultEntry>, ResultHandler<Result>, |
| | | FutureResult<SearchResultEntry>, ResultHandler<Result>, |
| | | SearchResultHandler |
| | | { |
| | | private final ResultHandler<? super SearchResultEntry> handler; |
| | |
| | | |
| | | private volatile int entryCount = 0; |
| | | |
| | | private volatile ResultFuture<Result> future = null; |
| | | private volatile FutureResult<Result> future = null; |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | public SearchResultEntry get() throws ErrorResultException, |
| | | CancellationException, InterruptedException |
| | | InterruptedException |
| | | { |
| | | future.get(); |
| | | return get0(); |
| | |
| | | |
| | | public SearchResultEntry get(long timeout, TimeUnit unit) |
| | | throws ErrorResultException, TimeoutException, |
| | | CancellationException, InterruptedException |
| | | InterruptedException |
| | | { |
| | | future.get(timeout, unit); |
| | | return get0(); |
| | |
| | | |
| | | |
| | | |
| | | public int getMessageID() |
| | | public int getRequestID() |
| | | { |
| | | return future.getMessageID(); |
| | | return future.getRequestID(); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | private void setResultFuture(ResultFuture<Result> future) |
| | | private void setResultFuture(FutureResult<Result> future) |
| | | { |
| | | this.future = future; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> readEntry(DN name, |
| | | public FutureResult<SearchResultEntry> readEntry(DN name, |
| | | Collection<String> attributeDescriptions, |
| | | ResultHandler<? super SearchResultEntry> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<RootDSE> readRootDSE( |
| | | public FutureResult<RootDSE> readRootDSE( |
| | | ResultHandler<RootDSE> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchema(DN name, |
| | | public FutureResult<Schema> readSchema(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchemaForEntry(DN name, |
| | | public FutureResult<Schema> readSchemaForEntry(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> searchSingleEntry( |
| | | public FutureResult<SearchResultEntry> searchSingleEntry( |
| | | SearchRequest request, |
| | | ResultHandler<? super SearchResultEntry> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SingleEntryFuture innerFuture = new SingleEntryFuture(handler); |
| | | final ResultFuture<Result> future = search(request, innerFuture, |
| | | final FutureResult<Result> future = search(request, innerFuture, |
| | | innerFuture); |
| | | innerFuture.setResultFuture(future); |
| | | return innerFuture; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public abstract ConnectionFuture<? extends C> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super C> handler); |
| | | public abstract FutureResult<? extends C> getAsynchronousConnection( |
| | | ResultHandler<? super C> handler); |
| | | |
| | | |
| | | |
| | |
| | | protected final C blockingGetAsynchronousConnection() |
| | | throws ErrorResultException |
| | | { |
| | | ConnectionFuture<? extends C> future = getAsynchronousConnection(null); |
| | | FutureResult<? extends C> future = getAsynchronousConnection(null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | * <h3>Operation processing</h3> |
| | | * <p> |
| | | * All operations are performed asynchronously and return a |
| | | * {@link ResultFuture} or sub-type thereof which can be used for |
| | | * retrieving the result using the {@link ResultFuture#get} method. |
| | | * {@link FutureResult} or sub-type thereof which can be used for |
| | | * retrieving the result using the {@link FutureResult#get} method. |
| | | * Operation failures, for whatever reason, are signalled by the |
| | | * {@link ResultFuture#get()} method throwing an |
| | | * {@link FutureResult#get()} method throwing an |
| | | * {@link ErrorResultException}. |
| | | * <p> |
| | | * Synchronous operations are easily simulated by immediately getting |
| | |
| | | * Connection connection2 = ...; |
| | | * AddRequest request = ...; |
| | | * // Add the entry to the first server (don't block). |
| | | * ResultFuture future1 = connection1.add(request); |
| | | * FutureResult future1 = connection1.add(request); |
| | | * // Add the entry to the second server (in parallel). |
| | | * ResultFuture future2 = connection2.add(request); |
| | | * FutureResult future2 = connection2.add(request); |
| | | * // Total time = is O(1) instead of O(n). |
| | | * future1.get(); |
| | | * future2.get(); |
| | |
| | | * abandon request. |
| | | * <p> |
| | | * <b>Note:</b> a more convenient approach to abandoning unfinished |
| | | * operations is provided via the {@link ResultFuture#cancel(boolean)} |
| | | * operations is provided via the {@link FutureResult#cancel(boolean)} |
| | | * method. |
| | | * |
| | | * @param request |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<Result> add(AddRequest request, |
| | | FutureResult<Result> add(AddRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<BindResult> bind(BindRequest request, |
| | | FutureResult<BindResult> bind(BindRequest request, |
| | | ResultHandler<? super BindResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<CompareResult> compare(CompareRequest request, |
| | | FutureResult<CompareResult> compare(CompareRequest request, |
| | | ResultHandler<? super CompareResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<Result> delete(DeleteRequest request, |
| | | FutureResult<Result> delete(DeleteRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | <R extends Result> ResultFuture<R> extendedRequest( |
| | | <R extends Result> FutureResult<R> extendedRequest( |
| | | ExtendedRequest<R> request, ResultHandler<? super R> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<Result> modify(ModifyRequest request, |
| | | FutureResult<Result> modify(ModifyRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<Result> modifyDN(ModifyDNRequest request, |
| | | FutureResult<Result> modifyDN(ModifyDNRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException; |
| | |
| | | * @throws NullPointerException |
| | | * If the {@code name} was {@code null}. |
| | | */ |
| | | ResultFuture<SearchResultEntry> readEntry(DN name, |
| | | FutureResult<SearchResultEntry> readEntry(DN name, |
| | | Collection<String> attributeDescriptions, |
| | | ResultHandler<? super SearchResultEntry> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | */ |
| | | ResultFuture<RootDSE> readRootDSE(ResultHandler<RootDSE> handler) |
| | | FutureResult<RootDSE> readRootDSE(ResultHandler<RootDSE> handler) |
| | | throws UnsupportedOperationException, IllegalStateException; |
| | | |
| | | |
| | |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | */ |
| | | ResultFuture<Schema> readSchema(DN name, ResultHandler<Schema> handler) |
| | | FutureResult<Schema> readSchema(DN name, ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException; |
| | | |
| | | |
| | |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | */ |
| | | ResultFuture<Schema> readSchemaForEntry(DN name, |
| | | FutureResult<Schema> readSchemaForEntry(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException; |
| | | |
| | |
| | | * @throws NullPointerException |
| | | * If {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<Result> search(SearchRequest request, |
| | | FutureResult<Result> search(SearchRequest request, |
| | | ResultHandler<Result> resultHandler, |
| | | SearchResultHandler searchResulthandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | * @throws NullPointerException |
| | | * If the {@code request} was {@code null}. |
| | | */ |
| | | ResultFuture<SearchResultEntry> searchSingleEntry( |
| | | FutureResult<SearchResultEntry> searchSingleEntry( |
| | | SearchRequest request, |
| | | ResultHandler<? super SearchResultEntry> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConnectionFuture<AuthenticatedAsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AuthenticatedAsynchronousConnection> handler) |
| | | public FutureResult<AuthenticatedAsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AuthenticatedAsynchronousConnection> handler) |
| | | { |
| | | // TODO: bug here? if allowRebind= false then bind will never |
| | | // happen |
| | | ConnectionFutureImpl future = new ConnectionFutureImpl( |
| | | ResultFutureImpl future = new ResultFutureImpl( |
| | | allowRebinds ? request : null, handler); |
| | | future.connectFuture = parentFactory |
| | | .getAsynchronousConnection(future); |
| | | .getAsynchronousConnection(future.connectionHandler); |
| | | return future; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> add(AddRequest request, |
| | | public FutureResult<Result> add(AddRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | * connections. This method will always throw {@code |
| | | * UnsupportedOperationException}. |
| | | */ |
| | | public ResultFuture<BindResult> bind(BindRequest request, |
| | | public FutureResult<BindResult> bind(BindRequest request, |
| | | ResultHandler<? super BindResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<CompareResult> compare(CompareRequest request, |
| | | public FutureResult<CompareResult> compare(CompareRequest request, |
| | | ResultHandler<? super CompareResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> delete(DeleteRequest request, |
| | | public FutureResult<Result> delete(DeleteRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public <R extends Result> ResultFuture<R> extendedRequest( |
| | | public <R extends Result> FutureResult<R> extendedRequest( |
| | | ExtendedRequest<R> request, ResultHandler<? super R> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> modify(ModifyRequest request, |
| | | public FutureResult<Result> modify(ModifyRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> modifyDN(ModifyDNRequest request, |
| | | public FutureResult<Result> modifyDN(ModifyDNRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | */ |
| | | public ResultFuture<BindResult> rebind( |
| | | public FutureResult<BindResult> rebind( |
| | | ResultHandler<? super BindResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> search(SearchRequest request, |
| | | public FutureResult<Result> search(SearchRequest request, |
| | | ResultHandler<Result> resultHandler, |
| | | SearchResultHandler searchResulthandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<RootDSE> readRootDSE( |
| | | public FutureResult<RootDSE> readRootDSE( |
| | | ResultHandler<RootDSE> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> readEntry(DN name, |
| | | public FutureResult<SearchResultEntry> readEntry(DN name, |
| | | Collection<String> attributeDescriptions, |
| | | ResultHandler<? super SearchResultEntry> resultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> searchSingleEntry( |
| | | public FutureResult<SearchResultEntry> searchSingleEntry( |
| | | SearchRequest request, |
| | | ResultHandler<? super SearchResultEntry> resultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchemaForEntry(DN name, |
| | | public FutureResult<Schema> readSchemaForEntry(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchema(DN name, |
| | | public FutureResult<Schema> readSchema(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | private static final class ConnectionFutureImpl implements |
| | | ConnectionFuture<AuthenticatedAsynchronousConnection>, |
| | | ConnectionResultHandler<AsynchronousConnection>, |
| | | private static final class ResultFutureImpl implements |
| | | FutureResult<AuthenticatedAsynchronousConnection> |
| | | { |
| | | private final class ConnectionResultHandler implements |
| | | ResultHandler<AsynchronousConnection> |
| | | { |
| | | public void handleResult(AsynchronousConnection conn) |
| | | { |
| | | connection = conn; |
| | | bindFuture = connection.bind(request, bindHandler); |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | exception = error; |
| | | latch.countDown(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private final class BindRequestResultHandler implements |
| | | ResultHandler<BindResult> |
| | | { |
| | | public void handleResult(BindResult result) |
| | | { |
| | | // FIXME: should make the result unmodifiable. |
| | | authenticatedConnection = new AuthenticatedAsynchronousConnection( |
| | | connection, request, result); |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleResult(authenticatedConnection); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | // Ensure that the connection is closed. |
| | | try |
| | | { |
| | | connection.close(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // Ignore. |
| | | } |
| | | |
| | | exception = error; |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleErrorResult(exception); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private final ResultHandler<BindResult> bindHandler = new BindRequestResultHandler(); |
| | | |
| | | private final ResultHandler<AsynchronousConnection> connectionHandler = new ConnectionResultHandler(); |
| | | |
| | | private volatile AuthenticatedAsynchronousConnection authenticatedConnection; |
| | | |
| | | private volatile AsynchronousConnection connection; |
| | | |
| | | private volatile ErrorResultException exception; |
| | | |
| | | private volatile ConnectionFuture<?> connectFuture; |
| | | private volatile FutureResult<?> connectFuture; |
| | | |
| | | private volatile ResultFuture<BindResult> bindFuture; |
| | | private volatile FutureResult<BindResult> bindFuture; |
| | | |
| | | private final CountDownLatch latch = new CountDownLatch(1); |
| | | |
| | | private final ConnectionResultHandler<? super AuthenticatedAsynchronousConnection> handler; |
| | | private final ResultHandler<? super AuthenticatedAsynchronousConnection> handler; |
| | | |
| | | private boolean cancelled; |
| | | |
| | |
| | | |
| | | |
| | | |
| | | private ConnectionFutureImpl( |
| | | private ResultFutureImpl( |
| | | BindRequest request, |
| | | ConnectionResultHandler<? super AuthenticatedAsynchronousConnection> handler) |
| | | ResultHandler<? super AuthenticatedAsynchronousConnection> handler) |
| | | { |
| | | this.request = request; |
| | | this.handler = handler; |
| | |
| | | |
| | | |
| | | |
| | | public void handleConnection(AsynchronousConnection connection) |
| | | public int getRequestID() |
| | | { |
| | | this.connection = connection; |
| | | this.bindFuture = this.connection.bind(request, this); |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleConnectionError(ErrorResultException error) |
| | | { |
| | | exception = error; |
| | | latch.countDown(); |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleResult(BindResult result) |
| | | { |
| | | // FIXME: should make the result unmodifiable. |
| | | authenticatedConnection = new AuthenticatedAsynchronousConnection( |
| | | connection, request, result); |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(authenticatedConnection); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | // Ensure that the connection is closed. |
| | | try |
| | | { |
| | | connection.close(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // Ignore. |
| | | } |
| | | |
| | | exception = error; |
| | | latch.countDown(); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnectionError(exception); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public ConnectionFuture<AuthenticatedAsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AuthenticatedAsynchronousConnection> handler) |
| | | public FutureResult<AuthenticatedAsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AuthenticatedAsynchronousConnection> handler) |
| | | { |
| | | return impl.getAsynchronousConnection(handler); |
| | | } |
| | |
| | | /** |
| | | * Initiates an asynchronous connection request to the Directory |
| | | * Server associated with this connection factory. The returned |
| | | * {@code ConnectionFuture} can be used to retrieve the completed |
| | | * {@code FutureResult} can be used to retrieve the completed |
| | | * asynchronous connection. Alternatively, if a {@code |
| | | * ConnectionResultHandler} is provided, the handler will be notified |
| | | * ResultHandler} is provided, the handler will be notified |
| | | * when the connection is available and ready for use. |
| | | * |
| | | * @param handler |
| | |
| | | * @return A future which can be used to retrieve the asynchronous |
| | | * connection. |
| | | */ |
| | | ConnectionFuture<? extends C> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super C> handler); |
| | | FutureResult<? extends C> getAsynchronousConnection( |
| | | ResultHandler<? super C> handler); |
| | | } |
| | |
| | | // FIXME: should use a better collection than this - CLQ? |
| | | private final Stack<AsynchronousConnection> pool; |
| | | |
| | | private final ConcurrentLinkedQueue<PendingConnectionFuture> pendingFutures; |
| | | private final ConcurrentLinkedQueue<PendingResultFuture> pendingFutures; |
| | | |
| | | private final Object lock = new Object(); |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> add(AddRequest request, |
| | | public FutureResult<Result> add(AddRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<BindResult> bind(BindRequest request, |
| | | public FutureResult<BindResult> bind(BindRequest request, |
| | | ResultHandler<? super BindResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | } |
| | | |
| | | // See if there waiters pending |
| | | PendingConnectionFuture future = pendingFutures.poll(); |
| | | PendingResultFuture future = pendingFutures.poll(); |
| | | if (future != null) |
| | | { |
| | | PooledConnectionWapper pooledConnection = new PooledConnectionWapper( |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<CompareResult> compare(CompareRequest request, |
| | | public FutureResult<CompareResult> compare(CompareRequest request, |
| | | ResultHandler<? super CompareResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> delete(DeleteRequest request, |
| | | public FutureResult<Result> delete(DeleteRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public <R extends Result> ResultFuture<R> extendedRequest( |
| | | public <R extends Result> FutureResult<R> extendedRequest( |
| | | ExtendedRequest<R> request, ResultHandler<? super R> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> modify(ModifyRequest request, |
| | | public FutureResult<Result> modify(ModifyRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> modifyDN(ModifyDNRequest request, |
| | | public FutureResult<Result> modifyDN(ModifyDNRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> search(SearchRequest request, |
| | | public FutureResult<Result> search(SearchRequest request, |
| | | ResultHandler<Result> resultHandler, |
| | | SearchResultHandler searchResulthandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> readEntry(DN name, |
| | | public FutureResult<SearchResultEntry> readEntry(DN name, |
| | | Collection<String> attributeDescriptions, |
| | | ResultHandler<? super SearchResultEntry> resultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> searchSingleEntry( |
| | | public FutureResult<SearchResultEntry> searchSingleEntry( |
| | | SearchRequest request, |
| | | ResultHandler<? super SearchResultEntry> resultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<RootDSE> readRootDSE( |
| | | public FutureResult<RootDSE> readRootDSE( |
| | | ResultHandler<RootDSE> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchemaForEntry(DN name, |
| | | public FutureResult<Schema> readSchemaForEntry(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchema(DN name, |
| | | public FutureResult<Schema> readSchema(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | private static final class CompletedConnectionFuture implements |
| | | ConnectionFuture<AsynchronousConnection> |
| | | private static final class CompletedResultFuture implements |
| | | FutureResult<AsynchronousConnection> |
| | | { |
| | | private final PooledConnectionWapper connection; |
| | | |
| | | |
| | | |
| | | private CompletedConnectionFuture(PooledConnectionWapper connection) |
| | | private CompletedResultFuture(PooledConnectionWapper connection) |
| | | { |
| | | this.connection = connection; |
| | | } |
| | |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | public int getRequestID() |
| | | { |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private final class PendingConnectionFuture implements |
| | | ConnectionFuture<AsynchronousConnection> |
| | | private final class PendingResultFuture implements |
| | | FutureResult<AsynchronousConnection> |
| | | { |
| | | private volatile boolean isCancelled; |
| | | |
| | |
| | | |
| | | private volatile ErrorResultException err; |
| | | |
| | | private final ConnectionResultHandler<? super AsynchronousConnection> handler; |
| | | private final ResultHandler<? super AsynchronousConnection> handler; |
| | | |
| | | private final CountDownLatch latch = new CountDownLatch(1); |
| | | |
| | | |
| | | |
| | | private PendingConnectionFuture( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | private PendingResultFuture( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | this.handler = handler; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public int getRequestID() |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | |
| | | private void connection(PooledConnectionWapper connection) |
| | | { |
| | | this.connection = connection; |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(connection); |
| | | handler.handleResult(connection); |
| | | } |
| | | latch.countDown(); |
| | | } |
| | |
| | | this.err = e; |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnectionError(e); |
| | | handler.handleErrorResult(e); |
| | | } |
| | | latch.countDown(); |
| | | } |
| | |
| | | this.connectionFactory = connectionFactory; |
| | | this.poolSize = poolSize; |
| | | this.pool = new Stack<AsynchronousConnection>(); |
| | | this.pendingFutures = new ConcurrentLinkedQueue<PendingConnectionFuture>(); |
| | | this.pendingFutures = new ConcurrentLinkedQueue<PendingResultFuture>(); |
| | | } |
| | | |
| | | |
| | | |
| | | private final class WrapConnectionResultHandler implements |
| | | ConnectionResultHandler<AsynchronousConnection> |
| | | private final class WrapResultHandler implements |
| | | ResultHandler<AsynchronousConnection> |
| | | { |
| | | private final PendingConnectionFuture future; |
| | | private final PendingResultFuture future; |
| | | |
| | | |
| | | |
| | | private WrapConnectionResultHandler(PendingConnectionFuture future) |
| | | private WrapResultHandler(PendingResultFuture future) |
| | | { |
| | | this.future = future; |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleConnection(AsynchronousConnection connection) |
| | | public void handleResult(AsynchronousConnection connection) |
| | | { |
| | | PooledConnectionWapper pooledConnection = new PooledConnectionWapper( |
| | | connection); |
| | |
| | | |
| | | |
| | | |
| | | public void handleConnectionError(ErrorResultException error) |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | future.error(error); |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public ConnectionFuture<AsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | public FutureResult<AsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | synchronized (lock) |
| | | { |
| | |
| | | conn); |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(pooledConnection); |
| | | handler.handleResult(pooledConnection); |
| | | } |
| | | return new CompletedConnectionFuture(pooledConnection); |
| | | return new CompletedResultFuture(pooledConnection); |
| | | } |
| | | |
| | | PendingConnectionFuture pendingFuture = new PendingConnectionFuture( |
| | | PendingResultFuture pendingFuture = new PendingResultFuture( |
| | | handler); |
| | | // Pool was empty. Maybe a new connection if pool size is not |
| | | // reached |
| | | if (numConnections < poolSize) |
| | | { |
| | | numConnections++; |
| | | WrapConnectionResultHandler wrapHandler = new WrapConnectionResultHandler( |
| | | WrapResultHandler wrapHandler = new WrapResultHandler( |
| | | pendingFuture); |
| | | connectionFactory.getAsynchronousConnection(wrapHandler); |
| | | if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE)) |
| File was renamed from sdk/src/org/opends/sdk/ResultFuture.java |
| | |
| | | |
| | | |
| | | |
| | | import java.util.concurrent.CancellationException; |
| | | import java.util.concurrent.Future; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.TimeoutException; |
| | |
| | | * @param <S> |
| | | * The type of result returned by this future. |
| | | */ |
| | | public interface ResultFuture<S> extends Future<S> |
| | | public interface FutureResult<S> extends Future<S> |
| | | { |
| | | /** |
| | | * Attempts to cancel the request. This attempt will fail if the |
| | |
| | | * @throws ErrorResultException |
| | | * If the result code indicates that the request failed for |
| | | * some reason. |
| | | * @throws CancellationException |
| | | * If the request was cancelled using a call to |
| | | * {@link #cancel}. |
| | | * @throws InterruptedException |
| | | * If the current thread was interrupted while waiting. |
| | | */ |
| | | S get() throws ErrorResultException, CancellationException, |
| | | InterruptedException; |
| | | S get() throws ErrorResultException, InterruptedException; |
| | | |
| | | |
| | | |
| | |
| | | * some reason. |
| | | * @throws TimeoutException |
| | | * If the wait timed out. |
| | | * @throws CancellationException |
| | | * If the request was cancelled using a call to |
| | | * {@link #cancel}. |
| | | * @throws InterruptedException |
| | | * If the current thread was interrupted while waiting. |
| | | */ |
| | | S get(long timeout, TimeUnit unit) throws ErrorResultException, |
| | | TimeoutException, CancellationException, InterruptedException; |
| | | TimeoutException, InterruptedException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the message ID of the request. |
| | | * Returns the request ID of the request if appropriate. |
| | | * |
| | | * @return The message ID. |
| | | * @return The request ID, or {@code -1} if there is no request ID. |
| | | */ |
| | | int getMessageID(); |
| | | int getRequestID(); |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> add(AddRequest request, |
| | | public FutureResult<Result> add(AddRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<BindResult> bind(BindRequest request, |
| | | public FutureResult<BindResult> bind(BindRequest request, |
| | | ResultHandler<? super BindResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<CompareResult> compare(CompareRequest request, |
| | | public FutureResult<CompareResult> compare(CompareRequest request, |
| | | ResultHandler<? super CompareResult> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> delete(DeleteRequest request, |
| | | public FutureResult<Result> delete(DeleteRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public <R extends Result> ResultFuture<R> extendedRequest( |
| | | public <R extends Result> FutureResult<R> extendedRequest( |
| | | ExtendedRequest<R> request, ResultHandler<? super R> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> modify(ModifyRequest request, |
| | | public FutureResult<Result> modify(ModifyRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> modifyDN(ModifyDNRequest request, |
| | | public FutureResult<Result> modifyDN(ModifyDNRequest request, |
| | | ResultHandler<Result> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | |
| | | |
| | | |
| | | |
| | | public ResultFuture<Result> search(SearchRequest request, |
| | | public FutureResult<Result> search(SearchRequest request, |
| | | ResultHandler<Result> resultHandler, |
| | | SearchResultHandler searchResultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> readEntry(DN name, |
| | | public FutureResult<SearchResultEntry> readEntry(DN name, |
| | | Collection<String> attributeDescriptions, |
| | | ResultHandler<? super SearchResultEntry> resultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<SearchResultEntry> searchSingleEntry( |
| | | public FutureResult<SearchResultEntry> searchSingleEntry( |
| | | SearchRequest request, |
| | | ResultHandler<? super SearchResultEntry> resultHandler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<RootDSE> readRootDSE( |
| | | public FutureResult<RootDSE> readRootDSE( |
| | | ResultHandler<RootDSE> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchemaForEntry(DN name, |
| | | public FutureResult<Schema> readSchemaForEntry(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ResultFuture<Schema> readSchema(DN name, |
| | | public FutureResult<Schema> readSchema(DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | private final class ConnectionFutureImpl implements |
| | | ConnectionFuture<AsynchronousConnection>, |
| | | ConnectionResultHandler<AsynchronousConnection> |
| | | private final class ResultFutureImpl implements |
| | | FutureResult<AsynchronousConnection>, |
| | | ResultHandler<AsynchronousConnection> |
| | | { |
| | | private volatile AsynchronousConnectionImpl heartBeatConnection; |
| | | |
| | | private volatile ErrorResultException exception; |
| | | |
| | | private volatile ConnectionFuture<?> connectFuture; |
| | | private volatile FutureResult<?> connectFuture; |
| | | |
| | | private final CountDownLatch latch = new CountDownLatch(1); |
| | | |
| | | private final ConnectionResultHandler<? super AsynchronousConnectionImpl> handler; |
| | | private final ResultHandler<? super AsynchronousConnectionImpl> handler; |
| | | |
| | | private boolean cancelled; |
| | | |
| | | |
| | | |
| | | private ConnectionFutureImpl( |
| | | ConnectionResultHandler<? super AsynchronousConnectionImpl> handler) |
| | | private ResultFutureImpl( |
| | | ResultHandler<? super AsynchronousConnectionImpl> handler) |
| | | { |
| | | this.handler = handler; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public void handleConnection(AsynchronousConnection connection) |
| | | public int getRequestID() |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleResult(AsynchronousConnection connection) |
| | | { |
| | | heartBeatConnection = new AsynchronousConnectionImpl(connection); |
| | | synchronized (activeConnections) |
| | |
| | | } |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnection(heartBeatConnection); |
| | | handler.handleResult(heartBeatConnection); |
| | | } |
| | | latch.countDown(); |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleConnectionError(ErrorResultException error) |
| | | public void handleErrorResult(ErrorResultException error) |
| | | { |
| | | exception = error; |
| | | if (handler != null) |
| | | { |
| | | handler.handleConnectionError(error); |
| | | handler.handleErrorResult(error); |
| | | } |
| | | latch.countDown(); |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public ConnectionFuture<AsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | public FutureResult<AsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | ConnectionFutureImpl future = new ConnectionFutureImpl(handler); |
| | | ResultFutureImpl future = new ResultFutureImpl(handler); |
| | | future.connectFuture = parentFactory |
| | | .getAsynchronousConnection(future); |
| | | return future; |
| | |
| | | * @throws NullPointerException |
| | | * If the {@code connection} was {@code null}. |
| | | */ |
| | | public static ResultFuture<RootDSE> readRootDSE( |
| | | public static FutureResult<RootDSE> readRootDSE( |
| | | AsynchronousConnection connection, |
| | | ResultHandler<RootDSE> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final ResultTransformer<SearchResultEntry, RootDSE> future = |
| | | new ResultTransformer<SearchResultEntry, RootDSE>(handler) |
| | | final FutureResultTransformer<SearchResultEntry, RootDSE> future = |
| | | new FutureResultTransformer<SearchResultEntry, RootDSE>(handler) |
| | | { |
| | | |
| | | protected RootDSE transformResult(SearchResultEntry result) |
| | |
| | | |
| | | }; |
| | | |
| | | ResultFuture<SearchResultEntry> innerFuture = connection |
| | | FutureResult<SearchResultEntry> innerFuture = connection |
| | | .searchSingleEntry(SEARCH_REQUEST, future); |
| | | future.setResultFuture(innerFuture); |
| | | future.setFutureResult(innerFuture); |
| | | return future; |
| | | } |
| | | |
| | |
| | | InterruptedException, UnsupportedOperationException, |
| | | IllegalStateException, NullPointerException |
| | | { |
| | | ResultFuture<Result> future = connection.add(request, null); |
| | | FutureResult<Result> future = connection.add(request, null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | ResultFuture<BindResult> future = connection.bind(request, null); |
| | | FutureResult<BindResult> future = connection.bind(request, null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | ResultFuture<CompareResult> future = connection.compare(request, |
| | | FutureResult<CompareResult> future = connection.compare(request, |
| | | null); |
| | | try |
| | | { |
| | |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | ResultFuture<Result> future = connection.delete(request, null); |
| | | FutureResult<Result> future = connection.delete(request, null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | ResultFuture<R> future = connection.extendedRequest(request, null); |
| | | FutureResult<R> future = connection.extendedRequest(request, null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | ResultFuture<Result> future = connection.modify(request, null); |
| | | FutureResult<Result> future = connection.modify(request, null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | ResultFuture<Result> future = connection.modifyDN(request, null); |
| | | FutureResult<Result> future = connection.modifyDN(request, null); |
| | | try |
| | | { |
| | | return future.get(); |
| | |
| | | InterruptedException, UnsupportedOperationException, |
| | | IllegalStateException, NullPointerException |
| | | { |
| | | ResultFuture<Result> future = connection.search(request, null, |
| | | FutureResult<Result> future = connection.search(request, null, |
| | | handler); |
| | | try |
| | | { |
| | |
| | | throws ErrorResultException, InterruptedException, |
| | | UnsupportedOperationException, IllegalStateException |
| | | { |
| | | ResultFuture<Schema> future = connection.readSchemaForEntry(name, |
| | | FutureResult<Schema> future = connection.readSchemaForEntry(name, |
| | | null); |
| | | try |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | public ConnectionFuture<AsynchronousConnection> getAsynchronousConnection( |
| | | ConnectionResultHandler<? super AsynchronousConnection> handler) |
| | | public FutureResult<AsynchronousConnection> getAsynchronousConnection( |
| | | ResultHandler<? super AsynchronousConnection> handler) |
| | | { |
| | | return impl.getAsynchronousConnection(handler); |
| | | } |
| | |
| | | |
| | | static |
| | | { |
| | | final SchemaBuilder builder = new SchemaBuilder(); |
| | | final SchemaBuilder builder = new SchemaBuilder("Core Schema"); |
| | | defaultSyntaxes(builder); |
| | | defaultMatchingRules(builder); |
| | | defaultAttributeTypes(builder); |
| | |
| | | import org.opends.sdk.responses.Result; |
| | | import org.opends.sdk.responses.SearchResultEntry; |
| | | |
| | | import com.sun.opends.sdk.util.ResultChain; |
| | | import com.sun.opends.sdk.util.ResultTransformer; |
| | | import com.sun.opends.sdk.util.FutureResultTransformer; |
| | | import com.sun.opends.sdk.util.RecursiveFutureResult; |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public String getSchemaName() |
| | | { |
| | | return "Empty Schema"; |
| | | } |
| | | |
| | | |
| | | |
| | | public Syntax getSyntax(String numericOID) |
| | | { |
| | | // Fake up a syntax substituted by the default syntax. |
| | |
| | | |
| | | |
| | | |
| | | String getSchemaName(); |
| | | |
| | | |
| | | |
| | | Syntax getSyntax(String numericOID) |
| | | throws UnknownSchemaElementException; |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public String getSchemaName() |
| | | { |
| | | return strictImpl.getSchemaName(); |
| | | } |
| | | |
| | | |
| | | |
| | | public Syntax getSyntax(String numericOID) |
| | | { |
| | | if (!strictImpl.hasSyntax(numericOID)) |
| | |
| | | |
| | | private final List<LocalizableMessage> warnings; |
| | | |
| | | private final String schemaName; |
| | | |
| | | |
| | | private StrictImpl(Map<String, Syntax> numericOID2Syntaxes, |
| | | |
| | | private StrictImpl(String schemaName, |
| | | Map<String, Syntax> numericOID2Syntaxes, |
| | | Map<String, MatchingRule> numericOID2MatchingRules, |
| | | Map<String, MatchingRuleUse> numericOID2MatchingRuleUses, |
| | | Map<String, AttributeType> numericOID2AttributeTypes, |
| | |
| | | Map<String, List<DITStructureRule>> nameForm2StructureRules, |
| | | SchemaCompatOptions options, List<LocalizableMessage> warnings) |
| | | { |
| | | this.schemaName = schemaName; |
| | | this.numericOID2Syntaxes = Collections |
| | | .unmodifiableMap(numericOID2Syntaxes); |
| | | this.numericOID2MatchingRules = Collections |
| | |
| | | |
| | | |
| | | |
| | | public String getSchemaName() |
| | | { |
| | | return schemaName; |
| | | } |
| | | |
| | | |
| | | |
| | | public Syntax getSyntax(String numericOID) |
| | | throws UnknownSchemaElementException |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server contained in the named |
| | | * subschema sub-entry using the provided connection. |
| | | * <p> |
| | | * If the requested schema is not returned by the Directory Server |
| | | * then the request will fail with an {@link EntryNotFoundException}. |
| | | * More specifically, this method will never return {@code null}. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the subschema sub-entry. |
| | | * @return The schema from the Directory Server. |
| | | * @throws ErrorResultException |
| | | * If the result code indicates that the request failed for |
| | | * some reason. |
| | | * @throws InterruptedException |
| | | * If the current thread was interrupted while waiting. |
| | | * @throws UnsupportedOperationException |
| | | * If the connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If the connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static Schema readSchema(Connection connection, DN name) |
| | | throws ErrorResultException, InterruptedException, |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = getReadSchemaSearchRequest(name); |
| | | final Entry entry = connection.searchSingleEntry(request); |
| | | return valueOf(entry); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server which applies to the |
| | | * named entry using the provided connection. |
| | | * <p> |
| | | * If the requested entry or its associated schema are not returned by |
| | | * the Directory Server then the request will fail with an |
| | | * {@link EntryNotFoundException}. More specifically, this method will |
| | | * never return {@code null}. |
| | | * <p> |
| | | * A typical implementation will first read the {@code |
| | | * subschemaSubentry} attribute of the entry in order to locate the |
| | | * schema. However, implementations may choose to perform other |
| | | * optimizations, such as caching. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the entry whose schema is to be |
| | | * located. |
| | | * @return The schema from the Directory Server which applies to the |
| | | * named entry. |
| | | * @throws ErrorResultException |
| | | * If the result code indicates that the request failed for |
| | | * some reason. |
| | | * @throws InterruptedException |
| | | * If the current thread was interrupted while waiting. |
| | | * @throws UnsupportedOperationException |
| | | * If the connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If the connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static Schema readSchemaForEntry(Connection connection, DN name) |
| | | throws ErrorResultException, InterruptedException, |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = getReadSchemaForEntrySearchRequest(name); |
| | | final Entry entry = connection.searchSingleEntry(request); |
| | | final DN subschemaDN = getSubschemaSubentryDN(name, entry); |
| | | |
| | | return readSchema(connection, subschemaDN); |
| | | } |
| | | |
| | | |
| | | |
| | | private static DN getSubschemaSubentryDN(DN name, final Entry entry) |
| | | throws ErrorResultException |
| | | { |
| | | final Attribute subentryAttr = entry |
| | | .getAttribute(ATTR_SUBSCHEMA_SUBENTRY); |
| | | |
| | | if (subentryAttr == null || subentryAttr.isEmpty()) |
| | | { |
| | | // Did not get the subschema sub-entry attribute. |
| | | Result result = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED) |
| | | .setDiagnosticMessage( |
| | | ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString()) |
| | | .toString()); |
| | | throw ErrorResultException.wrap(result); |
| | | } |
| | | |
| | | String dnString = subentryAttr.iterator().next().toString(); |
| | | DN subschemaDN; |
| | | try |
| | | { |
| | | subschemaDN = DN.valueOf(dnString); |
| | | } |
| | | catch (LocalizedIllegalArgumentException e) |
| | | { |
| | | Result result = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED) |
| | | .setDiagnosticMessage( |
| | | ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(), |
| | | dnString, e.getMessageObject()).toString()); |
| | | throw ErrorResultException.wrap(result); |
| | | } |
| | | return subschemaDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server contained in the named |
| | | * subschema sub-entry. |
| | | * <p> |
| | | * If the requested schema is not returned by the Directory Server |
| | | * then the request will fail with an {@link EntryNotFoundException}. |
| | | * More specifically, the returned future will never return {@code |
| | | * null}. |
| | | * <p> |
| | | * Implementations may choose to perform optimizations such as |
| | | * caching. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the subschema sub-entry. |
| | | * @param handler |
| | | * A result handler which can be used to asynchronously |
| | | * process the operation result when it is received, may be |
| | | * {@code null}. |
| | | * @return A future representing the result of the operation. |
| | | * @throws UnsupportedOperationException |
| | | * If this connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static ResultFuture<Schema> readSchema( |
| | | AsynchronousConnection connection, DN name, |
| | | ResultHandler<? super Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = getReadSchemaSearchRequest(name); |
| | | |
| | | final ResultTransformer<SearchResultEntry, Schema> future = new ResultTransformer<SearchResultEntry, Schema>( |
| | | handler) |
| | | { |
| | | |
| | | protected Schema transformResult(SearchResultEntry result) |
| | | throws ErrorResultException |
| | | { |
| | | return valueOf(result); |
| | | } |
| | | |
| | | }; |
| | | |
| | | ResultFuture<SearchResultEntry> innerFuture = connection |
| | | .searchSingleEntry(request, future); |
| | | future.setResultFuture(innerFuture); |
| | | return future; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server which applies to the |
| | | * named entry. |
| | | * <p> |
| | | * If the requested entry or its associated schema are not returned by |
| | | * the Directory Server then the request will fail with an |
| | | * {@link EntryNotFoundException}. More specifically, the returned |
| | | * future will never return {@code null}. |
| | | * <p> |
| | | * A typical implementation will first read the {@code |
| | | * subschemaSubentry} attribute of the entry in order to locate the |
| | | * schema. However, implementations may choose to perform other |
| | | * optimizations, such as caching. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the entry whose schema is to be |
| | | * located. |
| | | * @param handler |
| | | * A result handler which can be used to asynchronously |
| | | * process the operation result when it is received, may be |
| | | * {@code null}. |
| | | * @return A future representing the result of the operation. |
| | | * @throws UnsupportedOperationException |
| | | * If this connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static ResultFuture<Schema> readSchemaForEntry( |
| | | final AsynchronousConnection connection, final DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final ResultChain<SearchResultEntry, Schema> future = new ResultChain<SearchResultEntry, Schema>( |
| | | handler) |
| | | { |
| | | |
| | | protected ResultFuture<Schema> chainResult( |
| | | SearchResultEntry innerResult, |
| | | ResultHandler<? super Schema> handler) |
| | | throws ErrorResultException |
| | | { |
| | | final DN subschemaDN = getSubschemaSubentryDN(name, innerResult); |
| | | return readSchema(connection, subschemaDN, handler); |
| | | } |
| | | |
| | | }; |
| | | |
| | | final SearchRequest request = getReadSchemaForEntrySearchRequest(name); |
| | | ResultFuture<SearchResultEntry> innerFuture = connection |
| | | .searchSingleEntry(request, future); |
| | | future.setInnerResultFuture(innerFuture); |
| | | return future; |
| | | } |
| | | |
| | | |
| | | |
| | | // Constructs a search request for retrieving the named subschema |
| | | // sub-entry. |
| | | private static SearchRequest getReadSchemaSearchRequest(DN dn) |
| | | { |
| | | return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT, |
| | | SUBSCHEMA_FILTER, SUBSCHEMA_ATTRS); |
| | | } |
| | | |
| | | |
| | | |
| | | // Constructs a search request for retrieving the subschemaSubentry |
| | | // attribute from the named entry. |
| | | private static SearchRequest getReadSchemaForEntrySearchRequest(DN dn) |
| | | { |
| | | return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT, |
| | | SUBSCHEMA_FILTER, SUBSCHEMA_SUBENTRY_ATTRS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the core schema. The core schema is non-strict and contains |
| | | * the following standard LDAP schema elements: |
| | | * <ul> |
| | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server contained in the named |
| | | * subschema sub-entry. |
| | | * <p> |
| | | * If the requested schema is not returned by the Directory Server |
| | | * then the request will fail with an {@link EntryNotFoundException}. |
| | | * More specifically, the returned future will never return {@code |
| | | * null}. |
| | | * <p> |
| | | * Implementations may choose to perform optimizations such as |
| | | * caching. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the subschema sub-entry. |
| | | * @param handler |
| | | * A result handler which can be used to asynchronously |
| | | * process the operation result when it is received, may be |
| | | * {@code null}. |
| | | * @return A future representing the result of the operation. |
| | | * @throws UnsupportedOperationException |
| | | * If this connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static FutureResult<Schema> readSchema( |
| | | AsynchronousConnection connection, DN name, |
| | | ResultHandler<? super Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = getReadSchemaSearchRequest(name); |
| | | |
| | | final FutureResultTransformer<SearchResultEntry, Schema> future = new FutureResultTransformer<SearchResultEntry, Schema>( |
| | | handler) |
| | | { |
| | | |
| | | protected Schema transformResult(SearchResultEntry result) |
| | | throws ErrorResultException |
| | | { |
| | | return valueOf(result); |
| | | } |
| | | |
| | | }; |
| | | |
| | | final FutureResult<SearchResultEntry> innerFuture = connection |
| | | .searchSingleEntry(request, future); |
| | | future.setFutureResult(innerFuture); |
| | | return future; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server contained in the named |
| | | * subschema sub-entry using the provided connection. |
| | | * <p> |
| | | * If the requested schema is not returned by the Directory Server |
| | | * then the request will fail with an {@link EntryNotFoundException}. |
| | | * More specifically, this method will never return {@code null}. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the subschema sub-entry. |
| | | * @return The schema from the Directory Server. |
| | | * @throws ErrorResultException |
| | | * If the result code indicates that the request failed for |
| | | * some reason. |
| | | * @throws InterruptedException |
| | | * If the current thread was interrupted while waiting. |
| | | * @throws UnsupportedOperationException |
| | | * If the connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If the connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static Schema readSchema(Connection connection, DN name) |
| | | throws ErrorResultException, InterruptedException, |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = getReadSchemaSearchRequest(name); |
| | | final Entry entry = connection.searchSingleEntry(request); |
| | | return valueOf(entry); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server which applies to the |
| | | * named entry. |
| | | * <p> |
| | | * If the requested entry or its associated schema are not returned by |
| | | * the Directory Server then the request will fail with an |
| | | * {@link EntryNotFoundException}. More specifically, the returned |
| | | * future will never return {@code null}. |
| | | * <p> |
| | | * A typical implementation will first read the {@code |
| | | * subschemaSubentry} attribute of the entry in order to locate the |
| | | * schema. However, implementations may choose to perform other |
| | | * optimizations, such as caching. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the entry whose schema is to be |
| | | * located. |
| | | * @param handler |
| | | * A result handler which can be used to asynchronously |
| | | * process the operation result when it is received, may be |
| | | * {@code null}. |
| | | * @return A future representing the result of the operation. |
| | | * @throws UnsupportedOperationException |
| | | * If this connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If this connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static FutureResult<Schema> readSchemaForEntry( |
| | | final AsynchronousConnection connection, final DN name, |
| | | ResultHandler<Schema> handler) |
| | | throws UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final RecursiveFutureResult<SearchResultEntry, Schema> future = new RecursiveFutureResult<SearchResultEntry, Schema>( |
| | | handler) |
| | | { |
| | | |
| | | protected FutureResult<Schema> chainResult( |
| | | SearchResultEntry innerResult, |
| | | ResultHandler<? super Schema> handler) |
| | | throws ErrorResultException |
| | | { |
| | | final DN subschemaDN = getSubschemaSubentryDN(name, innerResult); |
| | | return readSchema(connection, subschemaDN, handler); |
| | | } |
| | | |
| | | }; |
| | | |
| | | final SearchRequest request = getReadSchemaForEntrySearchRequest(name); |
| | | final FutureResult<SearchResultEntry> innerFuture = connection |
| | | .searchSingleEntry(request, future); |
| | | future.setFutureResult(innerFuture); |
| | | return future; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Reads the schema from the Directory Server which applies to the |
| | | * named entry using the provided connection. |
| | | * <p> |
| | | * If the requested entry or its associated schema are not returned by |
| | | * the Directory Server then the request will fail with an |
| | | * {@link EntryNotFoundException}. More specifically, this method will |
| | | * never return {@code null}. |
| | | * <p> |
| | | * A typical implementation will first read the {@code |
| | | * subschemaSubentry} attribute of the entry in order to locate the |
| | | * schema. However, implementations may choose to perform other |
| | | * optimizations, such as caching. |
| | | * |
| | | * @param connection |
| | | * A connection to the Directory Server whose schema is to be |
| | | * read. |
| | | * @param name |
| | | * The distinguished name of the entry whose schema is to be |
| | | * located. |
| | | * @return The schema from the Directory Server which applies to the |
| | | * named entry. |
| | | * @throws ErrorResultException |
| | | * If the result code indicates that the request failed for |
| | | * some reason. |
| | | * @throws InterruptedException |
| | | * If the current thread was interrupted while waiting. |
| | | * @throws UnsupportedOperationException |
| | | * If the connection does not support search operations. |
| | | * @throws IllegalStateException |
| | | * If the connection has already been closed, i.e. if |
| | | * {@code isClosed() == true}. |
| | | * @throws NullPointerException |
| | | * If the {@code connection} or {@code name} was {@code |
| | | * null}. |
| | | */ |
| | | public static Schema readSchemaForEntry(Connection connection, DN name) |
| | | throws ErrorResultException, InterruptedException, |
| | | UnsupportedOperationException, IllegalStateException, |
| | | NullPointerException |
| | | { |
| | | final SearchRequest request = getReadSchemaForEntrySearchRequest(name); |
| | | final Entry entry = connection.searchSingleEntry(request); |
| | | final DN subschemaDN = getSubschemaSubentryDN(name, entry); |
| | | |
| | | return readSchema(connection, subschemaDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the default schema which should be used by this application. |
| | | * The default schema is initially set to the core schema. |
| | | * |
| | | * @param schema |
| | | * The default schema which should be used by this |
| | | * application. |
| | | */ |
| | | public static void setDefaultSchema(Schema schema) |
| | | { |
| | | DEFAULT_SCHEMA = schema; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the provided entry as a subschema subentry. Any problems |
| | | * encountered while parsing the entry can be retrieved using the |
| | | * returned schema's {@link #getWarnings()} method. |
| | |
| | | */ |
| | | public static Schema valueOf(Entry entry) |
| | | { |
| | | final SchemaBuilder builder = new SchemaBuilder(); |
| | | final SchemaBuilder builder = new SchemaBuilder(entry.getName() |
| | | .toString()); |
| | | |
| | | Attribute attr = entry.getAttribute(ATTR_LDAP_SYNTAXES); |
| | | if (attr != null) |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the default schema which should be used by this application. |
| | | * The default schema is initially set to the core schema. |
| | | * |
| | | * @param schema |
| | | * The default schema which should be used by this |
| | | * application. |
| | | */ |
| | | public static void setDefaultSchema(Schema schema) |
| | | // Constructs a search request for retrieving the subschemaSubentry |
| | | // attribute from the named entry. |
| | | private static SearchRequest getReadSchemaForEntrySearchRequest(DN dn) |
| | | { |
| | | DEFAULT_SCHEMA = schema; |
| | | return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT, |
| | | Filter.getObjectClassPresentFilter(), SUBSCHEMA_SUBENTRY_ATTRS); |
| | | } |
| | | |
| | | |
| | | |
| | | // Constructs a search request for retrieving the named subschema |
| | | // sub-entry. |
| | | private static SearchRequest getReadSchemaSearchRequest(DN dn) |
| | | { |
| | | return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT, |
| | | SUBSCHEMA_FILTER, SUBSCHEMA_ATTRS); |
| | | } |
| | | |
| | | |
| | | |
| | | private static DN getSubschemaSubentryDN(DN name, final Entry entry) |
| | | throws ErrorResultException |
| | | { |
| | | final Attribute subentryAttr = entry |
| | | .getAttribute(ATTR_SUBSCHEMA_SUBENTRY); |
| | | |
| | | if (subentryAttr == null || subentryAttr.isEmpty()) |
| | | { |
| | | // Did not get the subschema sub-entry attribute. |
| | | final Result result = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED) |
| | | .setDiagnosticMessage( |
| | | ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString()) |
| | | .toString()); |
| | | throw ErrorResultException.wrap(result); |
| | | } |
| | | |
| | | final String dnString = subentryAttr.iterator().next().toString(); |
| | | DN subschemaDN; |
| | | try |
| | | { |
| | | subschemaDN = DN.valueOf(dnString); |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | final Result result = Responses.newResult( |
| | | ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED) |
| | | .setDiagnosticMessage( |
| | | ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(), |
| | | dnString, e.getMessageObject()).toString()); |
| | | throw ErrorResultException.wrap(result); |
| | | } |
| | | return subschemaDN; |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | Schema(Map<String, Syntax> numericOID2Syntaxes, |
| | | private Schema(Impl impl) |
| | | { |
| | | this.impl = impl; |
| | | } |
| | | |
| | | |
| | | |
| | | Schema(String schemaName, Map<String, Syntax> numericOID2Syntaxes, |
| | | Map<String, MatchingRule> numericOID2MatchingRules, |
| | | Map<String, MatchingRuleUse> numericOID2MatchingRuleUses, |
| | | Map<String, AttributeType> numericOID2AttributeTypes, |
| | |
| | | Map<String, List<DITStructureRule>> nameForm2StructureRules, |
| | | SchemaCompatOptions options, List<LocalizableMessage> warnings) |
| | | { |
| | | impl = new StrictImpl(numericOID2Syntaxes, |
| | | impl = new StrictImpl(schemaName, numericOID2Syntaxes, |
| | | numericOID2MatchingRules, numericOID2MatchingRuleUses, |
| | | numericOID2AttributeTypes, numericOID2ObjectClasses, |
| | | numericOID2NameForms, numericOID2ContentRules, |
| | |
| | | |
| | | |
| | | |
| | | private Schema(Impl impl) |
| | | { |
| | | this.impl = impl; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the attribute type with the specified name or numeric OID. |
| | | * |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns the user-friendly name of this schema which may be used for |
| | | * debugging purposes. The format of the schema name is not defined |
| | | * but should contain the distinguished name of the subschema |
| | | * sub-entry for those schemas retrieved from a Directory Server. |
| | | * |
| | | * @return The user-friendly name of this schema which may be used for |
| | | * debugging purposes. |
| | | */ |
| | | public String getSchemaName() |
| | | { |
| | | return impl.getSchemaName(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the syntax with the specified numeric OID. |
| | | * |
| | | * @param numericOID |
| | |
| | | import static org.opends.sdk.schema.SchemaConstants.*; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.opends.sdk.DecodeException; |
| | | import org.opends.sdk.LocalizedIllegalArgumentException; |
| | | import org.opends.sdk.LocalizableMessage; |
| | | import org.opends.sdk.LocalizedIllegalArgumentException; |
| | | |
| | | import com.sun.opends.sdk.util.*; |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | | import com.sun.opends.sdk.util.SubstringReader; |
| | | import com.sun.opends.sdk.util.Validator; |
| | | |
| | | |
| | | |
| | |
| | | |
| | | private Schema schema; |
| | | |
| | | // A unique ID which can be used to uniquely identify schemas |
| | | // constructed without a name. |
| | | private final AtomicInteger nextSchemaID = new AtomicInteger(); |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public SchemaBuilder() |
| | | { |
| | | initBuilder(); |
| | | initBuilder(null); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public SchemaBuilder(Schema schema) throws NullPointerException |
| | | { |
| | | Validator.ensureNotNull(schema); |
| | | initBuilder(); |
| | | initBuilder(schema.getSchemaName()); |
| | | setSchemaCompatOptions(schema.getSchemaCompatOptions()); |
| | | addSchema(schema, true); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Creates a new schema builder with no schema elements and default |
| | | * compatibility options. |
| | | * |
| | | * @param schemaName |
| | | * The user-friendly name of this schema which may be used |
| | | * for debugging purposes. |
| | | */ |
| | | public SchemaBuilder(String schemaName) |
| | | { |
| | | initBuilder(schemaName); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the provided attribute type definition to this schema builder. |
| | | * |
| | | * @param definition |
| | |
| | | { |
| | | validate(); |
| | | final Schema builtSchema = schema; |
| | | initBuilder(); |
| | | initBuilder(null); |
| | | return builtSchema; |
| | | } |
| | | |
| | | |
| | | |
| | | void addWarning(LocalizableMessage warning) |
| | | { |
| | | warnings.add(warning); |
| | | } |
| | | |
| | | |
| | | |
| | | private synchronized void addAttributeType(AttributeType attribute, |
| | | boolean overwrite) throws ConflictingSchemaElementException |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | private void initBuilder() |
| | | private void initBuilder(String schemaName) |
| | | { |
| | | numericOID2Syntaxes = new HashMap<String, Syntax>(); |
| | | numericOID2MatchingRules = new HashMap<String, MatchingRule>(); |
| | |
| | | options = SchemaCompatOptions.defaultOptions(); |
| | | warnings = new LinkedList<LocalizableMessage>(); |
| | | |
| | | schema = new Schema(numericOID2Syntaxes, numericOID2MatchingRules, |
| | | numericOID2MatchingRuleUses, numericOID2AttributeTypes, |
| | | numericOID2ObjectClasses, numericOID2NameForms, |
| | | numericOID2ContentRules, id2StructureRules, name2MatchingRules, |
| | | name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses, |
| | | name2NameForms, name2ContentRules, name2StructureRules, |
| | | objectClass2NameForms, nameForm2StructureRules, options, |
| | | warnings); |
| | | if (schemaName == null) |
| | | { |
| | | schemaName = String.format("Schema#%d", nextSchemaID |
| | | .getAndIncrement()); |
| | | } |
| | | |
| | | schema = new Schema(schemaName, numericOID2Syntaxes, |
| | | numericOID2MatchingRules, numericOID2MatchingRuleUses, |
| | | numericOID2AttributeTypes, numericOID2ObjectClasses, |
| | | numericOID2NameForms, numericOID2ContentRules, |
| | | id2StructureRules, name2MatchingRules, name2MatchingRuleUses, |
| | | name2AttributeTypes, name2ObjectClasses, name2NameForms, |
| | | name2ContentRules, name2StructureRules, objectClass2NameForms, |
| | | nameForm2StructureRules, options, warnings); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | void addWarning(LocalizableMessage warning) |
| | | { |
| | | warnings.add(warning); |
| | | } |
| | | } |