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