View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  
21  package org.apache.directory.ldap.client.api;
22  
23  
24  import org.apache.commons.pool.PoolableObjectFactory;
25  import org.apache.commons.pool.impl.GenericObjectPool;
26  import org.apache.directory.api.ldap.codec.api.LdapApiService;
27  import org.apache.directory.api.ldap.model.exception.LdapException;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  
32  /**
33   * A pool implementation for LdapConnection objects.
34   * 
35   * This class is just a wrapper around the commons GenericObjectPool, and has
36   * a more meaningful name to represent the pool type.
37   * 
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   */
40  public class LdapConnectionPool extends GenericObjectPool<LdapConnection>
41  {
42      private static final Logger LOG = LoggerFactory.getLogger( LdapConnectionPool.class );
43  
44      private PoolableObjectFactory<LdapConnection> factory;
45  
46  
47      /**
48       * Instantiates a new LDAP connection pool.
49       *
50       * @param connectionConfig The connection configuration
51       * @param apiService The api service (codec)
52       * @param timeout The connection timeout in millis
53       */
54      public LdapConnectionPool( LdapConnectionConfig connectionConfig,
55          LdapApiService apiService, long timeout )
56      {
57          this( connectionConfig, apiService, timeout, null );
58      }
59  
60  
61      /**
62       * Instantiates a new LDAP connection pool.
63       *
64       * @param connectionConfig The connection configuration
65       * @param apiService The api service (codec)
66       * @param timeout The connection timeout in millis
67       * @param poolConfig The pool configuration
68       */
69      public LdapConnectionPool( LdapConnectionConfig connectionConfig,
70          LdapApiService apiService, long timeout, Config poolConfig )
71      {
72          this( newPoolableConnectionFactory( connectionConfig, apiService, timeout ), poolConfig );
73      }
74  
75  
76      /**
77       * Instantiates a new LDAP connection pool.
78       *
79       * @param factory The LDAP connection factory
80       */
81      public LdapConnectionPool( PoolableObjectFactory<LdapConnection> factory )
82      {
83          this( factory, null );
84      }
85  
86  
87      /**
88       * Instantiates a new LDAP connection pool.
89       *
90       * @param factory The LDAP connection factory
91       * @param poolConfig The pool configuration
92       */
93      public LdapConnectionPool( PoolableObjectFactory<LdapConnection> factory, Config poolConfig )
94      {
95          super( factory, poolConfig == null ? new Config() : poolConfig );
96          this.factory = factory;
97      }
98  
99  
100     /**
101      * Returns the LdapApiService instance used by this connection pool.
102      *
103      * @return The LdapApiService instance used by this connection pool.
104      */
105     public LdapApiService getLdapApiService()
106     {
107         return ( ( AbstractPoolableLdapConnectionFactory ) factory ).getLdapApiService();
108     }
109 
110 
111     /**
112      * Gives a LdapConnection fetched from the pool.
113      *
114      * @return an LdapConnection object from pool
115      * @throws LdapException if an error occurs while obtaining a connection from the factory
116      */
117     public LdapConnection getConnection() throws LdapException
118     {
119         LdapConnection connection;
120 
121         try
122         {
123             connection = super.borrowObject();
124             LOG.trace( "borrowed connection {}", connection );
125         }
126         catch ( LdapException | RuntimeException e )
127         {
128             throw e;
129         }
130         catch ( Exception e )
131         {
132             // wrap in runtime, but this should NEVER happen per published 
133             // contract as it only throws what the makeObject throws and our 
134             // PoolableLdapConnectionFactory only throws LdapException
135             LOG.error( "An unexpected exception was thrown: ", e );
136             throw new RuntimeException( e );
137         }
138 
139         return connection;
140     }
141 
142 
143     private static ValidatingPoolableLdapConnectionFactory newPoolableConnectionFactory(
144         LdapConnectionConfig connectionConfig, LdapApiService apiService,
145         long timeout )
146     {
147         DefaultLdapConnectionFactory connectionFactory =
148             new DefaultLdapConnectionFactory( connectionConfig );
149         connectionFactory.setLdapApiService( apiService );
150         connectionFactory.setTimeOut( timeout );
151         return new ValidatingPoolableLdapConnectionFactory( connectionFactory );
152     }
153 
154 
155     /**
156      * Places the given LdapConnection back in the pool.
157      * 
158      * @param connection the LdapConnection to be released
159      * @throws LdapException if an error occurs while releasing the connection
160      */
161     public void releaseConnection( LdapConnection connection ) throws LdapException
162     {
163         try
164         {
165             super.returnObject( connection );
166             LOG.trace( "returned connection {}", connection );
167         }
168         catch ( LdapException | RuntimeException e )
169         {
170             throw e;
171         }
172         catch ( Exception e )
173         {
174             // wrap in runtime, but this should NEVER happen as it only throws 
175             // what the passivateObject throws and our 
176             // PoolableLdapConnectionFactory only throws LdapException
177             LOG.error( "An unexpected exception was thrown: ", e );
178             throw new RuntimeException( e );
179         }
180     }
181 }