001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 021package org.apache.directory.ldap.client.api; 022 023 024import org.apache.directory.api.asn1.util.Oid; 025import org.apache.directory.api.ldap.model.exception.LdapException; 026import org.apache.directory.api.ldap.model.message.BindRequest; 027import org.apache.directory.api.ldap.model.message.ExtendedRequest; 028import org.apache.directory.api.ldap.model.name.Dn; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032 033/** 034 * A factory for creating LdapConnection objects managed by LdapConnectionPool. 035 * A bind operation is executed upon return if any of the following operations 036 * were performed on the connection while it was checked out: 037 * 038 * <ul> 039 * <li>{@link LdapConnection#bind() bind()}</li> 040 * <li>{@link LdapConnection#anonymousBind() anonymousBind()}</li> 041 * <li>{@link LdapConnection#bind(String) bind(String)}</li> 042 * <li>{@link LdapConnection#bind(String, String) bind(String, String)}</li> 043 * <li>{@link LdapConnection#bind(Dn) bind(Dn)}</li> 044 * <li>{@link LdapConnection#bind(Dn, String) bind(Dn, String)}</li> 045 * <li>{@link LdapConnection#bind(BindRequest) bind(BindRequest)}</li> 046 * <li>{@link LdapConnection#extended(String) extended(String)} <i>where oid is StartTLS</i></li> 047 * <li>{@link LdapConnection#extended(String, byte[]) extended(String, byte[])} <i>where oid is StartTLS</i></li> 048 * <li>{@link LdapConnection#extended(Oid) extended(String)} <i>where oid is StartTLS</i></li> 049 * <li>{@link LdapConnection#extended(Oid, byte[]) extended(String, byte[])} <i>where oid is StartTLS</i></li> 050 * <li>{@link LdapConnection#extended(ExtendedRequest) extended(ExtendedRequest)} <i>where ExtendedRequest is StartTLS</i></li> 051 * </ul> 052 * 053 * This is a <i>MOSTLY</i> safe way to handle connections in a pool. If one 054 * would like to use a slightly less expensive pool factory, the 055 * {@link DefaultPoolableLdapConnectionFactory} may be the right choice. 056 * 057 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 058 */ 059public class ValidatingPoolableLdapConnectionFactory extends AbstractPoolableLdapConnectionFactory 060{ 061 /** This class logger */ 062 private static final Logger LOG = LoggerFactory.getLogger( ValidatingPoolableLdapConnectionFactory.class ); 063 064 065 /** 066 * Creates a new instance of ValidatingPoolableLdapConnectionFactory. 067 * 068 * @param config the configuration for creating LdapConnections 069 */ 070 public ValidatingPoolableLdapConnectionFactory( LdapConnectionConfig config ) 071 { 072 this( new DefaultLdapConnectionFactory( config ) ); 073 } 074 075 076 /** 077 * Creates a new instance of ValidatingPoolableLdapConnectionFactory. The 078 * <code>connectionFactoryClass</code> must have a public constructor accepting 079 * an <code>LdapConnectionConfig</code> object or an 080 * <code>IllegalArgumentException</code> will be thrown. 081 * 082 * @param config the configuration for creating LdapConnections 083 * @param connectionFactoryClass An implementation class of for the 084 * LDAP connection factory. 085 * @throws IllegalArgumentException If the instantiation of an instance of 086 * the <code>connectionFactoryClass</code> fails. 087 */ 088 public ValidatingPoolableLdapConnectionFactory( LdapConnectionConfig config, 089 Class<? extends LdapConnectionFactory> connectionFactoryClass ) 090 { 091 this( newLdapConnectionFactory( config, connectionFactoryClass ) ); 092 } 093 094 095 /** 096 * Creates a new instance of ValidatingPoolableLdapConnectionFactory. 097 * 098 * @param connectionFactory the connection factory for creating LdapConnections 099 */ 100 public ValidatingPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory ) 101 { 102 this.connectionFactory = connectionFactory; 103 } 104 105 106 /** 107 * {@inheritDoc} 108 * 109 * There is nothing to do to activate a connection. 110 */ 111 @Override 112 public void activateObject( LdapConnection connection ) throws LdapException 113 { 114 LOG.debug( "Activating {}", connection ); 115 super.activateObject( connection ); 116 117 // clear the monitors 118 ( ( MonitoringLdapConnection ) connection ).resetMonitors(); 119 } 120 121 122 /** 123 * {@inheritDoc} 124 * 125 * Specifically, we are creating a new connection based on the LdapConnection Factory 126 * we used to create this pool of connections. The default is to create bound connections. 127 * 128 * @throws LdapException If unable to connect. 129 */ 130 @Override 131 public MonitoringLdapConnection makeObject() throws LdapException 132 { 133 LOG.debug( "Creating a LDAP connection" ); 134 return new MonitoringLdapConnection( connectionFactory.newLdapConnection() ); 135 } 136 137 138 /** 139 * {@inheritDoc} 140 * 141 * Here, passivating a connection means we re-bind it, so that the existing LDAPSession 142 * is reset. 143 * 144 * @throws LdapException If unable to reconfigure and rebind. 145 */ 146 @Override 147 public void passivateObject( LdapConnection connection ) throws LdapException 148 { 149 LOG.debug( "Passivating {}", connection ); 150 151 if ( !connection.isConnected() || !connection.isAuthenticated() 152 || ( ( MonitoringLdapConnection ) connection ).bindCalled() ) 153 { 154 LOG.debug( "rebind due to bind on connection {}", connection ); 155 connectionFactory.bindConnection( connection ); 156 } 157 if ( ( ( MonitoringLdapConnection ) connection ).startTlsCalled() ) 158 { 159 LOG.debug( "unbind/rebind due to startTls on {}", connection ); 160 // unbind to clear the tls 161 connection.unBind(); 162 connectionFactory.bindConnection( connection ); 163 } 164 165 // in case connection had configuration changed 166 connectionFactory.configureConnection( connection ); 167 } 168}