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 java.lang.reflect.Constructor;
25  
26  import org.apache.commons.pool.PoolableObjectFactory;
27  import org.apache.directory.api.ldap.codec.api.LdapApiService;
28  import org.apache.directory.api.ldap.model.exception.LdapException;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  
33  /**
34   * An abstract class implementing the PoolableObjectFactory, for LdapConnections.
35   *
36   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
37   */
38  public abstract class AbstractPoolableLdapConnectionFactory implements PoolableObjectFactory<LdapConnection>
39  {
40      /** This class logger */
41      private static final Logger LOG = LoggerFactory.getLogger( AbstractPoolableLdapConnectionFactory.class );
42  
43      /** The factory to use to create a new connection */
44      protected LdapConnectionFactory connectionFactory;
45  
46      /** The validator to use */
47      protected LdapConnectionValidator validator = new LookupLdapConnectionValidator();
48  
49      /**
50       * {@inheritDoc}
51       * 
52       * There is nothing to do to activate a connection.
53       */
54      public void activateObject( LdapConnection connection ) throws LdapException
55      {
56          LOG.debug( "Activating {}", connection );
57          if ( !connection.isConnected() || !connection.isAuthenticated() )
58          {
59              LOG.debug( "rebind due to connection dropped on {}", connection );
60              connectionFactory.bindConnection( connection );
61          }
62      }
63  
64  
65      /**
66       * {@inheritDoc}
67       * 
68       * Destroying a connection will unbind it which will result on a shutdown
69       * of teh underlying protocol.
70       */
71      public void destroyObject( LdapConnection connection ) throws LdapException
72      {
73          LOG.debug( "Destroying {}", connection );
74  
75          try
76          {
77              // https://tools.ietf.org/html/rfc2251#section-4.3
78              // unbind closes the connection so no need to close
79              connection.unBind();
80          }
81          catch ( LdapException e )
82          {
83              LOG.error( "unable to unbind connection: {}", e.getMessage() );
84              LOG.debug( "unable to unbind connection:", e );
85          }
86      }
87  
88  
89      /**
90       * Returns the LdapApiService instance used by this factory.
91       *
92       * @return The LdapApiService instance used by this factory
93       */
94      public LdapApiService getLdapApiService()
95      {
96          return connectionFactory.getLdapApiService();
97      }
98  
99  
100     /**
101      * {@inheritDoc}
102      * Specifically, we are creating a new connection based on the LdapConnection Factory
103      * we used to create this pool of connections. The default is to create bound connections.
104      * 
105      * @throws LdapException If unable to connect.
106      */
107     public LdapConnection makeObject() throws LdapException
108     {
109         LOG.debug( "Creating a LDAP connection" );
110         return connectionFactory.newLdapConnection();
111     }
112 
113 
114     protected static LdapConnectionFactory newLdapConnectionFactory(
115         LdapConnectionConfig config,
116         Class<? extends LdapConnectionFactory> connectionFactoryClass )
117     {
118         try
119         {
120             Constructor<? extends LdapConnectionFactory> constructor =
121                 connectionFactoryClass.getConstructor( LdapConnectionConfig.class );
122             return constructor.newInstance( config );
123         }
124         catch ( Exception e )
125         {
126             throw new IllegalArgumentException( "unable to create LdapConnectionFactory" + e.getMessage(), e );
127         }
128     }
129 
130 
131     /**
132      * {@inheritDoc}
133      * 
134      * We don't do anything with the connection. It remains in the state it was before
135      * being used.
136      * 
137      * @throws LdapException If unable to reconfigure and rebind.
138      */
139     public void passivateObject( LdapConnection connection ) throws LdapException
140     {
141         LOG.debug( "Passivating {}", connection );
142     }
143   
144     
145     /**
146      * Sets the validator to use when validation occurs.  Note that validation
147      * will only occur if the connection pool was configured to validate.  This
148      * means one of:
149      * <ul>
150      * <li>{@link org.apache.commons.pool.impl.GenericObjectPool#setTestOnBorrow setTestOnBorrow}</li>
151      * <li>{@link org.apache.commons.pool.impl.GenericObjectPool#setTestWhileIdle setTestWhileIdle}</li>
152      * <li>{@link org.apache.commons.pool.impl.GenericObjectPool#setTestOnReturn setTestOnReturn}</li>
153      * </ul>
154      * must have been set to true on the pool.  The default validator is 
155      * {@link LookupLdapConnectionValidator}.
156      *
157      * @param validator The validator
158      */
159     public void setValidator( LdapConnectionValidator validator ) 
160     {
161         this.validator = validator;
162     }
163 
164 
165     /**
166      * {@inheritDoc}
167      * 
168      * Validating a connection is done by checking the connection status.
169      */
170     public boolean validateObject( LdapConnection connection )
171     {
172         LOG.debug( "Validating {}", connection );
173         return validator.validate( connection );
174     }
175 }