/* See LICENSE for licensing and NOTICE for copyright. */ package org.ldaptive.provider.jndi; import java.util.Collections; import java.util.Hashtable; import java.util.Map; import javax.naming.NamingException; import javax.naming.ldap.InitialLdapContext; import org.ldaptive.ConnectionStrategy; import org.ldaptive.LdapException; import org.ldaptive.provider.AbstractProviderConnectionFactory; import org.ldaptive.provider.ConnectionException; import org.ldaptive.ssl.SslConfig; import org.ldaptive.ssl.ThreadLocalTLSSocketFactory; /** * Creates connections using the JNDI {@link InitialLdapContext} class. * * @author Middleware Services */ public class JndiConnectionFactory extends AbstractProviderConnectionFactory<JndiProviderConfig> { /** Environment properties. */ private final Map<String, Object> environment; /** Context class loader to use when instantiating {@link InitialLdapContext}. */ private final ClassLoader classLoader; /** Thread local SslConfig, if one exists. */ private SslConfig threadLocalSslConfig; /** * Creates a new jndi connection factory. * * @param url of the ldap to connect to * @param strategy connection strategy * @param config provider configuration * @param env jndi context environment * @param cl class loader */ public JndiConnectionFactory( final String url, final ConnectionStrategy strategy, final JndiProviderConfig config, final Map<String, Object> env, final ClassLoader cl) { super(url, strategy, config); environment = Collections.unmodifiableMap(env); classLoader = cl; if (ThreadLocalTLSSocketFactory.class.getName().equals(environment.get(JndiProvider.SOCKET_FACTORY))) { threadLocalSslConfig = new ThreadLocalTLSSocketFactory().getSslConfig(); } } @Override protected JndiConnection createInternal(final String url) throws LdapException { if ( threadLocalSslConfig != null && ThreadLocalTLSSocketFactory.class.getName().equals(environment.get(JndiProvider.SOCKET_FACTORY))) { final ThreadLocalTLSSocketFactory sf = new ThreadLocalTLSSocketFactory(); sf.setSslConfig(threadLocalSslConfig); } // CheckStyle:IllegalType OFF // the JNDI API requires the Hashtable type final Hashtable<String, Object> env = new Hashtable<>(environment); // CheckStyle:IllegalType ON env.put(JndiProvider.PROVIDER_URL, url); JndiConnection conn; try { if (classLoader != null) { final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(classLoader); conn = new JndiConnection(new InitialLdapContext(env, null), getProviderConfig()); } finally { Thread.currentThread().setContextClassLoader(currentClassLoader); } } else { conn = new JndiConnection(new InitialLdapContext(env, null), getProviderConfig()); } } catch (NamingException e) { throw new ConnectionException(e, NamingExceptionUtils.getResultCode(e.getClass())); } return conn; } @Override public String toString() { return String.format( "[%s@%d::metadata=%s, environment=%s, classLoader=%s, providerConfig=%s]", getClass().getName(), hashCode(), getMetadata(), environment, classLoader, getProviderConfig()); } }