001/* 002 * Copyright 2007-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2018 Ping Identity Corporation 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 */ 021package com.unboundid.ldap.sdk; 022 023 024 025import com.unboundid.util.ThreadSafety; 026import com.unboundid.util.ThreadSafetyLevel; 027 028import static com.unboundid.ldap.sdk.LDAPMessages.*; 029import static com.unboundid.util.StaticUtils.*; 030 031 032 033/** 034 * This enum defines a set of disconnect types that may be used to provide 035 * general information about the reason that an {@link LDAPConnection} was 036 * disconnected. Note that additional disconnect types may be added in the 037 * future, so any decision made based on a disconnect type should account for 038 * the possibility of previously-undefined disconnect types. 039 */ 040@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 041public enum DisconnectType 042{ 043 /** 044 * The connection was closed as a result of an unbind request sent by the 045 * client. 046 */ 047 UNBIND(INFO_DISCONNECT_TYPE_UNBIND.get(), ResultCode.LOCAL_ERROR), 048 049 050 051 /** 052 * The connection was closed at the request of the client, but without first 053 * sending an unbind request. 054 */ 055 CLOSED_WITHOUT_UNBIND(INFO_DISCONNECT_TYPE_CLOSED_WITHOUT_UNBIND.get(), 056 ResultCode.LOCAL_ERROR), 057 058 059 060 /** 061 * The connection was closed because a bind performed as part of the 062 * creation did not complete successfully. 063 */ 064 BIND_FAILED(INFO_DISCONNECT_TYPE_BIND_FAILED.get(), 065 ResultCode.CONNECT_ERROR), 066 067 068 069 /** 070 * The connection was closed because it is going to be re-established. 071 */ 072 RECONNECT(INFO_DISCONNECT_TYPE_RECONNECT.get(), ResultCode.SERVER_DOWN), 073 074 075 076 /** 077 * The connection was closed because it had been a temporary connection 078 * created for following a referral and was no longer needed. 079 */ 080 REFERRAL(INFO_DISCONNECT_TYPE_REFERRAL.get(), ResultCode.LOCAL_ERROR), 081 082 083 084 /** 085 * The connection was closed by the server, and a notice of disconnection 086 * unsolicited notification was provided. 087 */ 088 SERVER_CLOSED_WITH_NOTICE( 089 INFO_DISCONNECT_TYPE_SERVER_CLOSED_WITH_NOTICE.get(), 090 ResultCode.SERVER_DOWN), 091 092 093 094 /** 095 * The connection was closed by the server without a notice of disconnection. 096 */ 097 SERVER_CLOSED_WITHOUT_NOTICE( 098 INFO_DISCONNECT_TYPE_SERVER_CLOSED_WITHOUT_NOTICE.get(), 099 ResultCode.SERVER_DOWN), 100 101 102 103 /** 104 * The connection was closed because an I/O problem was encountered while 105 * trying to communicate with the server. 106 */ 107 IO_ERROR(INFO_DISCONNECT_TYPE_IO_ERROR.get(), ResultCode.SERVER_DOWN), 108 109 110 111 /** 112 * The connection was closed because an error occurred while trying to decode 113 * data from the server. 114 */ 115 DECODE_ERROR(INFO_DISCONNECT_TYPE_DECODE_ERROR.get(), 116 ResultCode.DECODING_ERROR), 117 118 119 120 /** 121 * The connection was closed because an unexpected error occurred within the 122 * LDAP SDK. 123 */ 124 LOCAL_ERROR(INFO_DISCONNECT_TYPE_LOCAL_ERROR.get(), ResultCode.LOCAL_ERROR), 125 126 127 128 /** 129 * The connection was closed because a problem was encountered while 130 * negotiating a security layer with the server. 131 */ 132 SECURITY_PROBLEM(INFO_DISCONNECT_TYPE_SECURITY_PROBLEM.get(), 133 ResultCode.LOCAL_ERROR), 134 135 136 137 /** 138 * The connection was closed because it was part of a connection pool that 139 * was closed. 140 */ 141 POOL_CLOSED(INFO_DISCONNECT_TYPE_POOL_CLOSED.get(), ResultCode.LOCAL_ERROR), 142 143 144 145 /** 146 * The connection was closed because it was part of a connection pool that 147 * was being initialized and a failure occurred while attempting to create 148 * another connection as part of the pool. 149 */ 150 POOL_CREATION_FAILURE(INFO_DISCONNECT_TYPE_POOL_CREATION_FAILURE.get(), 151 ResultCode.CONNECT_ERROR), 152 153 154 155 /** 156 * The connection was closed because it was part of a connection pool and had 157 * been classified as defunct. 158 */ 159 POOLED_CONNECTION_DEFUNCT( 160 INFO_DISCONNECT_TYPE_POOLED_CONNECTION_DEFUNCT.get(), 161 ResultCode.SERVER_DOWN), 162 163 164 165 /** 166 * The connection was closed because it was part of a connection pool and the 167 * connection had been established for longer than the maximum connection 168 * age for the pool. 169 */ 170 POOLED_CONNECTION_EXPIRED( 171 INFO_DISCONNECT_TYPE_POOLED_CONNECTION_EXPIRED.get(), 172 ResultCode.LOCAL_ERROR), 173 174 175 176 /** 177 * The connection was closed because it was part of a connection pool and was 178 * no longer needed. 179 */ 180 POOLED_CONNECTION_UNNEEDED( 181 INFO_DISCONNECT_TYPE_POOLED_CONNECTION_UNNEEDED.get(), 182 ResultCode.LOCAL_ERROR), 183 184 185 186 /** 187 * The reason for the disconnect is not known. This generally indicates a 188 * problem with inappropriate instrumentation in the LDAP SDK. 189 */ 190 UNKNOWN(INFO_DISCONNECT_TYPE_UNKNOWN.get(), ResultCode.LOCAL_ERROR), 191 192 193 194 /** 195 * The connection was closed by a finalizer in the LDAP SDK, which indicates 196 * that it was not properly closed by the application that had been using 197 * it. 198 */ 199 CLOSED_BY_FINALIZER(INFO_DISCONNECT_TYPE_CLOSED_BY_FINALIZER.get(), 200 ResultCode.LOCAL_ERROR), 201 202 203 204 /** 205 * The connection was closed for a reason that does not fit any other 206 * defined disconnect type. 207 */ 208 OTHER(INFO_DISCONNECT_TYPE_OTHER.get(), ResultCode.LOCAL_ERROR); 209 210 211 212 // The result code most closely associated with this disconnect type. 213 private final ResultCode resultCode; 214 215 // A description for this disconnect type. 216 private final String description; 217 218 219 220 /** 221 * Creates a new disconnect type with the specified description. 222 * 223 * @param description The description for this disconnect type. 224 * @param resultCode The result code most closely associated with this 225 * disconnect type. 226 */ 227 DisconnectType(final String description, final ResultCode resultCode) 228 { 229 this.description = description; 230 this.resultCode = resultCode; 231 } 232 233 234 235 /** 236 * Retrieves the description for this disconnect type. 237 * 238 * @return The description for this disconnect type. 239 */ 240 public String getDescription() 241 { 242 return description; 243 } 244 245 246 247 /** 248 * Retrieves the result code most closely associated with this disconnect 249 * type. 250 * 251 * @return The result code most closely associated with this disconnect type. 252 */ 253 public ResultCode getResultCode() 254 { 255 return resultCode; 256 } 257 258 259 260 /** 261 * Retrieves the disconnect type with the specified name. 262 * 263 * @param name The name of the disconnect type to retrieve. 264 * 265 * @return The requested change type, or {@code null} if no such 266 * disconnect type is defined. 267 */ 268 public static DisconnectType forName(final String name) 269 { 270 switch (toLowerCase(name)) 271 { 272 case "unbind": 273 return UNBIND; 274 case "closedwithoutunbind": 275 case "closed-without-unbind": 276 case "closed_without_unbind": 277 return CLOSED_WITHOUT_UNBIND; 278 case "bindfailed": 279 case "bind-failed": 280 case "bind_failed": 281 return BIND_FAILED; 282 case "reconnect": 283 return RECONNECT; 284 case "referral": 285 return REFERRAL; 286 case "serverclosedwithnotice": 287 case "server-closed-with-notice": 288 case "server_closed_with_notice": 289 return SERVER_CLOSED_WITH_NOTICE; 290 case "serverclosedwithoutnotice": 291 case "server-closed-without-notice": 292 case "server_closed_without_notice": 293 return SERVER_CLOSED_WITHOUT_NOTICE; 294 case "ioerror": 295 case "io-error": 296 case "io_error": 297 return IO_ERROR; 298 case "decodeerror": 299 case "decode-error": 300 case "decode_error": 301 return DECODE_ERROR; 302 case "localerror": 303 case "local-error": 304 case "local_error": 305 return LOCAL_ERROR; 306 case "securityproblem": 307 case "security-problem": 308 case "security_problem": 309 return SECURITY_PROBLEM; 310 case "poolclosed": 311 case "pool-closed": 312 case "pool_closed": 313 return POOL_CLOSED; 314 case "poolcreationfailure": 315 case "pool-creation-failure": 316 case "pool_creation_failure": 317 return POOL_CREATION_FAILURE; 318 case "pooledconnectiondefunct": 319 case "pooled-connection-defunct": 320 case "pooled_connection_defunct": 321 return POOLED_CONNECTION_DEFUNCT; 322 case "pooledconnectionexpired": 323 case "pooled-connection-expired": 324 case "pooled_connection_expired": 325 return POOLED_CONNECTION_EXPIRED; 326 case "pooledconnectionunneeded": 327 case "pooled-connection-unneeded": 328 case "pooled_connection_unneeded": 329 return POOLED_CONNECTION_UNNEEDED; 330 case "unknown": 331 return UNKNOWN; 332 case "closedbyfinalizer": 333 case "closed-by-finalizer": 334 case "closed_by_finalizer": 335 return CLOSED_BY_FINALIZER; 336 case "other": 337 return OTHER; 338 default: 339 return null; 340 } 341 } 342 343 344 345 /** 346 * Indicates whether the provided disconnect type is likely one that is 347 * expected in some way. This includes the following: 348 * <UL> 349 * <LI>Connections closed by the application.</LI> 350 * <LI>Connections which are managed as part of a connection pool.</LI> 351 * <LI>Temporary connections created for following a referral.</LI> 352 * <LI>Connections which are being closed by the SDK so they can be 353 * re-established.</LI> 354 * <LI>Connections that were not properly closed by the application but are 355 * no longer in use and are being closed by a finalizer.</LI> 356 * </UL> 357 * 358 * @param disconnectType The disconnect type for which to make the 359 * determination. 360 * 361 * @return {@code true} if the connection is one that can be classified as 362 * expected and there is likely nothing that a disconnect handler 363 * needs to do to handle it, or {@code false} if not. 364 */ 365 public static boolean isExpected(final DisconnectType disconnectType) 366 { 367 switch (disconnectType) 368 { 369 case UNBIND: 370 case CLOSED_WITHOUT_UNBIND: 371 case RECONNECT: 372 case REFERRAL: 373 case POOL_CLOSED: 374 case POOLED_CONNECTION_DEFUNCT: 375 case POOLED_CONNECTION_EXPIRED: 376 case POOLED_CONNECTION_UNNEEDED: 377 case CLOSED_BY_FINALIZER: 378 return true; 379 default: 380 return false; 381 } 382 } 383 384 385 386 /** 387 * Retrieves a string representation for this disconnect type. 388 * 389 * @return A string representation for this disconnect type. 390 */ 391 @Override() 392 public String toString() 393 { 394 final StringBuilder buffer = new StringBuilder(); 395 toString(buffer); 396 return buffer.toString(); 397 } 398 399 400 401 /** 402 * Appends a string representation of this disconnect type to the provided 403 * buffer. 404 * 405 * @param buffer The buffer to which the string representation should be 406 * appended. 407 */ 408 public void toString(final StringBuilder buffer) 409 { 410 buffer.append("DisconnectType(name='"); 411 buffer.append(name()); 412 buffer.append("', resultCode='"); 413 buffer.append(resultCode); 414 buffer.append("', description='"); 415 buffer.append(description); 416 buffer.append("')"); 417 } 418}