public LdapContext getContext(LdapName baseDN) throws NamingException {
        Log.debug("Creating a DirContext in LdapManager.getContext() for baseDN '{}'...", baseDN);
        if (!sslEnabled && !startTlsEnabled && lastUnencryptedWarning.isBefore(Instant.now().minus(UNENCRYPTED_WARNING_SUPPRESSION.getValue()))) {
            Log.warn("Using unencrypted connection to LDAP service! Consider reconfiguring the connection between Openfire and your AD/LDAP server. This warning will be suppressed for {}", UNENCRYPTED_WARNING_SUPPRESSION.getValue());
            lastUnencryptedWarning = Instant.now();
        }

        // Set up the environment for creating the initial context
        Hashtable<String, Object> env = new Hashtable<>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
        env.put(Context.PROVIDER_URL, getProviderURL(baseDN));

        // SSL
        if (sslEnabled) {
            env.put("java.naming.ldap.factory.socket", "org.jivesoftware.util.SimpleSSLSocketFactory");
            env.put(Context.SECURITY_PROTOCOL, "ssl");
        }

        // Use simple authentication to connect as the admin.
        if (adminDN != null) {
            /* If startTLS is requested we MUST NOT bind() before
             * the secure connection has been established. */
            if (!(startTlsEnabled && !sslEnabled)) {
                env.put(Context.SECURITY_AUTHENTICATION, "simple");
                env.put(Context.SECURITY_PRINCIPAL, adminDN);
                if (adminPassword != null) {
                    env.put(Context.SECURITY_CREDENTIALS, adminPassword);
                }
            }
        }
        // No login information so attempt to use anonymous login.
        else {
            env.put(Context.SECURITY_AUTHENTICATION, "none");
        }

        if (ldapDebugEnabled) {
            env.put("com.sun.jndi.ldap.trace.ber", System.err);
        }
        if (connectionPoolEnabled) {
            if (!startTlsEnabled) {
                env.put("com.sun.jndi.ldap.connect.pool", "true");
                System.setProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain ssl");
            } else {
                // See http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html "When Not to Use Pooling"
                Log.debug("connection pooling was requested but has been disabled because of StartTLS.");
                env.put("com.sun.jndi.ldap.connect.pool", "false");
            }
        } else {
            env.put("com.sun.jndi.ldap.connect.pool", "false");
        }
        if (connTimeout > 0) {
            env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(connTimeout));
        } else {
            env.put("com.sun.jndi.ldap.connect.timeout", "4000");
        }

        if (readTimeout > 0) {
            env.put("com.sun.jndi.ldap.read.timeout", String.valueOf(readTimeout));
        }
        if (followReferrals) {
            env.put(Context.REFERRAL, "follow");
        }
        if (!followAliasReferrals) {
            env.put("java.naming.ldap.derefAliases", "never");
        }

        Log.debug("Created hashtable with context values, attempting to create context...");

        // Create new initial context
        JiveInitialLdapContext context = new JiveInitialLdapContext(env, null);

        // TLS http://www.ietf.org/rfc/rfc2830.txt ("1.3.6.1.4.1.1466.20037")
        if (startTlsEnabled && !sslEnabled) {
            Log.debug("... StartTlsRequest");
            if (followReferrals) {
                Log.warn("\tConnections to referrals are unencrypted! If you do not want this, please turn off ldap.autoFollowReferrals");
            }

            // Perform a StartTLS extended operation
            StartTlsResponse tls = (StartTlsResponse)
                context.extendedOperation(new StartTlsRequest());


            /* Open a TLS connection (over the existing LDAP association) and
               get details of the negotiated TLS session: cipher suite,
               peer certificate, etc. */
            try {
                SSLSession session = tls.negotiate(new org.jivesoftware.util.SimpleSSLSocketFactory());

                context.setTlsResponse(tls);
                context.setSslSession(session);

                Log.debug("... peer host: {}, CipherSuite: {}", session.getPeerHost(), session.getCipherSuite());

                /* Set login credentials only if SSL session has been
                 * negotiated successfully - otherwise user/password
                 * could be transmitted in clear text. */
                if (adminDN != null) {
                    context.addToEnvironment(
                            Context.SECURITY_AUTHENTICATION,
                            "simple");
                    context.addToEnvironment(
                            Context.SECURITY_PRINCIPAL,
                            adminDN);
                    if (adminPassword != null) {
                        context.addToEnvironment(
                                Context.SECURITY_CREDENTIALS,
                                adminPassword);
                    }
                }
            } catch (java.io.IOException ex) {
                Log.error("An exception occurred while trying to create a context for baseDN {}", baseDN, ex);
            }
        }

        Log.debug("... context created successfully, returning.");

        return context;
    }
Returns a DirContext for the LDAP server that can be used to perform
lookups and searches using the specified base DN. The context uses the
admin login that is defined by {@code adminDN} and {@code adminPassword}.

@param baseDN the base DN to use for the context.
@return a connection to the LDAP server.
@throws NamingException if there is an error making the LDAP connection.
xmppserver/src/main/java/org/jivesoftware/openfire/ldap/LdapManager.java