001 /*
002 * Copyright 2009-2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2009-2016 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk;
022
023
024
025 import com.unboundid.util.Extensible;
026 import com.unboundid.util.ThreadSafety;
027 import com.unboundid.util.ThreadSafetyLevel;
028
029 import static com.unboundid.ldap.sdk.LDAPMessages.*;
030 import static com.unboundid.util.StaticUtils.*;
031
032
033
034 /**
035 * This class provides an API that may be used to determine whether connections
036 * associated with a connection pool are valid and suitable for use. It
037 * provides the ability to check the validity of a connection at the following
038 * times:
039 * <UL>
040 * <LI>Whenever a new connection is created for use in the pool, the
041 * {@link #ensureNewConnectionValid(LDAPConnection)} method will be called
042 * before making that connection available. The default implementation
043 * provided in this class does not perform any kind of processing, but
044 * subclasses may override this behavior if desired.</LI>
045 * <LI>Whenever a connection is checked out from the pool (including
046 * connections checked out internally for operations performed in the
047 * pool), the {@link #ensureConnectionValidForCheckout(LDAPConnection)}
048 * method will be called. The default implementation provided in this
049 * class does not perform any kind of processing, but subclasses may
050 * override this behavior if desired.</LI>
051 * <LI>Whenever a connection is released back to the pool (including
052 * connections checked out internally for operations performed in the
053 * pool), the {@link #ensureConnectionValidForRelease(LDAPConnection)}
054 * method will be called. The default implementation provided in this
055 * class does not perform any kind of processing, but subclasses may
056 * override this behavior if desired.</LI>
057 * <LI>The {@link #ensureConnectionValidForContinuedUse(LDAPConnection)}
058 * method will be invoked periodically by a background thread created by
059 * the connection pool to determine whether available connections within
060 * the pool are still valid. The default implementation provided in this
061 * class does not perform any kind of processing, but subclasses may
062 * override this behavior if desired.</LI>
063 * <LI>The {@link #ensureConnectionValidAfterException} method may be invoked
064 * if an exception is caught while processing an operation with a
065 * connection that is part of a connection pool. The default
066 * implementation provided in this class only examines the result code of
067 * the provided exception and uses the
068 * {@link ResultCode#isConnectionUsable(ResultCode)} method to make the
069 * determination, but subclasses may override this behavior if
070 * desired.</LI>
071 * </UL>
072 * Note that health check implementations should be designed so that they are
073 * suitable for use with connections having any authentication state. The
074 * {@link #ensureNewConnectionValid(LDAPConnection)} method will be invoked on
075 * unauthenticated connections, and the remaining health check methods will be
076 * invoked using whatever credentials are assigned to connections in the
077 * associated connection pool.
078 */
079 @Extensible()
080 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
081 public class LDAPConnectionPoolHealthCheck
082 {
083 /**
084 * Creates a new instance of this LDAP connection pool health check.
085 */
086 public LDAPConnectionPoolHealthCheck()
087 {
088 // No implementation is required.
089 }
090
091
092
093 /**
094 * Performs any desired processing to determine whether the provided new
095 * connection is available to be checked out and used for processing
096 * operations. This method will be invoked by either {@link ServerSet} used
097 * by the connection pool (if it supports enhanced health checking) or by the
098 * connection pool itself at the time that a new connection is created. No
099 * authentication will have been performed on this connection at the time the
100 * health check is invoked.
101 *
102 * @param connection The connection to be examined.
103 *
104 * @throws LDAPException If a problem is detected that suggests that the
105 * provided connection is not suitable for use.
106 */
107 public void ensureNewConnectionValid(final LDAPConnection connection)
108 throws LDAPException
109 {
110 // No processing is performed in this default implementation.
111 }
112
113
114
115 /**
116 * Performs any desired processing to determine whether the provided
117 * connection is valid after processing a bind operation with the provided
118 * result.
119 * <BR><BR>
120 * This method will be invoked under the following circumstances:
121 * <UL>
122 * <LI>
123 * If you create a connection pool with a {@link ServerSet} and a
124 * non-{@code null} {@link BindRequest}, then this health check method
125 * will be invoked for every new connection created by the pool after
126 * processing that {@code BindRequest} on the connection. If you create a
127 * connection pool with a {@code ServerSet} but a {@code null}
128 * {@code BindRequest}, then no authentication will be attempted (and
129 * therefore this health check method will not be invoked for)
130 * newly-created connections.
131 * </LI>
132 * <LI>
133 * If you create a connection pool with an {@link LDAPConnection} after
134 * having performed a bind operation on that connection, then every new
135 * connection created by the pool will attempt to perform the same type of
136 * bind operation and this health check method will be invoked after that
137 * bind attempt has completed. If you create a connection pool with an
138 * {@code LDAPConnection} that has not been authenticated, then no
139 * authentication will be attempted (and therefore this health check
140 * method will not be invoked for) newly-created connections.
141 * </LI>
142 * <LI>
143 * If you call a connection pool's {@code bindAndRevertAuthentication}
144 * method, then this health check method will be called after the second
145 * bind operation (the one used to revert authentication) has completed.
146 * In this case, this health check method will be called even if the
147 * connection pool was created with a {@code null} {@code BindRequest} or
148 * with an unauthenticated {@code LDAPConnection}. In that case, the
149 * bind operation used to revert authentication will be a
150 * {@link SimpleBindRequest} with an empty DN and password.
151 * </LI>
152 * <LI>
153 * If you call a connection pool's
154 * {@code releaseAndReAuthenticateConnection} method, then this health
155 * check method will be called after the bind operation has completed. As
156 * with {@code bindAndRevertAuthentication}, this health check method will
157 * be called even if the connection pool was created with a {@code null}
158 * {@code BindRequest} or with an unauthenticated {@code LDAPConnection}.
159 * </LI>
160 * </UL>
161 * <BR><BR>
162 * Note that this health check method may be invoked even if the bind
163 * attempt was not successful. This is useful because it allows the health
164 * check to intercept a failed authentication attempt and differentiate it
165 * from other types of failures in the course of trying to create or check out
166 * a connection. In the event that it is invoked with a {@code BindResult}
167 * that has a result code other than {@link ResultCode#SUCCESS}, if this
168 * method throws an exception then that exception will be propagated to the
169 * caller. If this method does not throw an exception when provided with a
170 * non-{@code SUCCESS} result, then the connection pool itself will throw an
171 * exception using the information in the bind result.
172 *
173 * @param connection The connection to be examined.
174 * @param bindResult The bind result obtained from the authentication
175 * process.
176 *
177 * @throws LDAPException If a problem is detected that suggests that the
178 * provided connection is not suitable for use.
179 */
180 public void ensureConnectionValidAfterAuthentication(
181 final LDAPConnection connection,
182 final BindResult bindResult)
183 throws LDAPException
184 {
185 // No processing is performed in this default implementation.
186 }
187
188
189
190 /**
191 * Performs any desired processing to determine whether the provided
192 * connection is available to be checked out and used for processing
193 * operations. This method will be invoked by the
194 * {@link LDAPConnectionPool#getConnection()} method before handing out a
195 * connection. This method should return normally if the connection is
196 * believed to be valid, or should throw an {@code LDAPException} if a problem
197 * is detected.
198 *
199 * @param connection The connection to be examined.
200 *
201 * @throws LDAPException If a problem is detected that suggests that the
202 * provided connection is not suitable for use.
203 */
204 public void ensureConnectionValidForCheckout(final LDAPConnection connection)
205 throws LDAPException
206 {
207 // No processing is performed in this default implementation.
208 }
209
210
211
212 /**
213 * Performs any desired processing to determine whether the provided
214 * connection is valid and should be released back to the pool to be used for
215 * processing other operations. This method will be invoked by the
216 * {@link LDAPConnectionPool#releaseConnection(LDAPConnection)} method before
217 * making the connection available for use in processing other operations.
218 * This method should return normally if the connection is believed to be
219 * valid, or should throw an {@code LDAPException} if a problem is detected.
220 *
221 * @param connection The connection to be examined.
222 *
223 * @throws LDAPException If a problem is detected that suggests that the
224 * provided connection is not suitable for use.
225 */
226 public void ensureConnectionValidForRelease(final LDAPConnection connection)
227 throws LDAPException
228 {
229 // No processing is performed in this default implementation.
230 }
231
232
233
234 /**
235 * Performs any desired processing to determine whether the provided
236 * connection is valid and should continue to be made available for
237 * processing operations. This method will be periodically invoked by a
238 * background thread used to test availability of connections within the pool.
239 * This method should return normally if the connection is believed to be
240 * valid, or should throw an {@code LDAPException} if a problem is detected.
241 *
242 * @param connection The connection to be examined.
243 *
244 * @throws LDAPException If a problem is detected that suggests that the
245 * provided connection is not suitable for use.
246 */
247 public void ensureConnectionValidForContinuedUse(
248 final LDAPConnection connection)
249 throws LDAPException
250 {
251 // No processing is performed in this default implementation.
252 }
253
254
255
256 /**
257 * Indicates whether the provided connection may still be considered valid
258 * after an attempt to process an operation yielded the given exception. This
259 * method will be invoked by the
260 * {@link LDAPConnectionPool#releaseConnectionAfterException} method, and it
261 * may also be manually invoked by external callers if an exception is
262 * encountered while processing an operation on a connection checked out from
263 * the pool. It may make a determination based solely on the provided
264 * exception, or it may also attempt to use the provided connection to further
265 * test its validity. This method should return normally if the connection is
266 * believed to be valid, or should throw an {@code LDAPException} if a problem
267 * is detected.
268 *
269 * @param connection The connection to be examined.
270 * @param exception The exception that was caught while processing an
271 * operation on the connection.
272 *
273 * @throws LDAPException If a problem is detected that suggests that the
274 * provided connection is not suitable for use.
275 */
276 public void ensureConnectionValidAfterException(
277 final LDAPConnection connection,
278 final LDAPException exception)
279 throws LDAPException
280 {
281 if (! ResultCode.isConnectionUsable(exception.getResultCode()))
282 {
283 throw new LDAPException(ResultCode.SERVER_DOWN,
284 ERR_POOL_HEALTH_CHECK_CONN_INVALID_AFTER_EXCEPTION.get(
285 getExceptionMessage(exception)),
286 exception);
287 }
288 }
289
290
291
292 /**
293 * Retrieves a string representation of this LDAP connection pool health
294 * check.
295 *
296 * @return A string representation of this LDAP connection pool health check.
297 */
298 @Override()
299 public final String toString()
300 {
301 final StringBuilder buffer = new StringBuilder();
302 toString(buffer);
303 return buffer.toString();
304 }
305
306
307
308 /**
309 * Appends a string representation of this LDAP connection pool health check
310 * to the provided buffer.
311 *
312 * @param buffer The buffer to which the information should be appended.
313 */
314 public void toString(final StringBuilder buffer)
315 {
316 buffer.append("LDAPConnectionPoolHealthCheck()");
317 }
318 }