class LdapRealm extends DefaultLdapRealm implements RealmLifecycle, ShiroAuthorizationInfoProvider {

    @Override
    protected AuthenticationInfo queryForAuthenticationInfo( AuthenticationToken token,
            LdapContextFactory ldapContextFactory )
            throws NamingException
    {
        if ( authenticationEnabled )
        {
            if ( useSAMAccountName )
            {
                return queryForAuthenticationInfoSAM( token, ldapContextFactory );
            }
            else
            {
                String serverString = server( (JndiLdapContextFactory) ldapContextFactory );
                try
                {
                    AuthenticationInfo info =
                            useStartTls ? queryForAuthenticationInfoUsingStartTls( token, ldapContextFactory )
                                        : super.queryForAuthenticationInfo( token, ldapContextFactory );
                    securityLog.debug( withRealm( "Authenticated user '%s' against %s", token.getPrincipal(),
                            serverString ) );
                    return info;
                }
                catch ( Exception e )
                {
                    if ( isExceptionAnLdapConnectionTimeout( e ) )
                    {
                        throw new AuthProviderTimeoutException( LDAP_CONNECTION_TIMEOUT_CLIENT_MESSAGE, e );
                    }
                    else if ( isExceptionAnLdapReadTimeout( e ) )
                    {
                        throw new AuthProviderTimeoutException( LDAP_READ_TIMEOUT_CLIENT_MESSAGE, e );
                    }
                    else if ( isExceptionConnectionRefused( e ) )
                    {
                        throw new AuthProviderFailedException( LDAP_CONNECTION_REFUSED_CLIENT_MESSAGE, e );
                    }
                    // This exception will be caught and rethrown by Shiro, and then by us, so we do not need to wrap it here
                    throw e;
                }
            }
        }
        else
        {
            return null;
        }
    }

    public  LdapRealm( Config config, SecurityLog securityLog, SecureHasher secureHasher );

}