001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2014-2015 ForgeRock AS. 025 */ 026package org.forgerock.opendj.ldap.spi; 027 028import org.forgerock.opendj.ldap.Connection; 029import org.forgerock.opendj.ldap.IntermediateResponseHandler; 030import org.forgerock.opendj.ldap.LdapException; 031import org.forgerock.opendj.ldap.LdapPromise; 032import org.forgerock.opendj.ldap.ResultCode; 033import org.forgerock.opendj.ldap.SearchResultHandler; 034import org.forgerock.opendj.ldap.requests.BindClient; 035import org.forgerock.opendj.ldap.requests.BindRequest; 036import org.forgerock.opendj.ldap.requests.CompareRequest; 037import org.forgerock.opendj.ldap.requests.ExtendedRequest; 038import org.forgerock.opendj.ldap.requests.Request; 039import org.forgerock.opendj.ldap.requests.SearchRequest; 040import org.forgerock.opendj.ldap.responses.CompareResult; 041import org.forgerock.opendj.ldap.responses.ExtendedResult; 042import org.forgerock.opendj.ldap.responses.Result; 043import org.forgerock.util.promise.Promise; 044import org.forgerock.util.promise.Promises; 045 046import static org.forgerock.opendj.ldap.responses.Responses.*; 047 048/** 049 * Utility methods for creating and composing {@link LdapPromise}s. 050 */ 051public final class LdapPromises { 052 /** 053 * Returns a {@link LdapPromise} representing an asynchronous task which has 054 * already succeeded with the provided result. Attempts to get the result 055 * will immediately return the result. 056 * 057 * @param <R> 058 * The type of the task's result, or {@link Void} if the task 059 * does not return anything (i.e. it only has side-effects). 060 * @param result 061 * The result of the asynchronous task. 062 * @return A {@link LdapPromise} representing an asynchronous task which has 063 * already succeeded with the provided result. 064 */ 065 public static <R> LdapPromise<R> newSuccessfulLdapPromise(final R result) { 066 return wrap(Promises.<R, LdapException> newResultPromise(result), -1); 067 } 068 069 /** 070 * Returns a {@link LdapPromise} representing an asynchronous task, 071 * identified by the provided requestID, which has already succeeded with 072 * the provided result. Attempts to get the result will immediately return 073 * the result. 074 * 075 * @param <R> 076 * The type of the task's result, or {@link Void} if the task 077 * does not return anything (i.e. it only has side-effects). 078 * @param result 079 * The result of the asynchronous task. 080 * @param requestID 081 * The request ID of the succeeded task. 082 * @return A {@link LdapPromise} representing an asynchronous task which has 083 * already succeeded with the provided result. 084 */ 085 public static <R> LdapPromise<R> newSuccessfulLdapPromise(final R result, int requestID) { 086 return wrap(Promises.<R, LdapException> newResultPromise(result), requestID); 087 } 088 089 /** 090 * Returns a {@link LdapPromise} representing an asynchronous task which has 091 * already failed with the provided error. 092 * 093 * @param <R> 094 * The type of the task's result, or {@link Void} if the task 095 * does not return anything (i.e. it only has side-effects). 096 * @param <E> 097 * The type of the exception thrown by the task if it fails. 098 * @param error 099 * The exception indicating why the asynchronous task has failed. 100 * @return A {@link LdapPromise} representing an asynchronous task which has 101 * already failed with the provided error. 102 */ 103 public static <R, E extends LdapException> LdapPromise<R> newFailedLdapPromise(final E error) { 104 return wrap(Promises.<R, LdapException> newExceptionPromise(error), -1); 105 } 106 107 /** 108 * Returns a {@link LdapPromise} representing an asynchronous task, 109 * identified by the provided requestID, which has already failed with the 110 * provided error. 111 * 112 * @param <R> 113 * The type of the task's result, or {@link Void} if the task 114 * does not return anything (i.e. it only has side-effects). 115 * @param <E> 116 * The type of the exception thrown by the task if it fails. 117 * @param error 118 * The exception indicating why the asynchronous task has failed. 119 * @param requestID 120 * The request ID of the failed task. 121 * @return A {@link LdapPromise} representing an asynchronous task which has 122 * already failed with the provided error. 123 */ 124 public static <R, E extends LdapException> LdapPromise<R> newFailedLdapPromise(final E error, int requestID) { 125 return wrap(Promises.<R, LdapException> newExceptionPromise(error), requestID); 126 } 127 128 /** 129 * Creates a new {@link ResultLdapPromiseImpl} to handle a standard request (add, delete, modify and modidyDN). 130 * 131 * @param <R> 132 * The type of the task's request. 133 * 134 * @param requestID 135 * Identifier of the request. 136 * @param request 137 * The request sent to the server. 138 * @param intermediateResponseHandler 139 * Handler that consumes intermediate responses from extended operations. 140 * @param connection 141 * The connection to directory server. 142 * 143 * @return The new {@link ResultLdapPromiseImpl}. 144 */ 145 public static <R extends Request> ResultLdapPromiseImpl<R, Result> newResultLdapPromise(final int requestID, 146 final R request, final IntermediateResponseHandler intermediateResponseHandler, 147 final Connection connection) { 148 return new ResultLdapPromiseImpl<R, Result>(requestID, request, intermediateResponseHandler, connection) { 149 @Override 150 protected Result newErrorResult(ResultCode resultCode, String diagnosticMessage, Throwable cause) { 151 return newResult(resultCode).setDiagnosticMessage(diagnosticMessage).setCause(cause); 152 } 153 }; 154 } 155 156 /** 157 * Creates a new bind {@link BindResultLdapPromiseImpl}. 158 * 159 * @param requestID 160 * Identifier of the request. 161 * @param request 162 * The bind request sent to server. 163 * @param bindClient 164 * Client that binds to the server. 165 * @param intermediateResponseHandler 166 * Handler that consumes intermediate responses from extended operations. 167 * @param connection 168 * The connection to directory server. 169 * 170 * @return The new {@link BindResultLdapPromiseImpl}. 171 */ 172 public static BindResultLdapPromiseImpl newBindLdapPromise(final int requestID, 173 final BindRequest request, final BindClient bindClient, 174 final IntermediateResponseHandler intermediateResponseHandler, final Connection connection) { 175 return new BindResultLdapPromiseImpl(requestID, request, bindClient, intermediateResponseHandler, connection); 176 } 177 178 /** 179 * Creates a new compare {@link ResultLdapPromiseImpl}. 180 * 181 * @param requestID 182 * Identifier of the request. 183 * @param request 184 * The compare request sent to the server. 185 * @param intermediateResponseHandler 186 * Handler that consumes intermediate responses from extended operations. 187 * @param connection 188 * The connection to directory server. 189 * 190 * @return The new {@link ResultLdapPromiseImpl}. 191 */ 192 public static ResultLdapPromiseImpl<CompareRequest, CompareResult> newCompareLdapPromise(final int requestID, 193 final CompareRequest request, final IntermediateResponseHandler intermediateResponseHandler, 194 final Connection connection) { 195 return new ResultLdapPromiseImpl<CompareRequest, CompareResult>(requestID, request, intermediateResponseHandler, 196 connection) { 197 @Override 198 protected CompareResult newErrorResult(ResultCode resultCode, String diagnosticMessage, Throwable cause) { 199 return newCompareResult(resultCode).setDiagnosticMessage(diagnosticMessage).setCause(cause); 200 } 201 }; 202 } 203 204 /** 205 * Creates a new extended {@link ExtendedResultLdapPromiseImpl}. 206 * 207 * @param <S> 208 * The type of result returned by this promise. 209 * @param requestID 210 * Identifier of the request. 211 * @param request 212 * The extended request sent to the server. 213 * @param intermediateResponseHandler 214 * Handler that consumes intermediate responses from extended operations. 215 * @param connection 216 * The connection to directory server. 217 * 218 * @return The new {@link ExtendedResultLdapPromiseImpl}. 219 */ 220 public static <S extends ExtendedResult> ExtendedResultLdapPromiseImpl<S> newExtendedLdapPromise( 221 final int requestID, final ExtendedRequest<S> request, 222 final IntermediateResponseHandler intermediateResponseHandler, final Connection connection) { 223 return new ExtendedResultLdapPromiseImpl<>(requestID, request, intermediateResponseHandler, connection); 224 } 225 226 /** 227 * Creates a new search {@link SearchResultLdapPromiseImpl}. 228 * 229 * @param requestID 230 * Identifier of the request. 231 * @param request 232 * The search request sent to the server. 233 * @param resultHandler 234 * Handler that consumes search result. 235 * @param intermediateResponseHandler 236 * Handler that consumes intermediate responses from extended operations. 237 * @param connection 238 * The connection to directory server. 239 * 240 * @return The new {@link SearchResultLdapPromiseImpl}. 241 */ 242 public static SearchResultLdapPromiseImpl newSearchLdapPromise(final int requestID, final SearchRequest request, 243 final SearchResultHandler resultHandler, final IntermediateResponseHandler intermediateResponseHandler, 244 final Connection connection) { 245 return new SearchResultLdapPromiseImpl(requestID, request, resultHandler, intermediateResponseHandler, 246 connection); 247 } 248 249 250 251 /** 252 * Converts a {@link Promise} to a {@link LdapPromise}. 253 * 254 * @param <R> 255 * The type of the task's result, or {@link Void} if the task 256 * does not return anything (i.e. it only has side-effects). 257 * @param wrappedPromise 258 * The {@link Promise} to wrap. 259 * @return A {@link LdapPromise} representing the same asynchronous task as 260 * the {@link Promise} provided. 261 */ 262 public static <R> LdapPromise<R> asPromise(Promise<R, LdapException> wrappedPromise) { 263 return wrap(wrappedPromise, -1); 264 } 265 266 static <R> LdapPromise<R> wrap(Promise<R, LdapException> wrappedPromise, int requestID) { 267 return new LdapPromiseWrapper<>(wrappedPromise, requestID); 268 } 269 270 private LdapPromises() { 271 } 272 273}