/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.provider;
import org.ldaptive.ConnectionFactoryMetadata;
import org.ldaptive.ConnectionStrategy;
import org.ldaptive.LdapException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides a basic implementation for other connection factories to inherit.
*
* @param <T> type of provider config for this connection factory
*
* @author Middleware Services
*/
public abstract class AbstractProviderConnectionFactory<T extends ProviderConfig>
implements ProviderConnectionFactory<T>
{
/** Logger for this class. */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** Provider configuration. */
private final T providerConfig;
/** Factory metadata. */
private final DefaultConnectionFactoryMetadata metadata;
/** Connection strategy. */
private final ConnectionStrategy connectionStrategy;
/**
* Creates a new abstract connection factory. Once invoked the supplied provider config is made immutable. See {@link
* ProviderConfig#makeImmutable()}.
*
* @param url of the ldap to connect to
* @param strategy connection strategy
* @param config provider configuration
*/
public AbstractProviderConnectionFactory(final String url, final ConnectionStrategy strategy, final T config)
{
metadata = new DefaultConnectionFactoryMetadata(url);
connectionStrategy = strategy;
providerConfig = config;
providerConfig.makeImmutable();
}
@Override
public T getProviderConfig()
{
return providerConfig;
}
/**
* Returns the connection factory metadata.
*
* @return metadata
*/
protected ConnectionFactoryMetadata getMetadata()
{
return metadata;
}
@Override
public ProviderConnection create()
throws LdapException
{
LdapException lastThrown = null;
final String[] urls = connectionStrategy.getLdapUrls(metadata);
if (urls == null || urls.length == 0) {
throw new ConnectionException(
"Connection strategy " + connectionStrategy + " did not produce any LDAP URLs for " + metadata);
}
ProviderConnection conn = null;
for (String url : urls) {
try {
logger.trace("[{}] Attempting connection to {} for strategy {}", metadata, url, connectionStrategy);
conn = createInternal(url);
metadata.incrementCount();
lastThrown = null;
break;
} catch (ConnectionException e) {
lastThrown = e;
logger.debug("Error connecting to LDAP URL: {}", url, e);
}
}
if (lastThrown != null) {
throw lastThrown;
}
return conn;
}
/**
* Create the provider connection and prepare the connection for use.
*
* @param url to connect to
*
* @return provider connection
*
* @throws LdapException if a connection cannot be established
*/
protected abstract ProviderConnection createInternal(final String url)
throws LdapException;
@Override
public String toString()
{
return
String.format(
"[%s@%d::metadata=%s, providerConfig=%s]",
getClass().getName(),
hashCode(),
metadata,
providerConfig);
}
/** Provides an object to track the connection count. */
private class DefaultConnectionFactoryMetadata implements ConnectionFactoryMetadata
{
/** ldap url. */
private final String ldapUrl;
/** connection count. */
private int count;
/**
* Creates a new default connection factory metadata.
*
* @param s ldap url
*/
DefaultConnectionFactoryMetadata(final String s)
{
ldapUrl = s;
}
@Override
public String getLdapUrl()
{
return ldapUrl;
}
@Override
public int getConnectionCount()
{
return count;
}
/** Increments the connection count. */
private void incrementCount()
{
count++;
// reset the count if it exceeds the size of an integer
if (count < 0) {
count = 0;
}
}
@Override
public String toString()
{
return String.format("[ldapUrl=%s, count=%s]", ldapUrl, count);
}
}
}