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