001 /*
002 * Copyright 2009-2012 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2009-2012 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 java.util.ArrayList;
026 import java.util.Collection;
027 import java.util.EnumSet;
028 import java.util.List;
029 import java.util.Set;
030
031 import com.unboundid.asn1.ASN1OctetString;
032 import com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest;
033 import com.unboundid.ldap.sdk.schema.Schema;
034 import com.unboundid.ldif.LDIFException;
035 import com.unboundid.util.NotExtensible;
036 import com.unboundid.util.ThreadSafety;
037 import com.unboundid.util.ThreadSafetyLevel;
038
039 import static com.unboundid.ldap.sdk.LDAPMessages.*;
040 import static com.unboundid.util.Debug.*;
041 import static com.unboundid.util.StaticUtils.*;
042 import static com.unboundid.util.Validator.*;
043
044
045
046 /**
047 * This class provides the base class for LDAP connection pool implementations
048 * provided by the LDAP SDK for Java.
049 */
050 @NotExtensible()
051 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_NOT_THREADSAFE)
052 public abstract class AbstractConnectionPool
053 implements LDAPInterface
054 {
055 /**
056 * Closes this connection pool. All connections currently held in the pool
057 * that are not in use will be closed, and any outstanding connections will be
058 * automatically closed when they are released back to the pool.
059 */
060 public abstract void close();
061
062
063
064 /**
065 * Indicates whether this connection pool has been closed.
066 *
067 * @return {@code true} if this connection pool has been closed, or
068 * {@code false} if not.
069 */
070 public abstract boolean isClosed();
071
072
073
074 /**
075 * Retrieves an LDAP connection from the pool.
076 *
077 * @return The LDAP connection taken from the pool.
078 *
079 * @throws LDAPException If no connection is available, or a problem occurs
080 * while creating a new connection to return.
081 */
082 public abstract LDAPConnection getConnection()
083 throws LDAPException;
084
085
086
087 /**
088 * Releases the provided connection back to this pool.
089 *
090 * @param connection The connection to be released back to the pool.
091 */
092 public abstract void releaseConnection(final LDAPConnection connection);
093
094
095
096 /**
097 * Indicates that the provided connection is no longer in use, but is also no
098 * longer fit for use. The provided connection will be terminated and a new
099 * connection will be created and added to the pool in its place.
100 *
101 * @param connection The defunct connection being released.
102 */
103 public abstract void releaseDefunctConnection(
104 final LDAPConnection connection);
105
106
107
108 /**
109 * Releases the provided connection back to the pool after an exception has
110 * been encountered while processing an operation on that connection. The
111 * connection pool health check instance associated with this pool will be
112 * used to determine whether the provided connection is still valid and will
113 * either release it back for use in processing other operations on the
114 * connection or will terminate the connection and create a new one to take
115 * its place.
116 *
117 * @param connection The connection to be evaluated and released back to the
118 * pool or replaced with a new connection.
119 * @param exception The exception caught while processing an operation on
120 * the connection.
121 */
122 public final void releaseConnectionAfterException(
123 final LDAPConnection connection,
124 final LDAPException exception)
125 {
126 final LDAPConnectionPoolHealthCheck healthCheck = getHealthCheck();
127
128 try
129 {
130 healthCheck.ensureConnectionValidAfterException(connection, exception);
131 releaseConnection(connection);
132 }
133 catch (LDAPException le)
134 {
135 debugException(le);
136 releaseDefunctConnection(connection);
137 }
138 }
139
140
141
142 /**
143 * Releases the provided connection as defunct and creates a new connection to
144 * replace it, if possible, optionally connected to a different directory
145 * server instance than the instance with which the original connection was
146 * established.
147 *
148 * @param connection The defunct connection to be replaced.
149 *
150 * @return The newly-created connection intended to replace the provided
151 * connection.
152 *
153 * @throws LDAPException If a problem is encountered while trying to create
154 * the new connection. Note that even if an exception
155 * is thrown, then the provided connection must have
156 * been properly released as defunct.
157 */
158 public abstract LDAPConnection replaceDefunctConnection(
159 final LDAPConnection connection)
160 throws LDAPException;
161
162
163
164 /**
165 * Attempts to replace the provided connection. However, if an exception is
166 * encountered while obtaining the new connection then an exception will be
167 * thrown based on the provided {@code Throwable} object.
168 *
169 * @param t The {@code Throwable} that was caught and prompted the
170 * connection to be replaced.
171 * @param connection The defunct connection to be replaced.
172 *
173 * @return The newly-created connection intended to replace the provided
174 * connection.
175 *
176 * @throws LDAPException If an exception is encountered while attempting to
177 * obtain the new connection. Note that this
178 * exception will be generated from the provided
179 * {@code Throwable} rather than based on the
180 * exception caught while trying to create the new
181 * connection.
182 */
183 private LDAPConnection replaceDefunctConnection(final Throwable t,
184 final LDAPConnection connection)
185 throws LDAPException
186 {
187 try
188 {
189 return replaceDefunctConnection(connection);
190 }
191 catch (final LDAPException le)
192 {
193 debugException(le);
194
195 if (t instanceof LDAPException)
196 {
197 throw (LDAPException) t;
198 }
199 else
200 {
201 throw new LDAPException(ResultCode.LOCAL_ERROR,
202 ERR_POOL_OP_EXCEPTION.get(getExceptionMessage(t)), t);
203 }
204 }
205 }
206
207
208
209 /**
210 * Indicates whether attempts to process operations should be retried on a
211 * newly-created connection if the initial attempt fails in a manner that
212 * indicates that the connection used to process that request may no longer
213 * be valid. Only a single retry will be attempted for any operation.
214 * <BR><BR>
215 * Note that this only applies to methods used to process operations in the
216 * context pool (e.g., using methods that are part of {@link LDAPInterface}),
217 * and will not automatically be used for operations processed on connections
218 * checked out of the pool.
219 * <BR><BR>
220 * This method is provided for the purpose of backward compatibility, but new
221 * functionality has been added to control retry on a per-operation-type
222 * basis via the {@link #setRetryFailedOperationsDueToInvalidConnections(Set)}
223 * method. If retry is enabled for any operation type, then this method will
224 * return {@code true}, and it will only return {@code false} if retry should
225 * not be used for any operation type. To determine the operation types for
226 * which failed operations may be retried, use the
227 * {@link #getOperationTypesToRetryDueToInvalidConnections()} method.
228 *
229 * @return {@code true} if the connection pool should attempt to retry
230 * operations on a newly-created connection if they fail in a way
231 * that indicates the associated connection may no longer be usable,
232 * or {@code false} if operations should only be attempted once.
233 */
234 public final boolean retryFailedOperationsDueToInvalidConnections()
235 {
236 return (! getOperationTypesToRetryDueToInvalidConnections().isEmpty());
237 }
238
239
240
241 /**
242 * Retrieves the set of operation types for which operations should be
243 * retried if the initial attempt fails in a manner that indicates that the
244 * connection used to process the request may no longer be valid.
245 *
246 * @return The set of operation types for which operations should be
247 * retried if the initial attempt fails in a manner that indicates
248 * that the connection used to process the request may no longer be
249 * valid, or an empty set if retries should not be performed for any
250 * type of operation.
251 */
252 public abstract Set<OperationType>
253 getOperationTypesToRetryDueToInvalidConnections();
254
255
256
257 /**
258 * Specifies whether attempts to process operations should be retried on a
259 * newly-created connection if the initial attempt fails in a manner that
260 * indicates that the connection used to process that request may no longer
261 * be valid. Only a single retry will be attempted for any operation.
262 * <BR><BR>
263 * Note that this only applies to methods used to process operations in the
264 * context pool (e.g., using methods that are part of {@link LDAPInterface}),
265 * and will not automatically be used for operations processed on connections
266 * checked out of the pool.
267 * <BR><BR>
268 * This method is provided for the purpose of backward compatibility, but new
269 * functionality has been added to control retry on a per-operation-type
270 * basis via the {@link #setRetryFailedOperationsDueToInvalidConnections(Set)}
271 * method. If this is called with a value of {@code true}, then retry will be
272 * enabled for all types of operations. If it is called with a value of
273 * {@code false}, then retry will be disabled for all types of operations.
274 *
275 * @param retryFailedOperationsDueToInvalidConnections
276 * Indicates whether attempts to process operations should be
277 * retried on a newly-created connection if they fail in a way
278 * that indicates the associated connection may no longer be
279 * usable.
280 */
281 public final void setRetryFailedOperationsDueToInvalidConnections(
282 final boolean retryFailedOperationsDueToInvalidConnections)
283 {
284 if (retryFailedOperationsDueToInvalidConnections)
285 {
286 setRetryFailedOperationsDueToInvalidConnections(
287 EnumSet.allOf(OperationType.class));
288 }
289 else
290 {
291 setRetryFailedOperationsDueToInvalidConnections(
292 EnumSet.noneOf(OperationType.class));
293 }
294 }
295
296
297
298 /**
299 * Specifies the types of operations that should be retried on a newly-created
300 * connection if the initial attempt fails in a manner that indicates that
301 * the connection used to process the request may no longer be valid. Only a
302 * single retry will be attempted for any operation.
303 * <BR><BR>
304 * Note that this only applies to methods used to process operations in the
305 * context pool (e.g., using methods that are part of {@link LDAPInterface}),
306 * and will not automatically be used for operations processed on connections
307 * checked out of the pool.
308 *
309 * @param operationTypes The types of operations for which to retry failed
310 * operations if they fail in a way that indicates the
311 * associated connection may no longer be usable. It
312 * may be {@code null} or empty to indicate that no
313 * types of operations should be retried.
314 */
315 public abstract void setRetryFailedOperationsDueToInvalidConnections(
316 final Set<OperationType> operationTypes);
317
318
319
320 /**
321 * Retrieves the number of connections that are currently available for use in
322 * this connection pool, if applicable.
323 *
324 * @return The number of connections that are currently available for use in
325 * this connection pool, or -1 if that is not applicable for this
326 * type of connection pool.
327 */
328 public abstract int getCurrentAvailableConnections();
329
330
331
332 /**
333 * Retrieves the maximum number of connections to be maintained in this
334 * connection pool, which is the maximum number of available connections that
335 * should be available at any time, if applicable.
336 *
337 * @return The number of connections to be maintained in this connection
338 * pool, or -1 if that is not applicable for this type of connection
339 * pool.
340 */
341 public abstract int getMaximumAvailableConnections();
342
343
344
345 /**
346 * Retrieves the set of statistics maintained for this LDAP connection pool.
347 *
348 * @return The set of statistics maintained for this LDAP connection pool.
349 */
350 public abstract LDAPConnectionPoolStatistics getConnectionPoolStatistics();
351
352
353
354 /**
355 * Retrieves the user-friendly name that has been assigned to this connection
356 * pool.
357 *
358 * @return The user-friendly name that has been assigned to this connection
359 * pool, or {@code null} if none has been assigned.
360 */
361 public abstract String getConnectionPoolName();
362
363
364
365 /**
366 * Specifies the user-friendly name that should be used for this connection
367 * pool. This name may be used in debugging to help identify the purpose of
368 * this connection pool. It will also be assigned to all connections
369 * associated with this connection pool.
370 *
371 * @param connectionPoolName The user-friendly name that should be used for
372 * this connection pool.
373 */
374 public abstract void setConnectionPoolName(final String connectionPoolName);
375
376
377
378 /**
379 * Retrieves the health check implementation for this connection pool.
380 *
381 * @return The health check implementation for this connection pool.
382 */
383 public abstract LDAPConnectionPoolHealthCheck getHealthCheck();
384
385
386
387 /**
388 * Retrieves the length of time in milliseconds between periodic background
389 * health checks against the available connections in this pool.
390 *
391 * @return The length of time in milliseconds between the periodic background
392 * health checks against the available connections in this pool.
393 */
394 public abstract long getHealthCheckIntervalMillis();
395
396
397
398 /**
399 * Specifies the length of time in milliseconds between periodic background
400 * health checks against the available connections in this pool.
401 *
402 * @param healthCheckInterval The length of time in milliseconds between
403 * periodic background health checks against the
404 * available connections in this pool. The
405 * provided value must be greater than zero.
406 */
407 public abstract void setHealthCheckIntervalMillis(
408 final long healthCheckInterval);
409
410
411
412 /**
413 * Performs a health check against all connections currently available in this
414 * connection pool. This should only be invoked by the connection pool health
415 * check thread.
416 */
417 protected abstract void doHealthCheck();
418
419
420
421 /**
422 * Retrieves the directory server root DSE using a connection from this
423 * connection pool.
424 *
425 * @return The directory server root DSE, or {@code null} if it is not
426 * available.
427 *
428 * @throws LDAPException If a problem occurs while attempting to retrieve
429 * the server root DSE.
430 */
431 public final RootDSE getRootDSE()
432 throws LDAPException
433 {
434 final LDAPConnection conn = getConnection();
435
436 try
437 {
438 final RootDSE rootDSE = conn.getRootDSE();
439 releaseConnection(conn);
440 return rootDSE;
441 }
442 catch (final Throwable t)
443 {
444 throwLDAPExceptionIfShouldNotRetry(t, OperationType.SEARCH, conn);
445
446 // If we have gotten here, then we should retry the operation with a
447 // newly-created connection.
448 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
449
450 try
451 {
452 final RootDSE rootDSE = newConn.getRootDSE();
453 releaseConnection(newConn);
454 return rootDSE;
455 }
456 catch (final Throwable t2)
457 {
458 throwLDAPException(t2, newConn);
459 }
460
461 // This return statement should never be reached.
462 return null;
463 }
464 }
465
466
467
468 /**
469 * Retrieves the directory server schema definitions using a connection from
470 * this connection pool, using the subschema subentry DN contained in the
471 * server's root DSE. For directory servers containing a single schema, this
472 * should be sufficient for all purposes. For servers with multiple schemas,
473 * it may be necessary to specify the DN of the target entry for which to
474 * obtain the associated schema.
475 *
476 * @return The directory server schema definitions, or {@code null} if the
477 * schema information could not be retrieved (e.g, the client does
478 * not have permission to read the server schema).
479 *
480 * @throws LDAPException If a problem occurs while attempting to retrieve
481 * the server schema.
482 */
483 public final Schema getSchema()
484 throws LDAPException
485 {
486 return getSchema("");
487 }
488
489
490
491 /**
492 * Retrieves the directory server schema definitions that govern the specified
493 * entry using a connection from this connection pool. The subschemaSubentry
494 * attribute will be retrieved from the target entry, and then the appropriate
495 * schema definitions will be loaded from the entry referenced by that
496 * attribute. This may be necessary to ensure correct behavior in servers
497 * that support multiple schemas.
498 *
499 * @param entryDN The DN of the entry for which to retrieve the associated
500 * schema definitions. It may be {@code null} or an empty
501 * string if the subschemaSubentry attribute should be
502 * retrieved from the server's root DSE.
503 *
504 * @return The directory server schema definitions, or {@code null} if the
505 * schema information could not be retrieved (e.g, the client does
506 * not have permission to read the server schema).
507 *
508 * @throws LDAPException If a problem occurs while attempting to retrieve
509 * the server schema.
510 */
511 public final Schema getSchema(final String entryDN)
512 throws LDAPException
513 {
514 final LDAPConnection conn = getConnection();
515
516 try
517 {
518 final Schema schema = conn.getSchema(entryDN);
519 releaseConnection(conn);
520 return schema;
521 }
522 catch (Throwable t)
523 {
524 throwLDAPExceptionIfShouldNotRetry(t, OperationType.SEARCH, conn);
525
526 // If we have gotten here, then we should retry the operation with a
527 // newly-created connection.
528 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
529
530 try
531 {
532 final Schema schema = newConn.getSchema(entryDN);
533 releaseConnection(newConn);
534 return schema;
535 }
536 catch (final Throwable t2)
537 {
538 throwLDAPException(t2, newConn);
539 }
540
541 // This return statement should never be reached.
542 return null;
543 }
544 }
545
546
547
548 /**
549 * Retrieves the entry with the specified DN using a connection from this
550 * connection pool. All user attributes will be requested in the entry to
551 * return.
552 *
553 * @param dn The DN of the entry to retrieve. It must not be {@code null}.
554 *
555 * @return The requested entry, or {@code null} if the target entry does not
556 * exist or no entry was returned (e.g., if the authenticated user
557 * does not have permission to read the target entry).
558 *
559 * @throws LDAPException If a problem occurs while sending the request or
560 * reading the response.
561 */
562 public final SearchResultEntry getEntry(final String dn)
563 throws LDAPException
564 {
565 return getEntry(dn, NO_STRINGS);
566 }
567
568
569
570 /**
571 * Retrieves the entry with the specified DN using a connection from this
572 * connection pool.
573 *
574 * @param dn The DN of the entry to retrieve. It must not be
575 * {@code null}.
576 * @param attributes The set of attributes to request for the target entry.
577 * If it is {@code null}, then all user attributes will be
578 * requested.
579 *
580 * @return The requested entry, or {@code null} if the target entry does not
581 * exist or no entry was returned (e.g., if the authenticated user
582 * does not have permission to read the target entry).
583 *
584 * @throws LDAPException If a problem occurs while sending the request or
585 * reading the response.
586 */
587 public final SearchResultEntry getEntry(final String dn,
588 final String... attributes)
589 throws LDAPException
590 {
591 final LDAPConnection conn = getConnection();
592
593 try
594 {
595 final SearchResultEntry entry = conn.getEntry(dn, attributes);
596 releaseConnection(conn);
597 return entry;
598 }
599 catch (Throwable t)
600 {
601 throwLDAPExceptionIfShouldNotRetry(t, OperationType.SEARCH, conn);
602
603 // If we have gotten here, then we should retry the operation with a
604 // newly-created connection.
605 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
606
607 try
608 {
609 final SearchResultEntry entry = newConn.getEntry(dn, attributes);
610 releaseConnection(newConn);
611 return entry;
612 }
613 catch (final Throwable t2)
614 {
615 throwLDAPException(t2, newConn);
616 }
617
618 // This return statement should never be reached.
619 return null;
620 }
621 }
622
623
624
625 /**
626 * Processes an add operation with the provided information using a connection
627 * from this connection pool.
628 *
629 * @param dn The DN of the entry to add. It must not be
630 * {@code null}.
631 * @param attributes The set of attributes to include in the entry to add.
632 * It must not be {@code null}.
633 *
634 * @return The result of processing the add operation.
635 *
636 * @throws LDAPException If the server rejects the add request, or if a
637 * problem is encountered while sending the request or
638 * reading the response.
639 */
640 public final LDAPResult add(final String dn, final Attribute... attributes)
641 throws LDAPException
642 {
643 return add(new AddRequest(dn, attributes));
644 }
645
646
647
648 /**
649 * Processes an add operation with the provided information using a connection
650 * from this connection pool.
651 *
652 * @param dn The DN of the entry to add. It must not be
653 * {@code null}.
654 * @param attributes The set of attributes to include in the entry to add.
655 * It must not be {@code null}.
656 *
657 * @return The result of processing the add operation.
658 *
659 * @throws LDAPException If the server rejects the add request, or if a
660 * problem is encountered while sending the request or
661 * reading the response.
662 */
663 public final LDAPResult add(final String dn,
664 final Collection<Attribute> attributes)
665 throws LDAPException
666 {
667 return add(new AddRequest(dn, attributes));
668 }
669
670
671
672 /**
673 * Processes an add operation with the provided information using a connection
674 * from this connection pool.
675 *
676 * @param entry The entry to add. It must not be {@code null}.
677 *
678 * @return The result of processing the add operation.
679 *
680 * @throws LDAPException If the server rejects the add request, or if a
681 * problem is encountered while sending the request or
682 * reading the response.
683 */
684 public final LDAPResult add(final Entry entry)
685 throws LDAPException
686 {
687 return add(new AddRequest(entry));
688 }
689
690
691
692 /**
693 * Processes an add operation with the provided information using a connection
694 * from this connection pool.
695 *
696 * @param ldifLines The lines that comprise an LDIF representation of the
697 * entry to add. It must not be empty or {@code null}.
698 *
699 * @return The result of processing the add operation.
700 *
701 * @throws LDIFException If the provided entry lines cannot be decoded as an
702 * entry in LDIF form.
703 *
704 * @throws LDAPException If the server rejects the add request, or if a
705 * problem is encountered while sending the request or
706 * reading the response.
707 */
708 public final LDAPResult add(final String... ldifLines)
709 throws LDIFException, LDAPException
710 {
711 return add(new AddRequest(ldifLines));
712 }
713
714
715
716 /**
717 * Processes the provided add request using a connection from this connection
718 * pool.
719 *
720 * @param addRequest The add request to be processed. It must not be
721 * {@code null}.
722 *
723 * @return The result of processing the add operation.
724 *
725 * @throws LDAPException If the server rejects the add request, or if a
726 * problem is encountered while sending the request or
727 * reading the response.
728 */
729 public final LDAPResult add(final AddRequest addRequest)
730 throws LDAPException
731 {
732 final LDAPConnection conn = getConnection();
733
734 try
735 {
736 final LDAPResult result = conn.add(addRequest);
737 releaseConnection(conn);
738 return result;
739 }
740 catch (Throwable t)
741 {
742 throwLDAPExceptionIfShouldNotRetry(t, OperationType.ADD, conn);
743
744 // If we have gotten here, then we should retry the operation with a
745 // newly-created connection.
746 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
747
748 try
749 {
750 final LDAPResult result = newConn.add(addRequest);
751 releaseConnection(newConn);
752 return result;
753 }
754 catch (final Throwable t2)
755 {
756 throwLDAPException(t2, newConn);
757 }
758
759 // This return statement should never be reached.
760 return null;
761 }
762 }
763
764
765
766 /**
767 * Processes the provided add request using a connection from this connection
768 * pool.
769 *
770 * @param addRequest The add request to be processed. It must not be
771 * {@code null}.
772 *
773 * @return The result of processing the add operation.
774 *
775 * @throws LDAPException If the server rejects the add request, or if a
776 * problem is encountered while sending the request or
777 * reading the response.
778 */
779 public final LDAPResult add(final ReadOnlyAddRequest addRequest)
780 throws LDAPException
781 {
782 return add((AddRequest) addRequest);
783 }
784
785
786
787 /**
788 * Processes a simple bind request with the provided DN and password using a
789 * connection from this connection pool. Note that this will impact the state
790 * of the connection in the pool, and therefore this method should only be
791 * used if this connection pool is used exclusively for processing bind
792 * operations, or if the retain identity request control (only available in
793 * the Commercial Edition of the LDAP SDK for use with the UnboundID Directory
794 * Server) is included in the bind request to ensure that the authentication
795 * state is not impacted.
796 *
797 * @param bindDN The bind DN for the bind operation.
798 * @param password The password for the simple bind operation.
799 *
800 * @return The result of processing the bind operation.
801 *
802 * @throws LDAPException If the server rejects the bind request, or if a
803 * problem occurs while sending the request or reading
804 * the response.
805 */
806 public final BindResult bind(final String bindDN, final String password)
807 throws LDAPException
808 {
809 return bind(new SimpleBindRequest(bindDN, password));
810 }
811
812
813
814 /**
815 * Processes the provided bind request using a connection from this connection
816 * pool. Note that this will impact the state of the connection in the pool,
817 * and therefore this method should only be used if this connection pool is
818 * used exclusively for processing bind operations, or if the retain identity
819 * request control (only available in the Commercial Edition of the LDAP SDK
820 * for use with the UnboundID Directory Server) is included in the bind
821 * request to ensure that the authentication state is not impacted.
822 *
823 * @param bindRequest The bind request to be processed. It must not be
824 * {@code null}.
825 *
826 * @return The result of processing the bind operation.
827 *
828 * @throws LDAPException If the server rejects the bind request, or if a
829 * problem occurs while sending the request or reading
830 * the response.
831 */
832 public final BindResult bind(final BindRequest bindRequest)
833 throws LDAPException
834 {
835 final LDAPConnection conn = getConnection();
836
837 try
838 {
839 final BindResult result = conn.bind(bindRequest);
840 releaseConnection(conn);
841 return result;
842 }
843 catch (Throwable t)
844 {
845 throwLDAPExceptionIfShouldNotRetry(t, OperationType.BIND, conn);
846
847 // If we have gotten here, then we should retry the operation with a
848 // newly-created connection.
849 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
850
851 try
852 {
853 final BindResult result = newConn.bind(bindRequest);
854 releaseConnection(newConn);
855 return result;
856 }
857 catch (final Throwable t2)
858 {
859 throwLDAPException(t2, newConn);
860 }
861
862 // This return statement should never be reached.
863 return null;
864 }
865 }
866
867
868
869 /**
870 * Processes a compare operation with the provided information using a
871 * connection from this connection pool.
872 *
873 * @param dn The DN of the entry in which to make the
874 * comparison. It must not be {@code null}.
875 * @param attributeName The attribute name for which to make the
876 * comparison. It must not be {@code null}.
877 * @param assertionValue The assertion value to verify in the target entry.
878 * It must not be {@code null}.
879 *
880 * @return The result of processing the compare operation.
881 *
882 * @throws LDAPException If the server rejects the compare request, or if a
883 * problem is encountered while sending the request or
884 * reading the response.
885 */
886 public final CompareResult compare(final String dn,
887 final String attributeName,
888 final String assertionValue)
889 throws LDAPException
890 {
891 return compare(new CompareRequest(dn, attributeName, assertionValue));
892 }
893
894
895
896 /**
897 * Processes the provided compare request using a connection from this
898 * connection pool.
899 *
900 * @param compareRequest The compare request to be processed. It must not
901 * be {@code null}.
902 *
903 * @return The result of processing the compare operation.
904 *
905 * @throws LDAPException If the server rejects the compare request, or if a
906 * problem is encountered while sending the request or
907 * reading the response.
908 */
909 public final CompareResult compare(final CompareRequest compareRequest)
910 throws LDAPException
911 {
912 final LDAPConnection conn = getConnection();
913
914 try
915 {
916 final CompareResult result = conn.compare(compareRequest);
917 releaseConnection(conn);
918 return result;
919 }
920 catch (Throwable t)
921 {
922 throwLDAPExceptionIfShouldNotRetry(t, OperationType.COMPARE, conn);
923
924 // If we have gotten here, then we should retry the operation with a
925 // newly-created connection.
926 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
927
928 try
929 {
930 final CompareResult result = newConn.compare(compareRequest);
931 releaseConnection(newConn);
932 return result;
933 }
934 catch (final Throwable t2)
935 {
936 throwLDAPException(t2, newConn);
937 }
938
939 // This return statement should never be reached.
940 return null;
941 }
942 }
943
944
945
946 /**
947 * Processes the provided compare request using a connection from this
948 * connection pool.
949 *
950 * @param compareRequest The compare request to be processed. It must not
951 * be {@code null}.
952 *
953 * @return The result of processing the compare operation.
954 *
955 * @throws LDAPException If the server rejects the compare request, or if a
956 * problem is encountered while sending the request or
957 * reading the response.
958 */
959 public final CompareResult compare(
960 final ReadOnlyCompareRequest compareRequest)
961 throws LDAPException
962 {
963 return compare((CompareRequest) compareRequest);
964 }
965
966
967
968 /**
969 * Deletes the entry with the specified DN using a connection from this
970 * connection pool.
971 *
972 * @param dn The DN of the entry to delete. It must not be {@code null}.
973 *
974 * @return The result of processing the delete operation.
975 *
976 * @throws LDAPException If the server rejects the delete request, or if a
977 * problem is encountered while sending the request or
978 * reading the response.
979 */
980 public final LDAPResult delete(final String dn)
981 throws LDAPException
982 {
983 return delete(new DeleteRequest(dn));
984 }
985
986
987
988 /**
989 * Processes the provided delete request using a connection from this
990 * connection pool.
991 *
992 * @param deleteRequest The delete request to be processed. It must not be
993 * {@code null}.
994 *
995 * @return The result of processing the delete operation.
996 *
997 * @throws LDAPException If the server rejects the delete request, or if a
998 * problem is encountered while sending the request or
999 * reading the response.
1000 */
1001 public final LDAPResult delete(final DeleteRequest deleteRequest)
1002 throws LDAPException
1003 {
1004 final LDAPConnection conn = getConnection();
1005
1006 try
1007 {
1008 final LDAPResult result = conn.delete(deleteRequest);
1009 releaseConnection(conn);
1010 return result;
1011 }
1012 catch (Throwable t)
1013 {
1014 throwLDAPExceptionIfShouldNotRetry(t, OperationType.DELETE, conn);
1015
1016 // If we have gotten here, then we should retry the operation with a
1017 // newly-created connection.
1018 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
1019
1020 try
1021 {
1022 final LDAPResult result = newConn.delete(deleteRequest);
1023 releaseConnection(newConn);
1024 return result;
1025 }
1026 catch (final Throwable t2)
1027 {
1028 throwLDAPException(t2, newConn);
1029 }
1030
1031 // This return statement should never be reached.
1032 return null;
1033 }
1034 }
1035
1036
1037
1038 /**
1039 * Processes the provided delete request using a connection from this
1040 * connection pool.
1041 *
1042 * @param deleteRequest The delete request to be processed. It must not be
1043 * {@code null}.
1044 *
1045 * @return The result of processing the delete operation.
1046 *
1047 * @throws LDAPException If the server rejects the delete request, or if a
1048 * problem is encountered while sending the request or
1049 * reading the response.
1050 */
1051 public final LDAPResult delete(final ReadOnlyDeleteRequest deleteRequest)
1052 throws LDAPException
1053 {
1054 return delete((DeleteRequest) deleteRequest);
1055 }
1056
1057
1058
1059 /**
1060 * Processes an extended operation with the provided request OID using a
1061 * connection from this connection pool. Note that this method should not be
1062 * used to perform any operation that will alter the state of the connection
1063 * in the pool (e.g., a StartTLS operation) or that involves multiple
1064 * distinct operations on the same connection (e.g., LDAP transactions).
1065 *
1066 * @param requestOID The OID for the extended request to process. It must
1067 * not be {@code null}.
1068 *
1069 * @return The extended result object that provides information about the
1070 * result of the request processing.
1071 *
1072 * @throws LDAPException If a problem occurs while sending the request or
1073 * reading the response.
1074 */
1075 public final ExtendedResult processExtendedOperation(final String requestOID)
1076 throws LDAPException
1077 {
1078 return processExtendedOperation(new ExtendedRequest(requestOID));
1079 }
1080
1081
1082
1083 /**
1084 * Processes an extended operation with the provided request OID and value
1085 * using a connection from this connection pool. Note that this method should
1086 * not be used to perform any operation that will alter the state of the
1087 * connection in the pool (e.g., a StartTLS operation) or that involves
1088 * multiple distinct operations on the same connection (e.g., LDAP
1089 * transactions).
1090 *
1091 * @param requestOID The OID for the extended request to process. It must
1092 * not be {@code null}.
1093 * @param requestValue The encoded value for the extended request to
1094 * process. It may be {@code null} if there does not
1095 * need to be a value for the requested operation.
1096 *
1097 * @return The extended result object that provides information about the
1098 * result of the request processing.
1099 *
1100 * @throws LDAPException If a problem occurs while sending the request or
1101 * reading the response.
1102 */
1103 public final ExtendedResult processExtendedOperation(final String requestOID,
1104 final ASN1OctetString requestValue)
1105 throws LDAPException
1106 {
1107 return processExtendedOperation(new ExtendedRequest(requestOID,
1108 requestValue));
1109 }
1110
1111
1112
1113 /**
1114 * Processes the provided extended request using a connection from this
1115 * connection pool. Note that this method should not be used to perform any
1116 * operation that will alter the state of the connection in the pool (e.g., a
1117 * StartTLS operation) or that involves multiple distinct operations on the
1118 * same connection (e.g., LDAP transactions).
1119 *
1120 * @param extendedRequest The extended request to be processed. It must not
1121 * be {@code null}.
1122 *
1123 * @return The extended result object that provides information about the
1124 * result of the request processing.
1125 *
1126 * @throws LDAPException If a problem occurs while sending the request or
1127 * reading the response.
1128 */
1129 public final ExtendedResult processExtendedOperation(
1130 final ExtendedRequest extendedRequest)
1131 throws LDAPException
1132 {
1133 if (extendedRequest.getOID().equals(
1134 StartTLSExtendedRequest.STARTTLS_REQUEST_OID))
1135 {
1136 throw new LDAPException(ResultCode.NOT_SUPPORTED,
1137 ERR_POOL_STARTTLS_NOT_ALLOWED.get());
1138 }
1139
1140 final LDAPConnection conn = getConnection();
1141
1142 try
1143 {
1144 final ExtendedResult result =
1145 conn.processExtendedOperation(extendedRequest);
1146 releaseConnection(conn);
1147 return result;
1148 }
1149 catch (Throwable t)
1150 {
1151 throwLDAPExceptionIfShouldNotRetry(t, OperationType.EXTENDED, conn);
1152
1153 // If we have gotten here, then we should retry the operation with a
1154 // newly-created connection.
1155 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
1156
1157 try
1158 {
1159 final ExtendedResult result =
1160 newConn.processExtendedOperation(extendedRequest);
1161 releaseConnection(newConn);
1162 return result;
1163 }
1164 catch (final Throwable t2)
1165 {
1166 throwLDAPException(t2, newConn);
1167 }
1168
1169 // This return statement should never be reached.
1170 return null;
1171 }
1172 }
1173
1174
1175
1176 /**
1177 * Applies the provided modification to the specified entry using a connection
1178 * from this connection pool.
1179 *
1180 * @param dn The DN of the entry to modify. It must not be {@code null}.
1181 * @param mod The modification to apply to the target entry. It must not
1182 * be {@code null}.
1183 *
1184 * @return The result of processing the modify operation.
1185 *
1186 * @throws LDAPException If the server rejects the modify request, or if a
1187 * problem is encountered while sending the request or
1188 * reading the response.
1189 */
1190 public final LDAPResult modify(final String dn, final Modification mod)
1191 throws LDAPException
1192 {
1193 return modify(new ModifyRequest(dn, mod));
1194 }
1195
1196
1197
1198 /**
1199 * Applies the provided set of modifications to the specified entry using a
1200 * connection from this connection pool.
1201 *
1202 * @param dn The DN of the entry to modify. It must not be {@code null}.
1203 * @param mods The set of modifications to apply to the target entry. It
1204 * must not be {@code null} or empty. *
1205 * @return The result of processing the modify operation.
1206 *
1207 * @throws LDAPException If the server rejects the modify request, or if a
1208 * problem is encountered while sending the request or
1209 * reading the response.
1210 */
1211 public final LDAPResult modify(final String dn, final Modification... mods)
1212 throws LDAPException
1213 {
1214 return modify(new ModifyRequest(dn, mods));
1215 }
1216
1217
1218
1219 /**
1220 * Applies the provided set of modifications to the specified entry using a
1221 * connection from this connection pool.
1222 *
1223 * @param dn The DN of the entry to modify. It must not be {@code null}.
1224 * @param mods The set of modifications to apply to the target entry. It
1225 * must not be {@code null} or empty.
1226 *
1227 * @return The result of processing the modify operation.
1228 *
1229 * @throws LDAPException If the server rejects the modify request, or if a
1230 * problem is encountered while sending the request or
1231 * reading the response.
1232 */
1233 public final LDAPResult modify(final String dn, final List<Modification> mods)
1234 throws LDAPException
1235 {
1236 return modify(new ModifyRequest(dn, mods));
1237 }
1238
1239
1240
1241 /**
1242 * Processes a modify request from the provided LDIF representation of the
1243 * changes using a connection from this connection pool.
1244 *
1245 * @param ldifModificationLines The lines that comprise an LDIF
1246 * representation of a modify change record.
1247 * It must not be {@code null} or empty.
1248 *
1249 * @return The result of processing the modify operation.
1250 *
1251 * @throws LDIFException If the provided set of lines cannot be parsed as an
1252 * LDIF modify change record.
1253 *
1254 * @throws LDAPException If the server rejects the modify request, or if a
1255 * problem is encountered while sending the request or
1256 * reading the response.
1257 *
1258 */
1259 public final LDAPResult modify(final String... ldifModificationLines)
1260 throws LDIFException, LDAPException
1261 {
1262 return modify(new ModifyRequest(ldifModificationLines));
1263 }
1264
1265
1266
1267 /**
1268 * Processes the provided modify request using a connection from this
1269 * connection pool.
1270 *
1271 * @param modifyRequest The modify request to be processed. It must not be
1272 * {@code null}.
1273 *
1274 * @return The result of processing the modify operation.
1275 *
1276 * @throws LDAPException If the server rejects the modify request, or if a
1277 * problem is encountered while sending the request or
1278 * reading the response.
1279 */
1280 public final LDAPResult modify(final ModifyRequest modifyRequest)
1281 throws LDAPException
1282 {
1283 final LDAPConnection conn = getConnection();
1284
1285 try
1286 {
1287 final LDAPResult result = conn.modify(modifyRequest);
1288 releaseConnection(conn);
1289 return result;
1290 }
1291 catch (Throwable t)
1292 {
1293 throwLDAPExceptionIfShouldNotRetry(t, OperationType.MODIFY, conn);
1294
1295 // If we have gotten here, then we should retry the operation with a
1296 // newly-created connection.
1297 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
1298
1299 try
1300 {
1301 final LDAPResult result = newConn.modify(modifyRequest);
1302 releaseConnection(newConn);
1303 return result;
1304 }
1305 catch (final Throwable t2)
1306 {
1307 throwLDAPException(t2, newConn);
1308 }
1309
1310 // This return statement should never be reached.
1311 return null;
1312 }
1313 }
1314
1315
1316
1317 /**
1318 * Processes the provided modify request using a connection from this
1319 * connection pool.
1320 *
1321 * @param modifyRequest The modify request to be processed. It must not be
1322 * {@code null}.
1323 *
1324 * @return The result of processing the modify operation.
1325 *
1326 * @throws LDAPException If the server rejects the modify request, or if a
1327 * problem is encountered while sending the request or
1328 * reading the response.
1329 */
1330 public final LDAPResult modify(final ReadOnlyModifyRequest modifyRequest)
1331 throws LDAPException
1332 {
1333 return modify((ModifyRequest) modifyRequest);
1334 }
1335
1336
1337
1338 /**
1339 * Performs a modify DN operation with the provided information using a
1340 * connection from this connection pool.
1341 *
1342 * @param dn The current DN for the entry to rename. It must not
1343 * be {@code null}.
1344 * @param newRDN The new RDN to use for the entry. It must not be
1345 * {@code null}.
1346 * @param deleteOldRDN Indicates whether to delete the current RDN value
1347 * from the entry.
1348 *
1349 * @return The result of processing the modify DN operation.
1350 *
1351 * @throws LDAPException If the server rejects the modify DN request, or if
1352 * a problem is encountered while sending the request
1353 * or reading the response.
1354 */
1355 public final LDAPResult modifyDN(final String dn, final String newRDN,
1356 final boolean deleteOldRDN)
1357 throws LDAPException
1358 {
1359 return modifyDN(new ModifyDNRequest(dn, newRDN, deleteOldRDN));
1360 }
1361
1362
1363
1364 /**
1365 * Performs a modify DN operation with the provided information using a
1366 * connection from this connection pool.
1367 *
1368 * @param dn The current DN for the entry to rename. It must not
1369 * be {@code null}.
1370 * @param newRDN The new RDN to use for the entry. It must not be
1371 * {@code null}.
1372 * @param deleteOldRDN Indicates whether to delete the current RDN value
1373 * from the entry.
1374 * @param newSuperiorDN The new superior DN for the entry. It may be
1375 * {@code null} if the entry is not to be moved below a
1376 * new parent.
1377 *
1378 * @return The result of processing the modify DN operation.
1379 *
1380 * @throws LDAPException If the server rejects the modify DN request, or if
1381 * a problem is encountered while sending the request
1382 * or reading the response.
1383 */
1384 public final LDAPResult modifyDN(final String dn, final String newRDN,
1385 final boolean deleteOldRDN,
1386 final String newSuperiorDN)
1387 throws LDAPException
1388 {
1389 return modifyDN(new ModifyDNRequest(dn, newRDN, deleteOldRDN,
1390 newSuperiorDN));
1391 }
1392
1393
1394
1395 /**
1396 * Processes the provided modify DN request using a connection from this
1397 * connection pool.
1398 *
1399 * @param modifyDNRequest The modify DN request to be processed. It must
1400 * not be {@code null}.
1401 *
1402 * @return The result of processing the modify DN operation.
1403 *
1404 * @throws LDAPException If the server rejects the modify DN request, or if
1405 * a problem is encountered while sending the request
1406 * or reading the response.
1407 */
1408 public final LDAPResult modifyDN(final ModifyDNRequest modifyDNRequest)
1409 throws LDAPException
1410 {
1411 final LDAPConnection conn = getConnection();
1412
1413 try
1414 {
1415 final LDAPResult result = conn.modifyDN(modifyDNRequest);
1416 releaseConnection(conn);
1417 return result;
1418 }
1419 catch (Throwable t)
1420 {
1421 throwLDAPExceptionIfShouldNotRetry(t, OperationType.MODIFY_DN, conn);
1422
1423 // If we have gotten here, then we should retry the operation with a
1424 // newly-created connection.
1425 final LDAPConnection newConn = replaceDefunctConnection(t, conn);
1426
1427 try
1428 {
1429 final LDAPResult result = newConn.modifyDN(modifyDNRequest);
1430 releaseConnection(newConn);
1431 return result;
1432 }
1433 catch (final Throwable t2)
1434 {
1435 throwLDAPException(t2, newConn);
1436 }
1437
1438 // This return statement should never be reached.
1439 return null;
1440 }
1441 }
1442
1443
1444
1445 /**
1446 * Processes the provided modify DN request using a connection from this
1447 * connection pool.
1448 *
1449 * @param modifyDNRequest The modify DN request to be processed. It must
1450 * not be {@code null}.
1451 *
1452 * @return The result of processing the modify DN operation.
1453 *
1454 * @throws LDAPException If the server rejects the modify DN request, or if
1455 * a problem is encountered while sending the request
1456 * or reading the response.
1457 */
1458 public final LDAPResult modifyDN(
1459 final ReadOnlyModifyDNRequest modifyDNRequest)
1460 throws LDAPException
1461 {
1462 return modifyDN((ModifyDNRequest) modifyDNRequest);
1463 }
1464
1465
1466
1467 /**
1468 * Processes a search operation with the provided information using a
1469 * connection from this connection pool. The search result entries and
1470 * references will be collected internally and included in the
1471 * {@code SearchResult} object that is returned.
1472 *
1473 * @param baseDN The base DN for the search request. It must not be
1474 * {@code null}.
1475 * @param scope The scope that specifies the range of entries that
1476 * should be examined for the search.
1477 * @param filter The string representation of the filter to use to
1478 * identify matching entries. It must not be
1479 * {@code null}.
1480 * @param attributes The set of attributes that should be returned in
1481 * matching entries. It may be {@code null} or empty if
1482 * the default attribute set (all user attributes) is to
1483 * be requested.
1484 *
1485 * @return A search result object that provides information about the
1486 * processing of the search, including the set of matching entries
1487 * and search references returned by the server.
1488 *
1489 * @throws LDAPSearchException If the search does not complete successfully,
1490 * or if a problem is encountered while parsing
1491 * the provided filter string, sending the
1492 * request, or reading the response.
1493 */
1494 public final SearchResult search(final String baseDN, final SearchScope scope,
1495 final String filter,
1496 final String... attributes)
1497 throws LDAPSearchException
1498 {
1499 return search(new SearchRequest(baseDN, scope, parseFilter(filter),
1500 attributes));
1501 }
1502
1503
1504
1505 /**
1506 * Processes a search operation with the provided information using a
1507 * connection from this connection pool. The search result entries and
1508 * references will be collected internally and included in the
1509 * {@code SearchResult} object that is returned.
1510 *
1511 * @param baseDN The base DN for the search request. It must not be
1512 * {@code null}.
1513 * @param scope The scope that specifies the range of entries that
1514 * should be examined for the search.
1515 * @param filter The filter to use to identify matching entries. It
1516 * must not be {@code null}.
1517 * @param attributes The set of attributes that should be returned in
1518 * matching entries. It may be {@code null} or empty if
1519 * the default attribute set (all user attributes) is to
1520 * be requested.
1521 *
1522 * @return A search result object that provides information about the
1523 * processing of the search, including the set of matching entries
1524 * and search references returned by the server.
1525 *
1526 * @throws LDAPSearchException If the search does not complete successfully,
1527 * or if a problem is encountered while sending
1528 * the request or reading the response.
1529 */
1530 public final SearchResult search(final String baseDN, final SearchScope scope,
1531 final Filter filter,
1532 final String... attributes)
1533 throws LDAPSearchException
1534 {
1535 return search(new SearchRequest(baseDN, scope, filter, attributes));
1536 }
1537
1538
1539
1540 /**
1541 * Processes a search operation with the provided information using a
1542 * connection from this connection pool.
1543 *
1544 * @param searchResultListener The search result listener that should be
1545 * used to return results to the client. It may
1546 * be {@code null} if the search results should
1547 * be collected internally and returned in the
1548 * {@code SearchResult} object.
1549 * @param baseDN The base DN for the search request. It must
1550 * not be {@code null}.
1551 * @param scope The scope that specifies the range of entries
1552 * that should be examined for the search.
1553 * @param filter The string representation of the filter to
1554 * use to identify matching entries. It must
1555 * not be {@code null}.
1556 * @param attributes The set of attributes that should be returned
1557 * in matching entries. It may be {@code null}
1558 * or empty if the default attribute set (all
1559 * user attributes) is to be requested.
1560 *
1561 * @return A search result object that provides information about the
1562 * processing of the search, potentially including the set of
1563 * matching entries and search references returned by the server.
1564 *
1565 * @throws LDAPSearchException If the search does not complete successfully,
1566 * or if a problem is encountered while parsing
1567 * the provided filter string, sending the
1568 * request, or reading the response.
1569 */
1570 public final SearchResult
1571 search(final SearchResultListener searchResultListener,
1572 final String baseDN, final SearchScope scope, final String filter,
1573 final String... attributes)
1574 throws LDAPSearchException
1575 {
1576 return search(new SearchRequest(searchResultListener, baseDN, scope,
1577 parseFilter(filter), attributes));
1578 }
1579
1580
1581
1582 /**
1583 * Processes a search operation with the provided information using a
1584 * connection from this connection pool.
1585 *
1586 * @param searchResultListener The search result listener that should be
1587 * used to return results to the client. It may
1588 * be {@code null} if the search results should
1589 * be collected internally and returned in the
1590 * {@code SearchResult} object.
1591 * @param baseDN The base DN for the search request. It must
1592 * not be {@code null}.
1593 * @param scope The scope that specifies the range of entries
1594 * that should be examined for the search.
1595 * @param filter The filter to use to identify matching
1596 * entries. It must not be {@code null}.
1597 * @param attributes The set of attributes that should be returned
1598 * in matching entries. It may be {@code null}
1599 * or empty if the default attribute set (all
1600 * user attributes) is to be requested.
1601 *
1602 * @return A search result object that provides information about the
1603 * processing of the search, potentially including the set of
1604 * matching entries and search references returned by the server.
1605 *
1606 * @throws LDAPSearchException If the search does not complete successfully,
1607 * or if a problem is encountered while sending
1608 * the request or reading the response.
1609 */
1610 public final SearchResult
1611 search(final SearchResultListener searchResultListener,
1612 final String baseDN, final SearchScope scope, final Filter filter,
1613 final String... attributes)
1614 throws LDAPSearchException
1615 {
1616 return search(new SearchRequest(searchResultListener, baseDN, scope,
1617 filter, attributes));
1618 }
1619
1620
1621
1622 /**
1623 * Processes a search operation with the provided information using a
1624 * connection from this connection pool. The search result entries and
1625 * references will be collected internally and included in the
1626 * {@code SearchResult} object that is returned.
1627 *
1628 * @param baseDN The base DN for the search request. It must not be
1629 * {@code null}.
1630 * @param scope The scope that specifies the range of entries that
1631 * should be examined for the search.
1632 * @param derefPolicy The dereference policy the server should use for any
1633 * aliases encountered while processing the search.
1634 * @param sizeLimit The maximum number of entries that the server should
1635 * return for the search. A value of zero indicates that
1636 * there should be no limit.
1637 * @param timeLimit The maximum length of time in seconds that the server
1638 * should spend processing this search request. A value
1639 * of zero indicates that there should be no limit.
1640 * @param typesOnly Indicates whether to return only attribute names in
1641 * matching entries, or both attribute names and values.
1642 * @param filter The string representation of the filter to use to
1643 * identify matching entries. It must not be
1644 * {@code null}.
1645 * @param attributes The set of attributes that should be returned in
1646 * matching entries. It may be {@code null} or empty if
1647 * the default attribute set (all user attributes) is to
1648 * be requested.
1649 *
1650 * @return A search result object that provides information about the
1651 * processing of the search, including the set of matching entries
1652 * and search references returned by the server.
1653 *
1654 * @throws LDAPSearchException If the search does not complete successfully,
1655 * or if a problem is encountered while parsing
1656 * the provided filter string, sending the
1657 * request, or reading the response.
1658 */
1659 public final SearchResult search(final String baseDN, final SearchScope scope,
1660 final DereferencePolicy derefPolicy,
1661 final int sizeLimit, final int timeLimit,
1662 final boolean typesOnly, final String filter,
1663 final String... attributes)
1664 throws LDAPSearchException
1665 {
1666 return search(new SearchRequest(baseDN, scope, derefPolicy, sizeLimit,
1667 timeLimit, typesOnly, parseFilter(filter), attributes));
1668 }
1669
1670
1671
1672 /**
1673 * Processes a search operation with the provided information using a
1674 * connection from this connection pool. The search result entries and
1675 * references will be collected internally and included in the
1676 * {@code SearchResult} object that is returned.
1677 *
1678 * @param baseDN The base DN for the search request. It must not be
1679 * {@code null}.
1680 * @param scope The scope that specifies the range of entries that
1681 * should be examined for the search.
1682 * @param derefPolicy The dereference policy the server should use for any
1683 * aliases encountered while processing the search.
1684 * @param sizeLimit The maximum number of entries that the server should
1685 * return for the search. A value of zero indicates that
1686 * there should be no limit.
1687 * @param timeLimit The maximum length of time in seconds that the server
1688 * should spend processing this search request. A value
1689 * of zero indicates that there should be no limit.
1690 * @param typesOnly Indicates whether to return only attribute names in
1691 * matching entries, or both attribute names and values.
1692 * @param filter The filter to use to identify matching entries. It
1693 * must not be {@code null}.
1694 * @param attributes The set of attributes that should be returned in
1695 * matching entries. It may be {@code null} or empty if
1696 * the default attribute set (all user attributes) is to
1697 * be requested.
1698 *
1699 * @return A search result object that provides information about the
1700 * processing of the search, including the set of matching entries
1701 * and search references returned by the server.
1702 *
1703 * @throws LDAPSearchException If the search does not complete successfully,
1704 * or if a problem is encountered while sending
1705 * the request or reading the response.
1706 */
1707 public final SearchResult search(final String baseDN, final SearchScope scope,
1708 final DereferencePolicy derefPolicy,
1709 final int sizeLimit, final int timeLimit,
1710 final boolean typesOnly, final Filter filter,
1711 final String... attributes)
1712 throws LDAPSearchException
1713 {
1714 return search(new SearchRequest(baseDN, scope, derefPolicy, sizeLimit,
1715 timeLimit, typesOnly, filter, attributes));
1716 }
1717
1718
1719
1720 /**
1721 * Processes a search operation with the provided information using a
1722 * connection from this connection pool.
1723 *
1724 * @param searchResultListener The search result listener that should be
1725 * used to return results to the client. It may
1726 * be {@code null} if the search results should
1727 * be collected internally and returned in the
1728 * {@code SearchResult} object.
1729 * @param baseDN The base DN for the search request. It must
1730 * not be {@code null}.
1731 * @param scope The scope that specifies the range of entries
1732 * that should be examined for the search.
1733 * @param derefPolicy The dereference policy the server should use
1734 * for any aliases encountered while processing
1735 * the search.
1736 * @param sizeLimit The maximum number of entries that the server
1737 * should return for the search. A value of
1738 * zero indicates that there should be no limit.
1739 * @param timeLimit The maximum length of time in seconds that
1740 * the server should spend processing this
1741 * search request. A value of zero indicates
1742 * that there should be no limit.
1743 * @param typesOnly Indicates whether to return only attribute
1744 * names in matching entries, or both attribute
1745 * names and values.
1746 * @param filter The string representation of the filter to
1747 * use to identify matching entries. It must
1748 * not be {@code null}.
1749 * @param attributes The set of attributes that should be returned
1750 * in matching entries. It may be {@code null}
1751 * or empty if the default attribute set (all
1752 * user attributes) is to be requested.
1753 *
1754 * @return A search result object that provides information about the
1755 * processing of the search, potentially including the set of
1756 * matching entries and search references returned by the server.
1757 *
1758 * @throws LDAPSearchException If the search does not complete successfully,
1759 * or if a problem is encountered while parsing
1760 * the provided filter string, sending the
1761 * request, or reading the response.
1762 */
1763 public final SearchResult
1764 search(final SearchResultListener searchResultListener,
1765 final String baseDN, final SearchScope scope,
1766 final DereferencePolicy derefPolicy, final int sizeLimit,
1767 final int timeLimit, final boolean typesOnly, final String filter,
1768 final String... attributes)
1769 throws LDAPSearchException
1770 {
1771 return search(new SearchRequest(searchResultListener, baseDN, scope,
1772 derefPolicy, sizeLimit, timeLimit, typesOnly, parseFilter(filter),
1773 attributes));
1774 }
1775
1776
1777
1778 /**
1779 * Processes a search operation with the provided information using a
1780 * connection from this connection pool.
1781 *
1782 *
1783 * @param searchResultListener The search result listener that should be
1784 * used to return results to the client. It may
1785 * be {@code null} if the search results should
1786 * be collected internally and returned in the
1787 * {@code SearchResult} object.
1788 * @param baseDN The base DN for the search request. It must
1789 * not be {@code null}.
1790 * @param scope The scope that specifies the range of entries
1791 * that should be examined for the search.
1792 * @param derefPolicy The dereference policy the server should use
1793 * for any aliases encountered while processing
1794 * the search.
1795 * @param sizeLimit The maximum number of entries that the server
1796 * should return for the search. A value of
1797 * zero indicates that there should be no limit.
1798 * @param timeLimit The maximum length of time in seconds that
1799 * the server should spend processing this
1800 * search request. A value of zero indicates
1801 * that there should be no limit.
1802 * @param typesOnly Indicates whether to return only attribute
1803 * names in matching entries, or both attribute
1804 * names and values.
1805 * @param filter The filter to use to identify matching
1806 * entries. It must not be {@code null}.
1807 * @param attributes The set of attributes that should be returned
1808 * in matching entries. It may be {@code null}
1809 * or empty if the default attribute set (all
1810 * user attributes) is to be requested.
1811 *
1812 * @return A search result object that provides information about the
1813 * processing of the search, potentially including the set of
1814 * matching entries and search references returned by the server.
1815 *
1816 * @throws LDAPSearchException If the search does not complete successfully,
1817 * or if a problem is encountered while sending
1818 * the request or reading the response.
1819 */
1820 public final SearchResult
1821 search(final SearchResultListener searchResultListener,
1822 final String baseDN, final SearchScope scope,
1823 final DereferencePolicy derefPolicy, final int sizeLimit,
1824 final int timeLimit, final boolean typesOnly,
1825 final Filter filter, final String... attributes)
1826 throws LDAPSearchException
1827 {
1828 return search(new SearchRequest(searchResultListener, baseDN, scope,
1829 derefPolicy, sizeLimit, timeLimit, typesOnly, filter, attributes));
1830 }
1831
1832
1833
1834 /**
1835 * Processes the provided search request using a connection from this
1836 * connection pool.
1837 *
1838 * @param searchRequest The search request to be processed. It must not be
1839 * {@code null}.
1840 *
1841 * @return A search result object that provides information about the
1842 * processing of the search, potentially including the set of
1843 * matching entries and search references returned by the server.
1844 *
1845 * @throws LDAPSearchException If the search does not complete successfully,
1846 * or if a problem is encountered while sending
1847 * the request or reading the response.
1848 */
1849 public final SearchResult search(final SearchRequest searchRequest)
1850 throws LDAPSearchException
1851 {
1852 final LDAPConnection conn;
1853 try
1854 {
1855 conn = getConnection();
1856 }
1857 catch (LDAPException le)
1858 {
1859 debugException(le);
1860 throw new LDAPSearchException(le);
1861 }
1862
1863 try
1864 {
1865 final SearchResult result = conn.search(searchRequest);
1866 releaseConnection(conn);
1867 return result;
1868 }
1869 catch (Throwable t)
1870 {
1871 throwLDAPSearchExceptionIfShouldNotRetry(t, conn);
1872
1873 // If we have gotten here, then we should retry the operation with a
1874 // newly-created connection.
1875 final LDAPConnection newConn;
1876 try
1877 {
1878 newConn = replaceDefunctConnection(t, conn);
1879 }
1880 catch (final LDAPException le)
1881 {
1882 debugException(le);
1883 throw new LDAPSearchException(le);
1884 }
1885
1886 try
1887 {
1888 final SearchResult result = newConn.search(searchRequest);
1889 releaseConnection(newConn);
1890 return result;
1891 }
1892 catch (final Throwable t2)
1893 {
1894 throwLDAPSearchException(t2, newConn);
1895 }
1896
1897 // This return statement should never be reached.
1898 return null;
1899 }
1900 }
1901
1902
1903
1904 /**
1905 * Processes the provided search request using a connection from this
1906 * connection pool.
1907 *
1908 * @param searchRequest The search request to be processed. It must not be
1909 * {@code null}.
1910 *
1911 * @return A search result object that provides information about the
1912 * processing of the search, potentially including the set of
1913 * matching entries and search references returned by the server.
1914 *
1915 * @throws LDAPSearchException If the search does not complete successfully,
1916 * or if a problem is encountered while sending
1917 * the request or reading the response.
1918 */
1919 public final SearchResult search(final ReadOnlySearchRequest searchRequest)
1920 throws LDAPSearchException
1921 {
1922 return search((SearchRequest) searchRequest);
1923 }
1924
1925
1926
1927 /**
1928 * Processes a search operation with the provided information using a
1929 * connection from this connection pool. It is expected that at most one
1930 * entry will be returned from the search, and that no additional content from
1931 * the successful search result (e.g., diagnostic message or response
1932 * controls) are needed.
1933 *
1934 * @param baseDN The base DN for the search request. It must not be
1935 * {@code null}.
1936 * @param scope The scope that specifies the range of entries that
1937 * should be examined for the search.
1938 * @param filter The string representation of the filter to use to
1939 * identify matching entries. It must not be
1940 * {@code null}.
1941 * @param attributes The set of attributes that should be returned in
1942 * matching entries. It may be {@code null} or empty if
1943 * the default attribute set (all user attributes) is to
1944 * be requested.
1945 *
1946 * @return The entry that was returned from the search, or {@code null} if no
1947 * entry was returned or the base entry does not exist.
1948 *
1949 * @throws LDAPSearchException If the search does not complete successfully,
1950 * if more than a single entry is returned, or
1951 * if a problem is encountered while parsing the
1952 * provided filter string, sending the request,
1953 * or reading the response.
1954 */
1955 public final SearchResultEntry searchForEntry(final String baseDN,
1956 final SearchScope scope,
1957 final String filter,
1958 final String... attributes)
1959 throws LDAPSearchException
1960 {
1961 return searchForEntry(new SearchRequest(baseDN, scope,
1962 DereferencePolicy.NEVER, 1, 0, false, parseFilter(filter),
1963 attributes));
1964 }
1965
1966
1967
1968 /**
1969 * Processes a search operation with the provided information using a
1970 * connection from this connection pool. It is expected that at most one
1971 * entry will be returned from the search, and that no additional content from
1972 * the successful search result (e.g., diagnostic message or response
1973 * controls) are needed.
1974 *
1975 * @param baseDN The base DN for the search request. It must not be
1976 * {@code null}.
1977 * @param scope The scope that specifies the range of entries that
1978 * should be examined for the search.
1979 * @param filter The string representation of the filter to use to
1980 * identify matching entries. It must not be
1981 * {@code null}.
1982 * @param attributes The set of attributes that should be returned in
1983 * matching entries. It may be {@code null} or empty if
1984 * the default attribute set (all user attributes) is to
1985 * be requested.
1986 *
1987 * @return The entry that was returned from the search, or {@code null} if no
1988 * entry was returned or the base entry does not exist.
1989 *
1990 * @throws LDAPSearchException If the search does not complete successfully,
1991 * if more than a single entry is returned, or
1992 * if a problem is encountered while parsing the
1993 * provided filter string, sending the request,
1994 * or reading the response.
1995 */
1996 public final SearchResultEntry searchForEntry(final String baseDN,
1997 final SearchScope scope,
1998 final Filter filter,
1999 final String... attributes)
2000 throws LDAPSearchException
2001 {
2002 return searchForEntry(new SearchRequest(baseDN, scope,
2003 DereferencePolicy.NEVER, 1, 0, false, filter, attributes));
2004 }
2005
2006
2007
2008 /**
2009 * Processes a search operation with the provided information using a
2010 * connection from this connection pool. It is expected that at most one
2011 * entry will be returned from the search, and that no additional content from
2012 * the successful search result (e.g., diagnostic message or response
2013 * controls) are needed.
2014 *
2015 * @param baseDN The base DN for the search request. It must not be
2016 * {@code null}.
2017 * @param scope The scope that specifies the range of entries that
2018 * should be examined for the search.
2019 * @param derefPolicy The dereference policy the server should use for any
2020 * aliases encountered while processing the search.
2021 * @param timeLimit The maximum length of time in seconds that the server
2022 * should spend processing this search request. A value
2023 * of zero indicates that there should be no limit.
2024 * @param typesOnly Indicates whether to return only attribute names in
2025 * matching entries, or both attribute names and values.
2026 * @param filter The string representation of the filter to use to
2027 * identify matching entries. It must not be
2028 * {@code null}.
2029 * @param attributes The set of attributes that should be returned in
2030 * matching entries. It may be {@code null} or empty if
2031 * the default attribute set (all user attributes) is to
2032 * be requested.
2033 *
2034 * @return The entry that was returned from the search, or {@code null} if no
2035 * entry was returned or the base entry does not exist.
2036 *
2037 * @throws LDAPSearchException If the search does not complete successfully,
2038 * if more than a single entry is returned, or
2039 * if a problem is encountered while parsing the
2040 * provided filter string, sending the request,
2041 * or reading the response.
2042 */
2043 public final SearchResultEntry
2044 searchForEntry(final String baseDN, final SearchScope scope,
2045 final DereferencePolicy derefPolicy, final int timeLimit,
2046 final boolean typesOnly, final String filter,
2047 final String... attributes)
2048 throws LDAPSearchException
2049 {
2050 return searchForEntry(new SearchRequest(baseDN, scope, derefPolicy, 1,
2051 timeLimit, typesOnly, parseFilter(filter), attributes));
2052 }
2053
2054
2055
2056 /**
2057 * Processes a search operation with the provided information using a
2058 * connection from this connection pool. It is expected that at most one
2059 * entry will be returned from the search, and that no additional content from
2060 * the successful search result (e.g., diagnostic message or response
2061 * controls) are needed.
2062 *
2063 * @param baseDN The base DN for the search request. It must not be
2064 * {@code null}.
2065 * @param scope The scope that specifies the range of entries that
2066 * should be examined for the search.
2067 * @param derefPolicy The dereference policy the server should use for any
2068 * aliases encountered while processing the search.
2069 * @param timeLimit The maximum length of time in seconds that the server
2070 * should spend processing this search request. A value
2071 * of zero indicates that there should be no limit.
2072 * @param typesOnly Indicates whether to return only attribute names in
2073 * matching entries, or both attribute names and values.
2074 * @param filter The filter to use to identify matching entries. It
2075 * must not be {@code null}.
2076 * @param attributes The set of attributes that should be returned in
2077 * matching entries. It may be {@code null} or empty if
2078 * the default attribute set (all user attributes) is to
2079 * be requested.
2080 *
2081 * @return The entry that was returned from the search, or {@code null} if no
2082 * entry was returned or the base entry does not exist.
2083 *
2084 * @throws LDAPSearchException If the search does not complete successfully,
2085 * if more than a single entry is returned, or
2086 * if a problem is encountered while parsing the
2087 * provided filter string, sending the request,
2088 * or reading the response.
2089 */
2090 public final SearchResultEntry
2091 searchForEntry(final String baseDN, final SearchScope scope,
2092 final DereferencePolicy derefPolicy, final int timeLimit,
2093 final boolean typesOnly, final Filter filter,
2094 final String... attributes)
2095 throws LDAPSearchException
2096 {
2097 return searchForEntry(new SearchRequest(baseDN, scope, derefPolicy, 1,
2098 timeLimit, typesOnly, filter, attributes));
2099 }
2100
2101
2102
2103 /**
2104 * Processes a search operation with the provided information using a
2105 * connection from this connection pool. It is expected that at most one
2106 * entry will be returned from the search, and that no additional content from
2107 * the successful search result (e.g., diagnostic message or response
2108 * controls) are needed.
2109 *
2110 * @param searchRequest The search request to be processed. If it is
2111 * configured with a search result listener or a size
2112 * limit other than one, then the provided request will
2113 * be duplicated with the appropriate settings.
2114 *
2115 * It must not be
2116 * {@code null}, it must not be configured with a
2117 * search result listener, and it should be configured
2118 * with a size limit of one.
2119 *
2120 * @return The entry that was returned from the search, or {@code null} if no
2121 * entry was returned or the base entry does not exist.
2122 *
2123 * @throws LDAPSearchException If the search does not complete successfully,
2124 * if more than a single entry is returned, or
2125 * if a problem is encountered while parsing the
2126 * provided filter string, sending the request,
2127 * or reading the response.
2128 */
2129 public final SearchResultEntry searchForEntry(
2130 final SearchRequest searchRequest)
2131 throws LDAPSearchException
2132 {
2133 final LDAPConnection conn;
2134 try
2135 {
2136 conn = getConnection();
2137 }
2138 catch (LDAPException le)
2139 {
2140 debugException(le);
2141 throw new LDAPSearchException(le);
2142 }
2143
2144 try
2145 {
2146 final SearchResultEntry entry = conn.searchForEntry(searchRequest);
2147 releaseConnection(conn);
2148 return entry;
2149 }
2150 catch (Throwable t)
2151 {
2152 throwLDAPSearchExceptionIfShouldNotRetry(t, conn);
2153
2154 // If we have gotten here, then we should retry the operation with a
2155 // newly-created connection.
2156 final LDAPConnection newConn;
2157 try
2158 {
2159 newConn = replaceDefunctConnection(t, conn);
2160 }
2161 catch (final LDAPException le)
2162 {
2163 debugException(le);
2164 throw new LDAPSearchException(le);
2165 }
2166
2167 try
2168 {
2169 final SearchResultEntry entry = newConn.searchForEntry(searchRequest);
2170 releaseConnection(newConn);
2171 return entry;
2172 }
2173 catch (final Throwable t2)
2174 {
2175 throwLDAPSearchException(t2, newConn);
2176 }
2177
2178 // This return statement should never be reached.
2179 return null;
2180 }
2181 }
2182
2183
2184
2185 /**
2186 * Processes a search operation with the provided information using a
2187 * connection from this connection pool. It is expected that at most one
2188 * entry will be returned from the search, and that no additional content from
2189 * the successful search result (e.g., diagnostic message or response
2190 * controls) are needed.
2191 *
2192 * @param searchRequest The search request to be processed. If it is
2193 * configured with a search result listener or a size
2194 * limit other than one, then the provided request will
2195 * be duplicated with the appropriate settings.
2196 *
2197 * @return The entry that was returned from the search, or {@code null} if no
2198 * entry was returned or the base entry does not exist.
2199 *
2200 * @throws LDAPSearchException If the search does not complete successfully,
2201 * if more than a single entry is returned, or
2202 * if a problem is encountered while parsing the
2203 * provided filter string, sending the request,
2204 * or reading the response.
2205 */
2206 public final SearchResultEntry searchForEntry(
2207 final ReadOnlySearchRequest searchRequest)
2208 throws LDAPSearchException
2209 {
2210 return searchForEntry((SearchRequest) searchRequest);
2211 }
2212
2213
2214
2215 /**
2216 * Parses the provided string as a {@code Filter} object.
2217 *
2218 * @param filterString The string to parse as a {@code Filter}.
2219 *
2220 * @return The parsed {@code Filter}.
2221 *
2222 * @throws LDAPSearchException If the provided string does not represent a
2223 * valid search filter.
2224 */
2225 private static Filter parseFilter(final String filterString)
2226 throws LDAPSearchException
2227 {
2228 try
2229 {
2230 return Filter.create(filterString);
2231 }
2232 catch (final LDAPException le)
2233 {
2234 debugException(le);
2235 throw new LDAPSearchException(le);
2236 }
2237 }
2238
2239
2240
2241 /**
2242 * Processes multiple requests in the order they are provided over a single
2243 * connection from this pool. Note that the
2244 * {@link #retryFailedOperationsDueToInvalidConnections()} setting will be
2245 * ignored when processing the provided operations, so that any failed
2246 * operations will not be retried.
2247 *
2248 * @param requests The list of requests to be processed. It must not
2249 * be {@code null} or empty.
2250 * @param continueOnError Indicates whether to attempt to process subsequent
2251 * requests if any of the operations does not
2252 * complete successfully.
2253 *
2254 * @return The set of results from the requests that were processed. The
2255 * order of result objects will correspond to the order of the
2256 * request objects, although the list of results may contain fewer
2257 * elements than the list of requests if an error occurred during
2258 * processing and {@code continueOnError} is {@code false}.
2259 *
2260 * @throws LDAPException If a problem occurs while trying to obtain a
2261 * connection to use for the requests.
2262 */
2263 public final List<LDAPResult> processRequests(
2264 final List<LDAPRequest> requests,
2265 final boolean continueOnError)
2266 throws LDAPException
2267 {
2268 ensureNotNull(requests);
2269 ensureFalse(requests.isEmpty(),
2270 "LDAPConnectionPool.processRequests.requests must not be empty.");
2271
2272 final LDAPConnection conn;
2273 try
2274 {
2275 conn = getConnection();
2276 }
2277 catch (LDAPException le)
2278 {
2279 debugException(le);
2280 throw new LDAPSearchException(le);
2281 }
2282
2283 final ArrayList<LDAPResult> results =
2284 new ArrayList<LDAPResult>(requests.size());
2285 boolean isDefunct = false;
2286
2287 try
2288 {
2289 requestLoop:
2290 for (final LDAPRequest request : requests)
2291 {
2292 try
2293 {
2294 final LDAPResult result = request.process(conn, 1);
2295 results.add(result);
2296 switch (result.getResultCode().intValue())
2297 {
2298 case ResultCode.SUCCESS_INT_VALUE:
2299 case ResultCode.COMPARE_FALSE_INT_VALUE:
2300 case ResultCode.COMPARE_TRUE_INT_VALUE:
2301 case ResultCode.NO_OPERATION_INT_VALUE:
2302 // These will be considered successful operations.
2303 break;
2304
2305 default:
2306 // Anything else will be considered a failure.
2307 if (! ResultCode.isConnectionUsable(result.getResultCode()))
2308 {
2309 isDefunct = true;
2310 }
2311
2312 if (! continueOnError)
2313 {
2314 break requestLoop;
2315 }
2316 break;
2317 }
2318 }
2319 catch (LDAPException le)
2320 {
2321 debugException(le);
2322 results.add(new LDAPResult(request.getLastMessageID(),
2323 le.getResultCode(), le.getMessage(),
2324 le.getMatchedDN(), le.getReferralURLs(),
2325 le.getResponseControls()));
2326
2327 if (! ResultCode.isConnectionUsable(le.getResultCode()))
2328 {
2329 isDefunct = true;
2330 }
2331
2332 if (! continueOnError)
2333 {
2334 break;
2335 }
2336 }
2337 }
2338 }
2339 finally
2340 {
2341 if (isDefunct)
2342 {
2343 releaseDefunctConnection(conn);
2344 }
2345 else
2346 {
2347 releaseConnection(conn);
2348 }
2349 }
2350
2351 return results;
2352 }
2353
2354
2355
2356 /**
2357 * Examines the provided {@code Throwable} object to determine whether it
2358 * represents an {@code LDAPException} that indicates the associated
2359 * connection may no longer be valid. If that is the case, and if such
2360 * operations should be retried, then no exception will be thrown. Otherwise,
2361 * an appropriate {@code LDAPException} will be thrown.
2362 *
2363 * @param t The {@code Throwable} object that was caught.
2364 * @param o The type of operation for which to make the determination.
2365 * @param conn The connection to be released to the pool.
2366 *
2367 * @throws LDAPException To indicate that a problem occurred during LDAP
2368 * processing and the operation should not be retried.
2369 */
2370 private void throwLDAPExceptionIfShouldNotRetry(final Throwable t,
2371 final OperationType o,
2372 final LDAPConnection conn)
2373 throws LDAPException
2374 {
2375 if ((t instanceof LDAPException) &&
2376 getOperationTypesToRetryDueToInvalidConnections().contains(o))
2377 {
2378 final LDAPException le = (LDAPException) t;
2379 final LDAPConnectionPoolHealthCheck healthCheck = getHealthCheck();
2380
2381 try
2382 {
2383 healthCheck.ensureConnectionValidAfterException(conn, le);
2384 }
2385 catch (final Exception e)
2386 {
2387 // If we have gotten this exception, then it indicates that the
2388 // connection is no longer valid and the operation should be retried.
2389 debugException(e);
2390 return;
2391 }
2392 }
2393
2394 throwLDAPException(t, conn);
2395 }
2396
2397
2398
2399 /**
2400 * Examines the provided {@code Throwable} object to determine whether it
2401 * represents an {@code LDAPException} that indicates the associated
2402 * connection may no longer be valid. If that is the case, and if such
2403 * operations should be retried, then no exception will be thrown. Otherwise,
2404 * an appropriate {@code LDAPSearchException} will be thrown.
2405 *
2406 * @param t The {@code Throwable} object that was caught.
2407 * @param conn The connection to be released to the pool.
2408 *
2409 * @throws LDAPSearchException To indicate that a problem occurred during
2410 * LDAP processing and the operation should not
2411 * be retried.
2412 */
2413 private void throwLDAPSearchExceptionIfShouldNotRetry(final Throwable t,
2414 final LDAPConnection conn)
2415 throws LDAPSearchException
2416 {
2417 if ((t instanceof LDAPException) &&
2418 getOperationTypesToRetryDueToInvalidConnections().contains(
2419 OperationType.SEARCH))
2420 {
2421 final LDAPException le = (LDAPException) t;
2422 final LDAPConnectionPoolHealthCheck healthCheck = getHealthCheck();
2423
2424 try
2425 {
2426 healthCheck.ensureConnectionValidAfterException(conn, le);
2427 }
2428 catch (final Exception e)
2429 {
2430 // If we have gotten this exception, then it indicates that the
2431 // connection is no longer valid and the operation should be retried.
2432 debugException(e);
2433 return;
2434 }
2435 }
2436
2437 throwLDAPSearchException(t, conn);
2438 }
2439
2440
2441
2442 /**
2443 * Handles the provided {@code Throwable} object by ensuring that the provided
2444 * connection is released to the pool and throwing an appropriate
2445 * {@code LDAPException} object.
2446 *
2447 * @param t The {@code Throwable} object that was caught.
2448 * @param conn The connection to be released to the pool.
2449 *
2450 * @throws LDAPException To indicate that a problem occurred during LDAP
2451 * processing.
2452 */
2453 void throwLDAPException(final Throwable t, final LDAPConnection conn)
2454 throws LDAPException
2455 {
2456 debugException(t);
2457 if (t instanceof LDAPException)
2458 {
2459 final LDAPException le = (LDAPException) t;
2460 releaseConnectionAfterException(conn, le);
2461 throw le;
2462 }
2463 else
2464 {
2465 releaseDefunctConnection(conn);
2466 throw new LDAPException(ResultCode.LOCAL_ERROR,
2467 ERR_POOL_OP_EXCEPTION.get(getExceptionMessage(t)), t);
2468 }
2469 }
2470
2471
2472
2473 /**
2474 * Handles the provided {@code Throwable} object by ensuring that the provided
2475 * connection is released to the pool and throwing an appropriate
2476 * {@code LDAPSearchException} object.
2477 *
2478 * @param t The {@code Throwable} object that was caught.
2479 * @param conn The connection to be released to the pool.
2480 *
2481 * @throws LDAPSearchException To indicate that a problem occurred during
2482 * LDAP search processing.
2483 */
2484 void throwLDAPSearchException(final Throwable t, final LDAPConnection conn)
2485 throws LDAPSearchException
2486 {
2487 debugException(t);
2488 if (t instanceof LDAPException)
2489 {
2490 final LDAPSearchException lse;
2491 if (t instanceof LDAPSearchException)
2492 {
2493 lse = (LDAPSearchException) t;
2494 }
2495 else
2496 {
2497 lse = new LDAPSearchException((LDAPException) t);
2498 }
2499
2500 releaseConnectionAfterException(conn, lse);
2501 throw lse;
2502 }
2503 else
2504 {
2505 releaseDefunctConnection(conn);
2506 throw new LDAPSearchException(ResultCode.LOCAL_ERROR,
2507 ERR_POOL_OP_EXCEPTION.get(getExceptionMessage(t)), t);
2508 }
2509 }
2510
2511
2512
2513 /**
2514 * Retrieves a string representation of this connection pool.
2515 *
2516 * @return A string representation of this connection pool.
2517 */
2518 @Override()
2519 public final String toString()
2520 {
2521 final StringBuilder buffer = new StringBuilder();
2522 toString(buffer);
2523 return buffer.toString();
2524 }
2525
2526
2527
2528 /**
2529 * Appends a string representation of this connection pool to the provided
2530 * buffer.
2531 *
2532 * @param buffer The buffer to which the string representation should be
2533 * appended.
2534 */
2535 public abstract void toString(final StringBuilder buffer);
2536 }