<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
       default-init-method="initialize"
       default-destroy-method="destroy"
       default-lazy-init="true">

    <alias name="%{idp.authn.LDAP.authenticator:anonSearchAuthenticator}" alias="shibboleth.authn.LDAP.authenticator" />
    <bean id="shibboleth.authn.LDAP.returnAttributes" parent="shibboleth.CommaDelimStringArray">
        <constructor-arg type="java.lang.String" value="%{idp.authn.LDAP.returnAttributes:1.1}" />
    </bean>

    <alias name="ValidateUsernamePasswordAgainstLDAP" alias="ValidateUsernamePassword" />

    <!-- Connection Configuration -->
    <bean id="connectionConfig" class="org.ldaptive.ConnectionConfig" abstract="true" p:ldapUrl="%{idp.authn.LDAP.ldapURL}"
        p:useStartTLS="%{idp.authn.LDAP.useStartTLS:true}"
        p:useSSL="%{idp.authn.LDAP.useSSL:false}"
        p:connectTimeout="%{idp.authn.LDAP.connectTimeout:3000}"
        p:sslConfig-ref="sslConfig" />

    <alias name="%{idp.authn.LDAP.sslConfig:certificateTrust}" alias="sslConfig" />

    <bean id="jvmTrust" class="org.ldaptive.ssl.SslConfig" />
    <bean id="certificateTrust" class="org.ldaptive.ssl.SslConfig">
        <property name="credentialConfig">
            <bean parent="shibboleth.X509ResourceCredentialConfig" p:trustCertificates="%{idp.authn.LDAP.trustCertificates:undefined}" />
        </property>
    </bean>
    <bean id="keyStoreTrust" class="org.ldaptive.ssl.SslConfig">
        <property name="credentialConfig">
            <bean parent="shibboleth.KeystoreResourceCredentialConfig" p:truststore="%{idp.authn.LDAP.trustStore:undefined}" />
        </property>
    </bean>

    <!-- Authentication handler -->
    <bean id="authHandler" class="org.ldaptive.auth.PooledBindAuthenticationHandler" p:connectionFactory-ref="bindPooledConnectionFactory"  />
    <bean id="bindPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory" p:connectionPool-ref="bindConnectionPool" />
    <bean id="bindConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
        p:connectionFactory-ref="bindConnectionFactory" p:name="bind-pool" />
    <bean id="bindConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="bindConnectionConfig" />
    <bean id="bindConnectionConfig" parent="connectionConfig" />

     <!--<bean id="authenticationControl"
        class="org.ldaptive.control.PasswordPolicyControl" /> -->
    <!-- Format DN resolution -->
    <bean id="formatDnResolver" class="org.ldaptive.auth.FormatDnResolver" p:format="%{idp.authn.LDAP.dnFormat:undefined}" />

    <!-- Pool Configuration -->
    <bean id="connectionPool" class="org.ldaptive.pool.BlockingConnectionPool" abstract="true"
        p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:3000}"
p:poolConfig-ref="poolConfig"
        p:pruneStrategy-ref="pruneStrategy"
        p:validator-ref="searchValidator"
        p:failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}" />
    <bean id="poolConfig" class="org.ldaptive.pool.PoolConfig"
        p:minPoolSize="%{idp.pool.LDAP.minSize:3}"
        p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
        p:validateOnCheckOut="%{idp.pool.LDAP.validateOnCheckout:false}"
        p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
        p:validatePeriod="%{idp.pool.LDAP.validatePeriod:300}" />
    <bean id="pruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
        p:prunePeriod="%{idp.pool.LDAP.prunePeriod:300}"
        p:idleTime="%{idp.pool.LDAP.idleTime:600}" />
    <bean id="searchValidator" class="org.ldaptive.pool.SearchValidator" />

    <!-- Anonymous Search Configuration -->
    <bean name="anonSearchAuthenticator" class="org.ldaptive.auth.Authenticator" p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
        <constructor-arg index="0" ref="anonSearchDnResolver" />
        <constructor-arg index="1" ref="authHandler" />
    </bean>
    <bean id="anonSearchDnResolver" class="org.ldaptive.auth.PooledSearchDnResolver"
        p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
        p:userFilter="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}"
        p:connectionFactory-ref="anonSearchPooledConnectionFactory" />
    <bean id="anonSearchPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory"
        p:connectionPool-ref="anonSearchConnectionPool" />
    <bean id="anonSearchConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
        p:connectionFactory-ref="anonSearchConnectionFactory" p:name="search-pool" />
    <bean id="anonSearchConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="anonSearchConnectionConfig" />
    <bean id="anonSearchConnectionConfig" parent="connectionConfig" />

	<bean name="bindSearchAuthenticator"
		class="org.ldaptive.auth.Authenticator" 
		p:authenticationResponseHandlers-ref="eDirAuthenticationResponseHandler"
		p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}"
		p:entryResolver-ref="searchEntryResolver">
        <constructor-arg index="0" ref="bindSearchDnResolver" />
        <constructor-arg index="1" ref="authHandler" />
    </bean>

    <bean id="bindSearchDnResolver"
        class="org.ldaptive.auth.PooledSearchDnResolver"
        p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
        p:userFilter="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}"
        p:connectionFactory-ref="bindSearchPooledConnectionFactory" />
    <bean id="bindSearchPooledConnectionFactory"
        class="org.ldaptive.pool.PooledConnectionFactory"
        p:connectionPool-ref="bindSearchConnectionPool" />
    <bean id="bindSearchConnectionPool"
        class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
        p:connectionFactory-ref="bindSearchConnectionFactory"
        p:name="search-pool" />
    <bean id="bindSearchConnectionFactory"
        class="org.ldaptive.DefaultConnectionFactory"
        p:connectionConfig-ref="bindSearchConnectionConfig" />
    <bean id="bindSearchConnectionConfig" parent="connectionConfig"
        p:connectionInitializer-ref="bindConnectionInitializer" />
    <bean id="bindConnectionInitializer"
        class="org.ldaptive.BindConnectionInitializer"
            p:bindDn="#{'%{idp.authn.LDAP.bindDN:undefined}'.trim()}">
        <property name="bindCredential">
            <bean class="org.ldaptive.Credential">
                <constructor-arg
                value="%{idp.authn.LDAP.bindDNCredential:undefined}" />
            </bean>
        </property>
    </bean>

        <bean id="searchEntryResolver"
        class="org.ldaptive.auth.SearchEntryResolver"
        p:connectionFactory-ref="bindSearchPooledConnectionFactory" />

        <bean id="eDirAuthenticationResponseHandler"
        class="org.ldaptive.auth.ext.EDirectoryAuthenticationResponseHandler" >
                <constructor-arg index="0" value="120" type="int" />
        </bean>

    <!-- Direct Search Configuration -->
    <bean name="directAuthenticator" class="org.ldaptive.auth.Authenticator" p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
        <constructor-arg index="0" ref="formatDnResolver" />
        <constructor-arg index="1" ref="authHandler" />
    </bean>
    
        <bean id="adAuthenticator" class="org.ldaptive.auth.Authenticator" p:authenticationResponseHandlers-ref="authenticationResponseHandler"
        p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
        <constructor-arg index="0" ref="formatDnResolver" />
        <constructor-arg index="1" ref="authHandler" />
    </bean>
    <!--<bean id="authenticationResponseHandler" class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler" /> -->
    <!--  <bean id="authenticationResponseHandler" class="org.ldaptive.auth.ext.PasswordPolicyAuthenticationResponseHandler" /> -->

</beans>