/** {@inheritDoc} */ @Override public void addCancelRequestListener(final CancelRequestListener listener) { Reject.ifNull(listener); boolean invokeImmediately = false; synchronized (stateLock) { switch (state) { case PENDING: if (cancelRequestListeners == null) { cancelRequestListeners = new LinkedList<>(); } cancelRequestListeners.add(listener); break; case CANCEL_REQUESTED: // Signal immediately outside lock. invokeImmediately = true; break; case TOO_LATE: case RESULT_SENT: case CANCELLED: /* * No point in registering the callback since the request * can never be cancelled now. */ break; } } if (invokeImmediately) { listener.handleCancelRequest(cancelRequestReason); } }
private <R extends ExtendedResult> void cancel( final LocalizableMessage reason, final ExtendedRequest<R> cancelRequest, final LdapResultHandler<R> cancelResultHandler, final boolean sendResult) { Reject.ifNull(reason); if (!isCancelSupported) { if (cancelResultHandler != null) { final Result result = Responses.newGenericExtendedResult(ResultCode.CANNOT_CANCEL); cancelResultHandler.handleException(newLdapException(result)); } return; } List<CancelRequestListener> tmpListeners = null; boolean invokeResultHandler = false; boolean resultHandlerIsSuccess = false; synchronized (stateLock) { switch (state) { case PENDING: /* Switch to CANCEL_REQUESTED state. */ cancelRequestReason = reason; if (cancelResultHandler != null) { cancelResultHandlers = new LinkedList<>(); cancelResultHandlers.add( new ExtendedResultHandlerHolder<R>(cancelRequest, cancelResultHandler)); } tmpListeners = cancelRequestListeners; cancelRequestListeners = null; state = RequestState.CANCEL_REQUESTED; this.sendResult &= sendResult; break; case CANCEL_REQUESTED: /* * Cancel already request so listeners already invoked. */ if (cancelResultHandler != null) { if (cancelResultHandlers == null) { cancelResultHandlers = new LinkedList<>(); } cancelResultHandlers.add( new ExtendedResultHandlerHolder<R>(cancelRequest, cancelResultHandler)); } break; case TOO_LATE: case RESULT_SENT: /* * Cannot cancel, so invoke result handler immediately * outside of lock. */ if (cancelResultHandler != null) { invokeResultHandler = true; resultHandlerIsSuccess = false; } break; case CANCELLED: /* * Multiple cancellation attempts. Clients should not do * this, but the cancel will effectively succeed * immediately, so invoke result handler immediately outside * of lock. */ if (cancelResultHandler != null) { invokeResultHandler = true; resultHandlerIsSuccess = true; } break; } } /* Invoke listeners outside of lock. */ if (tmpListeners != null) { for (final CancelRequestListener listener : tmpListeners) { listener.handleCancelRequest(reason); } } if (invokeResultHandler) { if (resultHandlerIsSuccess) { final R result = cancelRequest.getResultDecoder().newExtendedErrorResult(ResultCode.SUCCESS, "", ""); cancelResultHandler.handleResult(result); } else { final Result result = Responses.newGenericExtendedResult(ResultCode.TOO_LATE); cancelResultHandler.handleException(newLdapException(result)); } } }