[java-identity-provider] branch master updated: Ldaptive v1.3 API changes.

Daniel Fisher dfisher at vt.edu
Wed Dec 4 16:05:22 EST 2019


This is an automated email from the git hooks/post-receive script.

dfisher pushed a commit to branch master
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=7503489fcfa746f63f311793c4a90f4dd8a1c7f8

The following commit(s) were added to refs/heads/master by this push:
       new  7503489   Ldaptive v1.3 API changes.
7503489 is described below

commit 7503489fcfa746f63f311793c4a90f4dd8a1c7f8
Author: Daniel Fisher <dfisher at vt.edu>
AuthorDate: Wed Dec 4 15:54:12 2019 -0500

    Ldaptive v1.3 API changes.
    
    Removes DEFAULT connection strategy.
    Removes blockWhenEmpty pool config.
    Removes support for JNDI properties.
    Fixes IDP-1440, IDP-1401, IDP-1357, IDP-1095.
---
 .../AbstractExecutableSearchFilterBuilder.java     |   6 +
 idp-attribute-resolver-spring/pom.xml              |   5 -
 .../dc/ldap/impl/LDAPDataConnectorParser.java      | 168 ++------
 .../spring/impl/StringToDurationConverter.java     |  33 ++
 .../dc/ldap/LDAPDataConnectorParserTest.java       | 177 ++------
 .../ldap-attribute-resolver-spring-context.xml     |  24 +-
 ...dap-attribute-resolver-spring-props-context.xml |  14 -
 .../resolver/spring/dc/ldap/ldap-v2.properties     |   3 -
 .../resolver/spring/dc/ldap/ldap-v3.properties     |  17 +-
 .../resolver/ldap-attribute-resolver-v2-hybrid.xml |   2 -
 .../resolver/ldap-attribute-resolver-v2-jndi.xml   |  34 --
 .../resolver/ldap-attribute-resolver-v2-multi.xml  |   5 -
 .../resolver/ldap-attribute-resolver-v2-nosec.xml  |   4 -
 .../resolver/ldap-attribute-resolver-v2-props.xml  |   2 -
 .../ldap/resolver/ldap-attribute-resolver-v2.xml   |   4 -
 .../idp/authn/PooledTemplateSearchDnResolver.java  |   4 +-
 .../idp/authn/TemplateSearchDnResolver.java        |   4 +-
 .../config/LDAPAuthenticationFactoryBean.java      | 474 +++++++++++++++++++++
 .../authn/impl/LDAPCredentialValidatorTest.java    |   3 +-
 idp-conf/pom.xml                                   |   5 -
 .../resources/conf/authn/ldap-authn-config.xml     | 149 ++-----
 .../main/resources/system/conf/global-system.xml   |   1 -
 .../net/shibboleth/idp/test/InMemoryDirectory.java |  15 +-
 idp-distribution/pom.xml                           |  10 -
 .../schema/shibboleth-attribute-resolver.xsd       |  20 +-
 idp-war-distribution/pom.xml                       |  11 -
 26 files changed, 656 insertions(+), 538 deletions(-)

diff --git a/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/ldap/impl/AbstractExecutableSearchFilterBuilder.java b/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/ldap/impl/AbstractExecutableSearchFilterBuilder.java
index dffa7e0..cde77f2 100644
--- a/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/ldap/impl/AbstractExecutableSearchFilterBuilder.java
+++ b/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/ldap/impl/AbstractExecutableSearchFilterBuilder.java
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
 import org.ldaptive.ConnectionFactory;
 import org.ldaptive.LdapException;
 import org.ldaptive.Response;
+import org.ldaptive.ResultCode;
 import org.ldaptive.SearchExecutor;
 import org.ldaptive.SearchFilter;
 import org.ldaptive.SearchResult;
@@ -61,6 +62,11 @@ public abstract class AbstractExecutableSearchFilterBuilder extends AbstractInit
                     @Nonnull final ConnectionFactory factory) throws LdapException {
                 final Response<SearchResult> response = executor.search(factory, searchFilter);
                 log.trace("Search returned response {}", response);
+                if (response.getResultCode() != ResultCode.SUCCESS) {
+                    // It's possible for the LDAP to return partial results and report either a size limit or
+                    // time limit result code. Throw if we don't receive all results.
+                    throw new LdapException("Search operation did not return success: " + response.getResultCode());
+                }
                 return response.getResult();
             }
 
diff --git a/idp-attribute-resolver-spring/pom.xml b/idp-attribute-resolver-spring/pom.xml
index 0ff653d..8632475 100644
--- a/idp-attribute-resolver-spring/pom.xml
+++ b/idp-attribute-resolver-spring/pom.xml
@@ -181,11 +181,6 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.ldaptive</groupId>
-            <artifactId>ldaptive-unboundid</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>com.unboundid</groupId>
             <artifactId>unboundid-ldapsdk</artifactId>
             <scope>test</scope>
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java
index 1d49f05..b278a80 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/impl/LDAPDataConnectorParser.java
@@ -25,10 +25,13 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.xml.namespace.QName;
 
+import org.ldaptive.ActivePassiveConnectionStrategy;
 import org.ldaptive.BindConnectionInitializer;
 import org.ldaptive.ConnectionConfig;
 import org.ldaptive.Credential;
 import org.ldaptive.DefaultConnectionFactory;
+import org.ldaptive.RandomConnectionStrategy;
+import org.ldaptive.RoundRobinConnectionStrategy;
 import org.ldaptive.SearchExecutor;
 import org.ldaptive.SearchFilter;
 import org.ldaptive.SearchRequest;
@@ -42,8 +45,6 @@ import org.ldaptive.pool.IdlePruneStrategy;
 import org.ldaptive.pool.PoolConfig;
 import org.ldaptive.pool.PooledConnectionFactory;
 import org.ldaptive.pool.SearchValidator;
-import org.ldaptive.pool.SoftLimitConnectionPool;
-import org.ldaptive.provider.ConnectionStrategy;
 import org.ldaptive.sasl.Mechanism;
 import org.ldaptive.sasl.SaslConfig;
 import org.ldaptive.ssl.SslConfig;
@@ -95,7 +96,7 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
      * Parses a version 2 configuration. <br/>
      * The following automatically created & injected beans acquire hard wired defaults:
      * <ul>
-     * <li>{@link SearchExecutor#setTimeLimit(long)} defaults to 3000, overridden by the "searchTimeLimit" attribute.
+     * <li>{@link SearchExecutor#setTimeLimit(Duration)} defaults to 3s, overridden by the "searchTimeLimit" attribute.
      * </li>
      * <li>{@link SearchExecutor#setSizeLimit(long)} defaults to 1, overridden by the "maxResultSize" attribute.</li>
      * <li>{@link SearchRequest#setBaseDn(String)} default to "", overridden by the "validateDN" attribute.</li>
@@ -105,7 +106,7 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
      * attribute "minPoolSize" are set.</li>
      * <li>{@link PoolConfig#setMaxPoolSize(int)} defaults to 3 if neither the attribute "poolMaxIdleSize" nor the
      * attribute "maxPoolSize" are set.</li>
-     * <li>{@link PoolConfig#setValidatePeriod(long)} defaults to 1800, overridden by the attribute
+     * <li>{@link PoolConfig#setValidatePeriod(Duration)} defaults to 30m, overridden by the attribute
      * "validateTimerPeriod"</li>
      * </ul>
      * 
@@ -123,46 +124,6 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
                 BeanDefinitionBuilder.genericBeanDefinition(DefaultConnectionFactory.class);
         connectionFactory.addConstructorArgValue(v2Parser.createConnectionConfig(parserContext));
 
-        final BeanDefinitionBuilder provider =
-                BeanDefinitionBuilder.genericBeanDefinition(DefaultConnectionFactory.getDefaultProvider().getClass());
-        final BeanDefinitionBuilder providerConfig =
-                BeanDefinitionBuilder.genericBeanDefinition(DefaultConnectionFactory.getDefaultProvider()
-                        .getProviderConfig().getClass());
-        final String connectionStrategy = AttributeSupport.getAttributeValue(config, new QName("connectionStrategy"));
-        if (connectionStrategy == null) {
-            providerConfig.addPropertyValue("connectionStrategy", ConnectionStrategy.ACTIVE_PASSIVE);
-        } else {
-            switch (connectionStrategy) {
-                case "DEFAULT":
-                    providerConfig.addPropertyValue("connectionStrategy", ConnectionStrategy.DEFAULT);
-                    break;
-
-                case "ROUND_ROBIN":
-                    providerConfig.addPropertyValue("connectionStrategy", ConnectionStrategy.ROUND_ROBIN);
-                    break;
-
-                case "RANDOM":
-                    providerConfig.addPropertyValue("connectionStrategy", ConnectionStrategy.RANDOM);
-                    break;
-
-                default:
-                    providerConfig.addPropertyValue("connectionStrategy", ConnectionStrategy.ACTIVE_PASSIVE);
-                    break;
-            }
-        }
-
-        final ManagedMap<String, String> props = new ManagedMap<>();
-        final List<Element> propertyElements =
-                ElementSupport.getChildElements(config,
-                        new QName(AttributeResolverNamespaceHandler.NAMESPACE, "LDAPProperty"));
-        for (final Element e : propertyElements) {
-            props.put(AttributeSupport.getAttributeValue(e, new QName("name")),
-                    AttributeSupport.getAttributeValue(e, new QName("value")));
-        }
-        providerConfig.addPropertyValue("properties", props);
-        provider.addPropertyValue("providerConfig", providerConfig.getBeanDefinition());
-        connectionFactory.addPropertyValue("provider", provider.getBeanDefinition());
-
         final String searchBuilderID = v2Parser.getBeanSearchBuilderID();
         if (searchBuilderID != null) {
             builder.addPropertyReference("executableSearchBuilder", searchBuilderID);
@@ -183,7 +144,7 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
             builder.addPropertyValue("connectionFactory", connectionFactory.getBeanDefinition());
         }
 
-        final BeanDefinition searchExecutor = v2Parser.createSearchExecutor(props);
+        final BeanDefinition searchExecutor = v2Parser.createSearchExecutor();
         builder.addPropertyValue("searchExecutor", searchExecutor);
 
         final String mappingStrategyID = AttributeSupport.getAttributeValue(config, new QName("mappingStrategyRef"));
@@ -278,22 +239,14 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
                 connectionConfig.addPropertyValue("useStartTLS", useStartTLS);
             }
             if (connectTimeout != null) {
-                final BeanDefinitionBuilder timeout =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                timeout.addConstructorArgValue(connectTimeout);
-                timeout.addConstructorArgValue(1);
-                connectionConfig.addPropertyValue("connectTimeout", timeout.getBeanDefinition());
+                connectionConfig.addPropertyValue("connectTimeout", connectTimeout);
             } else {
-                connectionConfig.addPropertyValue("connectTimeout", 3000);
+                connectionConfig.addPropertyValue("connectTimeout", Duration.ofSeconds(3));
             }
             if (responseTimeout != null) {
-                final BeanDefinitionBuilder timeout =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                timeout.addConstructorArgValue(responseTimeout);
-                timeout.addConstructorArgValue(1);
-                connectionConfig.addPropertyValue("responseTimeout", timeout.getBeanDefinition());
+                connectionConfig.addPropertyValue("responseTimeout", responseTimeout);
             } else {
-                connectionConfig.addPropertyValue("responseTimeout", 3000);
+                connectionConfig.addPropertyValue("responseTimeout", Duration.ofSeconds(3));
             }
             final BeanDefinitionBuilder sslConfig = BeanDefinitionBuilder.genericBeanDefinition(SslConfig.class);
             sslConfig.addPropertyValue("credentialConfig", createCredentialConfig(parserContext));
@@ -319,6 +272,26 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
             if (principal != null || principalCredential != null || authenticationType != null) {
                 connectionConfig.addPropertyValue("connectionInitializer", connectionInitializer.getBeanDefinition());
             }
+            final String connectionStrategy = AttributeSupport.getAttributeValue(
+                configElement, new QName("connectionStrategy"));
+            if (connectionStrategy == null) {
+                connectionConfig.addPropertyValue("connectionStrategy", new ActivePassiveConnectionStrategy());
+            } else {
+                switch (connectionStrategy) {
+                case "ROUND_ROBIN":
+                    connectionConfig.addPropertyValue("connectionStrategy", new RoundRobinConnectionStrategy());
+                    break;
+
+                case "RANDOM":
+                    connectionConfig.addPropertyValue("connectionStrategy", new RandomConnectionStrategy());
+                    break;
+
+                default:
+                    connectionConfig.addPropertyValue("connectionStrategy", new ActivePassiveConnectionStrategy());
+                    break;
+                }
+            }
+
             return connectionConfig.getBeanDefinition();
         }
         // CheckStyle: CyclomaticComplexity ON
@@ -453,12 +426,10 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
         /**
          * Creates a new search executor bean definition from a v2 XML configuration.
          *
-         * @param props ldap properties
-         *
          * @return search executor bean definition
          */
         // CheckStyle: CyclomaticComplexity|MethodLength OFF
-        @Nonnull public BeanDefinition createSearchExecutor(final ManagedMap<String, String> props) {
+        @Nonnull public BeanDefinition createSearchExecutor() {
             final String baseDn = AttributeSupport.getAttributeValue(configElement, new QName("baseDN"));
             final String searchScope = AttributeSupport.getAttributeValue(configElement, new QName("searchScope"));
             final String derefAliases = AttributeSupport.getAttributeValue(configElement, new QName("derefAliases"));
@@ -478,18 +449,11 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
             }
             if (derefAliases != null) {
                 searchExecutor.addPropertyValue("derefAliases", derefAliases);
-            } else if (props.containsKey("java.naming.ldap.derefAliases")) {
-                searchExecutor.addPropertyValue(
-                  "derefAliases", props.get("java.naming.ldap.derefAliases").toUpperCase());
             }
             if (searchTimeLimit != null) {
-                final BeanDefinitionBuilder duration =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                duration.addConstructorArgValue(searchTimeLimit);
-                duration.addConstructorArgValue(1);
-                searchExecutor.addPropertyValue("timeLimit", duration.getBeanDefinition());
+                searchExecutor.addPropertyValue("timeLimit", searchTimeLimit);
             } else {
-                searchExecutor.addPropertyValue("timeLimit", 3000);
+                searchExecutor.addPropertyValue("timeLimit", Duration.ofSeconds(3));
             }
             if (maxResultSize != null) {
                 searchExecutor.addPropertyValue("sizeLimit", maxResultSize);
@@ -532,11 +496,6 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
                   BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildStringList");
                 binaryAttrs.addConstructorArgValue(ElementSupport.getElementContentAsString(binaryAttrsElement));
                 searchExecutor.addPropertyValue("binaryAttributes", binaryAttrs.getBeanDefinition());
-            } else if (props.containsKey("java.naming.ldap.attributes.binary")) {
-                final BeanDefinitionBuilder binaryAttrs =
-                  BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildStringList");
-                binaryAttrs.addConstructorArgValue(props.get("java.naming.ldap.attributes.binary"));
-                searchExecutor.addPropertyValue("binaryAttributes", binaryAttrs.getBeanDefinition());
             }
 
             return searchExecutor.getBeanDefinition();
@@ -583,28 +542,15 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
                     AttributeSupport.getAttributeValue(poolConfigElement, new QName("expirationTime"));
 
             final BeanDefinitionBuilder pool =
-                    BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildConnectionPool");
-            pool.addConstructorArgValue(AttributeSupport.getAttributeValue(configElement, new QName("blockWhenEmpty")));
+                    BeanDefinitionBuilder.genericBeanDefinition(BlockingConnectionPool.class);
+            pool.addPropertyValue("name", "resolver-pool");
             if (blockWaitTime != null) {
-                final BeanDefinitionBuilder duration =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                duration.addConstructorArgValue(blockWaitTime);
-                duration.addConstructorArgValue(1);
-                pool.addPropertyValue("blockWaitTime", duration.getBeanDefinition());
+                pool.addPropertyValue("blockWaitTime", blockWaitTime);
             }
             if (expirationTime != null) {
-                final BeanDefinitionBuilder period =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                period.addConstructorArgValue(expirationTime);
-                period.addConstructorArgValue(2000);
-                final BeanDefinitionBuilder idle =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                idle.addConstructorArgValue(expirationTime);
-                idle.addConstructorArgValue(1000);
                 final BeanDefinitionBuilder strategy =
                         BeanDefinitionBuilder.genericBeanDefinition(IdlePruneStrategy.class);
-                strategy.addConstructorArgValue(period.getBeanDefinition());
-                strategy.addConstructorArgValue(idle.getBeanDefinition());
+                strategy.addConstructorArgValue(expirationTime);
                 pool.addPropertyValue("pruneStrategy", strategy.getBeanDefinition());
             }
             pool.addPropertyValue("poolConfig", createPoolConfig());
@@ -667,14 +613,9 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
                 poolConfig.addPropertyValue("validatePeriodically", validatePeriodically);
             }
             if (validateTimerPeriod != null) {
-                final BeanDefinitionBuilder period =
-                        BeanDefinitionBuilder.rootBeanDefinition(V2Parser.class, "buildDuration");
-                period.addConstructorArgValue(validateTimerPeriod);
-                // Convert to seconds.
-                period.addConstructorArgValue(1000);
-                poolConfig.addPropertyValue("validatePeriod", period.getBeanDefinition());
+                poolConfig.addPropertyValue("validatePeriod", validateTimerPeriod);
             } else {
-                poolConfig.addPropertyValue("validatePeriod", 1800);
+                poolConfig.addPropertyValue("validatePeriod", Duration.ofMinutes(30));
             }
             return poolConfig.getBeanDefinition();
         }
@@ -753,19 +694,6 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
         }
 
         /**
-         * Converts the supplied duration to milliseconds and divides it by the divisor. Useful for modifying durations
-         * while resolving property replacement.
-         * 
-         * @param duration the duration (which may have gone through spring translation from iso to long)
-         * @param divisor to modify the duration with
-         * 
-         * @return result of the division
-         */
-        public static long buildDuration(@Nonnull final Duration duration, final long divisor) {
-            return duration.toMillis() / divisor;
-        } 
-
-        /**
          * Converts the supplied value to a list of strings delimited by {@link XMLConstants#LIST_DELIMITERS} and comma.
          * 
          * @param value to convert to a list
@@ -777,24 +705,6 @@ public class LDAPDataConnectorParser extends AbstractDataConnectorParser {
         }
 
         /**
-         * Returns a soft limit connection pool if blockWhenEmpty is false, otherwise return a blocking connection pool.
-         * 
-         * @param blockWhenEmpty boolean string indicating the type of blocking connection pool
-         * 
-         * @return soft limit or blocking connection pool
-         */
-        @Nonnull public static BlockingConnectionPool buildConnectionPool(@Nullable final String blockWhenEmpty) {
-            BlockingConnectionPool pool = null;
-            if (blockWhenEmpty == null || Boolean.valueOf(blockWhenEmpty)) {
-                pool = new BlockingConnectionPool();
-            } else {
-                pool = new SoftLimitConnectionPool();
-            }
-            pool.setName("resolver-pool");
-            return pool;
-        }
-
-        /**
          * Returns a search validator or null if validatePeriodically is false.
          *
          * @param validatePeriodically whether to create a search validator
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/StringToDurationConverter.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/StringToDurationConverter.java
new file mode 100644
index 0000000..76701dd
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/StringToDurationConverter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.attribute.resolver.spring.impl;
+
+import java.time.Duration;
+import org.springframework.core.convert.converter.Converter;
+
+/**
+ * Spring converter that produces a {@link java.time.Duration} from it's ISO time format.
+ */
+public class StringToDurationConverter implements Converter<String, Duration> {
+
+    @Override
+    public Duration convert(final String s)
+    {
+        return Duration.parse(s);
+    }
+}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java
index 083d431..dd96c28 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/LDAPDataConnectorParserTest.java
@@ -30,22 +30,18 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.stream.Collectors;
 
 import org.ldaptive.BindConnectionInitializer;
 import org.ldaptive.ConnectionConfig;
 import org.ldaptive.DefaultConnectionFactory;
-import org.ldaptive.DerefAliases;
 import org.ldaptive.SearchExecutor;
-import org.ldaptive.SearchScope;
 import org.ldaptive.pool.BlockingConnectionPool;
 import org.ldaptive.pool.IdlePruneStrategy;
 import org.ldaptive.pool.PoolConfig;
 import org.ldaptive.pool.PooledConnectionFactory;
 import org.ldaptive.pool.SearchValidator;
-import org.ldaptive.provider.ProviderConfig;
 import org.ldaptive.ssl.CredentialConfig;
 import org.ldaptive.ssl.SslConfig;
 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
@@ -188,35 +184,31 @@ public class LDAPDataConnectorParserTest {
                 getLdapDataConnector(new String[] {"net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-minimal.xml"});
         assertNotNull(dataConnector);
         assertTrue(dataConnector.isFailFastInitialize());
-        assertEquals(Duration.ZERO, dataConnector.getNoRetryDelay());
+        assertEquals(dataConnector.getNoRetryDelay(), Duration.ZERO);
         final DefaultConnectionFactory connFactory = (DefaultConnectionFactory) dataConnector.getConnectionFactory();
         assertNotNull(connFactory);
 
         final ConnectionConfig connConfig = connFactory.getConnectionConfig();
         assertNotNull(connConfig);
-        assertEquals("ldap://localhost:10389", connConfig.getLdapUrl());
-        assertEquals(false, connConfig.getUseSSL());
-        assertEquals(false, connConfig.getUseStartTLS());
+        assertEquals(connConfig.getLdapUrl(), "ldap://localhost:10389");
+        assertFalse(connConfig.getUseSSL());
+        assertFalse(connConfig.getUseStartTLS());
         final BindConnectionInitializer connInitializer = (BindConnectionInitializer) connConfig.getConnectionInitializer();
-        assertEquals("cn=Directory Manager", connInitializer.getBindDn());
-        assertEquals("password", connInitializer.getBindCredential().getString());
-        assertEquals(3000, connConfig.getConnectTimeout());
-        assertEquals(3000, connConfig.getResponseTimeout());
+        assertEquals(connInitializer.getBindDn(), "cn=Directory Manager");
+        assertEquals(connInitializer.getBindCredential().getString(), "password");
+        assertEquals(connConfig.getConnectTimeout(), Duration.ofSeconds(3));
+        assertEquals(connConfig.getResponseTimeout(), Duration.ofSeconds(3));
 
         final SslConfig sslConfig = connFactory.getConnectionConfig().getSslConfig();
         assertNotNull(sslConfig);
         final CredentialConfig credentialConfig = sslConfig.getCredentialConfig();
         assertNotNull(credentialConfig);
 
-        final ProviderConfig<?> providerConfig = connFactory.getProvider().getProviderConfig();
-        assertNotNull(providerConfig);
-        assertTrue(providerConfig.getProperties().isEmpty());
-
         final SearchExecutor searchExecutor = dataConnector.getSearchExecutor();
         assertNotNull(searchExecutor);
-        assertEquals("", searchExecutor.getBaseDn());
+        assertEquals(searchExecutor.getBaseDn(), "");
         assertNull(searchExecutor.getSearchFilter());
-        assertEquals(3000, searchExecutor.getTimeLimit());
+        assertEquals(searchExecutor.getTimeLimit(), Duration.ofSeconds(3));
 
         final ConnectionFactoryValidator validator = (ConnectionFactoryValidator) dataConnector.getValidator();
         assertNotNull(validator);
@@ -252,47 +244,43 @@ public class LDAPDataConnectorParserTest {
         assertNotNull(connFactory);
         final BlockingConnectionPool connPool = (BlockingConnectionPool) connFactory.getConnectionPool();
         assertNotNull(connPool);
-        assertEquals(0, connPool.getBlockWaitTime());
+        assertNull(connPool.getBlockWaitTime());
         assertEquals("resolver-pool", connPool.getName());
         final PoolConfig poolConfig = connPool.getPoolConfig();
         assertNotNull(poolConfig);
-        assertEquals(0, poolConfig.getMinPoolSize());
-        assertEquals(3, poolConfig.getMaxPoolSize());
+        assertEquals(poolConfig.getMinPoolSize(), 0);
+        assertEquals(poolConfig.getMaxPoolSize(), 3);
         assertFalse(poolConfig.isValidatePeriodically());
-        assertEquals(1800, poolConfig.getValidatePeriod());
+        assertEquals(poolConfig.getValidatePeriod(), Duration.ofMinutes(30));
         assertTrue(connPool.getFailFastInitialize());
         assertNull(connPool.getValidator());
 
         final IdlePruneStrategy pruneStrategy = (IdlePruneStrategy) connPool.getPruneStrategy();
         assertNotNull(pruneStrategy);
-        assertEquals(300, pruneStrategy.getPrunePeriod());
-        assertEquals(600, pruneStrategy.getIdleTime());
+        assertEquals(pruneStrategy.getPrunePeriod(), Duration.ofMinutes(5));
+        assertEquals(pruneStrategy.getIdleTime(), Duration.ofMinutes(10));
 
         final ConnectionConfig connConfig = connPool.getConnectionFactory().getConnectionConfig();
         assertNotNull(connConfig);
-        assertEquals("ldap://localhost:10389", connConfig.getLdapUrl());
-        assertEquals(false, connConfig.getUseSSL());
-        assertEquals(false, connConfig.getUseStartTLS());
+        assertEquals(connConfig.getLdapUrl(), "ldap://localhost:10389");
+        assertFalse(connConfig.getUseSSL());
+        assertFalse(connConfig.getUseStartTLS());
         final BindConnectionInitializer connInitializer = (BindConnectionInitializer) connConfig.getConnectionInitializer();
-        assertEquals("cn=Directory Manager", connInitializer.getBindDn());
-        assertEquals("password", connInitializer.getBindCredential().getString());
-        assertEquals(3000, connConfig.getConnectTimeout());
-        assertEquals(3000, connConfig.getResponseTimeout());
+        assertEquals(connInitializer.getBindDn(), "cn=Directory Manager");
+        assertEquals(connInitializer.getBindCredential().getString(), "password");
+        assertEquals(connConfig.getConnectTimeout(), Duration.ofSeconds(3));
+        assertEquals(connConfig.getResponseTimeout(), Duration.ofSeconds(3));
 
         final SslConfig sslConfig = connPool.getConnectionFactory().getConnectionConfig().getSslConfig();
         assertNotNull(sslConfig);
         final CredentialConfig credentialConfig = sslConfig.getCredentialConfig();
         assertNotNull(credentialConfig);
 
-        final ProviderConfig<?> providerConfig = connPool.getConnectionFactory().getProvider().getProviderConfig();
-        assertNotNull(providerConfig);
-        assertTrue(providerConfig.getProperties().isEmpty());
-
         final SearchExecutor searchExecutor = dataConnector.getSearchExecutor();
         assertNotNull(searchExecutor);
-        assertEquals("", searchExecutor.getBaseDn());
+        assertEquals(searchExecutor.getBaseDn(), "");
         assertNull(searchExecutor.getSearchFilter());
-        assertEquals(3000, searchExecutor.getTimeLimit());
+        assertEquals(searchExecutor.getTimeLimit(), Duration.ofSeconds(3));
 
         final ConnectionFactoryValidator validator = (ConnectionFactoryValidator) dataConnector.getValidator();
         assertNotNull(validator);
@@ -318,74 +306,6 @@ public class LDAPDataConnectorParserTest {
         assertNotNull(attrs.get("entryDN"));
     }
 
-    @Test public void v2JndiConfig() throws Exception {
-        final LDAPDataConnector dataConnector =
-          getLdapDataConnector(new String[] {"net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml"});
-        assertNotNull(dataConnector);
-        assertEquals(Duration.ofMinutes(5), dataConnector.getNoRetryDelay());
-        final DefaultConnectionFactory connFactory = (DefaultConnectionFactory) dataConnector.getConnectionFactory();
-        assertNotNull(connFactory);
-
-        final ConnectionConfig connConfig = connFactory.getConnectionConfig();
-        assertNotNull(connConfig);
-        assertEquals("ldap://localhost:10389", connConfig.getLdapUrl());
-        assertEquals(false, connConfig.getUseSSL());
-        assertEquals(true, connConfig.getUseStartTLS());
-        final BindConnectionInitializer connInitializer = (BindConnectionInitializer) connConfig.getConnectionInitializer();
-        assertEquals("cn=Directory Manager", connInitializer.getBindDn());
-        assertEquals("password", connInitializer.getBindCredential().getString());
-        assertEquals(2000, connConfig.getConnectTimeout());
-        assertEquals(4000, connConfig.getResponseTimeout());
-
-        final SslConfig sslConfig = connFactory.getConnectionConfig().getSslConfig();
-        assertNotNull(sslConfig);
-        final CredentialConfig credentialConfig = sslConfig.getCredentialConfig();
-        assertNotNull(credentialConfig);
-
-        final ProviderConfig<?> providerConfig = connFactory.getProvider().getProviderConfig();
-        assertNotNull(providerConfig);
-        assertEquals("value1", providerConfig.getProperties().get("name1"));
-        assertEquals("finding", providerConfig.getProperties().get("java.naming.ldap.derefAliases"));
-        assertEquals("jpegPhoto employeeNumber", providerConfig.getProperties().get("java.naming.ldap.attributes.binary"));
-
-        final SearchExecutor searchExecutor = dataConnector.getSearchExecutor();
-        assertNotNull(searchExecutor);
-        assertEquals("ou=people,dc=shibboleth,dc=net", searchExecutor.getBaseDn());
-        assertNull(searchExecutor.getSearchFilter());
-        assertEquals(7000, searchExecutor.getTimeLimit());
-        assertEquals(SearchScope.SUBTREE, searchExecutor.getSearchScope());
-        assertEquals(DerefAliases.FINDING, searchExecutor.getDerefAliases());
-        assertEquals(new String[] {"jpegPhoto", "employeeNumber"}, searchExecutor.getBinaryAttributes());
-
-        final ConnectionFactoryValidator validator = (ConnectionFactoryValidator) dataConnector.getValidator();
-        assertNotNull(validator);
-        assertFalse(validator.isThrowValidateError());
-        assertNotNull(validator.getConnectionFactory());
-
-        final ExecutableSearchBuilder<?> searchBuilder = dataConnector.getExecutableSearchBuilder();
-        assertNotNull(searchBuilder);
-
-        final StringAttributeValueMappingStrategy mappingStrategy =(StringAttributeValueMappingStrategy) dataConnector.getMappingStrategy();
-        assertNotNull(mappingStrategy);
-        assertTrue(mappingStrategy.isNoResultAnError());
-        assertTrue(mappingStrategy.isMultipleResultsAnError());
-
-        assertNull(dataConnector.getResultsCache());
-
-        dataConnector.initialize();
-        final AttributeResolutionContext context =
-          TestSources.createResolutionContext(TestSources.PRINCIPAL_ID, TestSources.IDP_ENTITY_ID,
-            TestSources.SP_ENTITY_ID);
-        final Map<String, IdPAttribute> attrs = dataConnector.resolve(context);
-        assertNotNull(attrs);
-        assertEquals(5, attrs.size());
-        assertNotNull(attrs.get("cn"));
-        assertNotNull(attrs.get("sn"));
-        assertNotNull(attrs.get("jpegPhoto"));
-        assertEquals(attrs.get("employeeNumber").getValues().get(0).getNativeValue(), "C2J20hMNp7NlUwQ+");
-        assertNotNull(attrs.get("entryDN"));
-    }
-
     @Test public void v2PropsConfig() throws Exception {
         final Resource props = new ClassPathResource("net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v2.properties");
         final LDAPDataConnector dataConnector =
@@ -525,61 +445,54 @@ public class LDAPDataConnectorParserTest {
     protected void doTest(final LDAPDataConnector dataConnector) throws ResolutionException {
 
         final String id = dataConnector.getId();
-        assertEquals("myLDAP", id);
-        assertEquals(Duration.ofMinutes(5), dataConnector.getNoRetryDelay());
+        assertEquals(id, "myLDAP");
+        assertEquals(dataConnector.getNoRetryDelay(), Duration.ofMinutes(5));
 
         final PooledConnectionFactory connFactory = (PooledConnectionFactory) dataConnector.getConnectionFactory();
         assertNotNull(connFactory);
         final BlockingConnectionPool connPool = (BlockingConnectionPool) connFactory.getConnectionPool();
         assertNotNull(connPool);
-        assertEquals(5000, connPool.getBlockWaitTime());
-        assertEquals("resolver-pool", connPool.getName());
+        assertEquals(connPool.getBlockWaitTime(), Duration.ofSeconds(5));
+        assertEquals(connPool.getName(), "resolver-pool");
         final PoolConfig poolConfig = connPool.getPoolConfig();
         assertNotNull(poolConfig);
-        assertEquals(5, poolConfig.getMinPoolSize());
-        assertEquals(10, poolConfig.getMaxPoolSize());
+        assertEquals(poolConfig.getMinPoolSize(), 5);
+        assertEquals(poolConfig.getMaxPoolSize(), 10);
         assertTrue(poolConfig.isValidatePeriodically());
-        assertEquals(900, poolConfig.getValidatePeriod());
+        assertEquals(poolConfig.getValidatePeriod(), Duration.ofMinutes(15));
         assertFalse(connPool.getFailFastInitialize());
 
         final SearchValidator searchValidator = (SearchValidator) connPool.getValidator();
         assertNotNull(searchValidator);
-        assertEquals("dc=shibboleth,dc=net", searchValidator.getSearchRequest().getBaseDn());
-        assertEquals("(ou=people)", searchValidator.getSearchRequest().getSearchFilter().getFilter());
+        assertEquals(searchValidator.getSearchRequest().getBaseDn(), "dc=shibboleth,dc=net");
+        assertEquals(searchValidator.getSearchRequest().getSearchFilter().getFilter(), "(ou=people)");
 
         final IdlePruneStrategy pruneStrategy = (IdlePruneStrategy) connPool.getPruneStrategy();
         assertNotNull(pruneStrategy);
-        assertEquals(300, pruneStrategy.getPrunePeriod());
-        assertEquals(600, pruneStrategy.getIdleTime());
+        assertEquals(pruneStrategy.getPrunePeriod(), Duration.ofMinutes(5));
+        assertEquals(pruneStrategy.getIdleTime(), Duration.ofMinutes(10));
 
         final ConnectionConfig connConfig = connPool.getConnectionFactory().getConnectionConfig();
         assertNotNull(connConfig);
-        assertEquals("ldap://localhost:10389", connConfig.getLdapUrl());
-        assertEquals(false, connConfig.getUseSSL());
-        assertEquals(true, connConfig.getUseStartTLS());
+        assertEquals(connConfig.getLdapUrl(), "ldap://localhost:10389");
+        assertFalse(connConfig.getUseSSL());
+        assertTrue(connConfig.getUseStartTLS());
         final BindConnectionInitializer connInitializer = (BindConnectionInitializer) connConfig.getConnectionInitializer();
-        assertEquals("cn=Directory Manager", connInitializer.getBindDn());
-        assertEquals("password", connInitializer.getBindCredential().getString());
-        assertEquals(2000, connConfig.getConnectTimeout());
-        assertEquals(4000, connConfig.getResponseTimeout());
+        assertEquals(connInitializer.getBindDn(), "cn=Directory Manager");
+        assertEquals(connInitializer.getBindCredential().getString(), "password");
+        assertEquals(connConfig.getConnectTimeout(), Duration.ofSeconds(2));
+        assertEquals(connConfig.getResponseTimeout(), Duration.ofSeconds(4));
 
         final SslConfig sslConfig = connPool.getConnectionFactory().getConnectionConfig().getSslConfig();
         assertNotNull(sslConfig);
         final CredentialConfig credentialConfig = sslConfig.getCredentialConfig();
         assertNotNull(credentialConfig);
 
-        final Map<String, Object> providerProps = new HashMap<>();
-        providerProps.put("name1", "value1");
-        providerProps.put("name2", "value2");
-        final ProviderConfig<?> providerConfig = connPool.getConnectionFactory().getProvider().getProviderConfig();
-        assertNotNull(providerConfig);
-        assertEquals(providerProps, providerConfig.getProperties());
-
         final SearchExecutor searchExecutor = dataConnector.getSearchExecutor();
         assertNotNull(searchExecutor);
-        assertEquals("ou=people,dc=shibboleth,dc=net", searchExecutor.getBaseDn());
+        assertEquals(searchExecutor.getBaseDn(), "ou=people,dc=shibboleth,dc=net");
         assertNull(searchExecutor.getSearchFilter());
-        assertEquals(7000, searchExecutor.getTimeLimit());
+        assertEquals(searchExecutor.getTimeLimit(), Duration.ofSeconds(7));
 
         final ConnectionFactoryValidator validator = (ConnectionFactoryValidator) dataConnector.getValidator();
         assertNotNull(validator);
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-context.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-context.xml
index e58fa3d..8086ca8 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-context.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-context.xml
@@ -4,30 +4,16 @@
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
     <bean id="connectionFactory" class="org.ldaptive.pool.PooledConnectionFactory">
         <property name="connectionPool">
-            <bean class="org.ldaptive.pool.BlockingConnectionPool" init-method="initialize" p:blockWaitTime="5000" p:failFastInitialize="false" p:name="resolver-pool">
+            <bean class="org.ldaptive.pool.BlockingConnectionPool" init-method="initialize" p:blockWaitTime="PT5S" p:failFastInitialize="false" p:name="resolver-pool">
                 <constructor-arg index="0">
                     <bean class="org.ldaptive.pool.PoolConfig" p:minPoolSize="5" p:maxPoolSize="10"
-                        p:validatePeriodically="true" p:validatePeriod="900" />
+                        p:validatePeriodically="true" p:validatePeriod="PT15M" />
                 </constructor-arg>
                 <constructor-arg index="1">
                     <bean class="org.ldaptive.DefaultConnectionFactory">
-                        <property name="provider">
-                            <bean class="org.ldaptive.provider.jndi.JndiProvider">
-                                <property name="providerConfig">
-                                    <bean class="org.ldaptive.provider.jndi.JndiProviderConfig">
-                                        <property name="properties">
-                                            <map>
-                                                <entry key="name1" value="value1" />
-                                                <entry key="name2" value="value2" />
-                                            </map>
-                                        </property>
-                                    </bean>
-                                </property>
-                            </bean>
-                        </property>
                         <property name="connectionConfig">
                             <bean class="org.ldaptive.ConnectionConfig" p:ldapUrl="ldap://localhost:10389"
-                                p:useStartTLS="true" p:connectTimeout="2000" p:responseTimeout="4000">
+                                p:useStartTLS="true" p:connectTimeout="PT2S" p:responseTimeout="PT4S">
                                 <property name="connectionInitializer">
                                     <bean class="org.ldaptive.BindConnectionInitializer" p:bindDn="cn=Directory Manager"
                                         p:bindCredential="password" />
@@ -57,12 +43,12 @@
                     </bean>
                 </property>
                 <property name="pruneStrategy">
-                    <bean class="org.ldaptive.pool.IdlePruneStrategy" p:prunePeriod="300" p:idleTime="600" />
+                    <bean class="org.ldaptive.pool.IdlePruneStrategy" p:prunePeriod="PT5M" p:idleTime="PT10M" />
                 </property>
             </bean>
         </property>
     </bean>
-    <bean class="org.ldaptive.SearchExecutor" p:baseDn="ou=people,dc=shibboleth,dc=net" p:returnAttributes="uid,homephone,mail" p:timeLimit="7000" />
+    <bean class="org.ldaptive.SearchExecutor" p:baseDn="ou=people,dc=shibboleth,dc=net" p:returnAttributes="uid,homephone,mail" p:timeLimit="PT7S" />
     <bean id="cache" class="com.google.common.cache.Cache" factory-bean="cacheBuilderExternal" factory-method="build" />
     <bean id="filter" class="net.shibboleth.idp.attribute.resolver.dc.ldap.impl.TemplatedExecutableSearchFilterBuilder"
         p:templateText="(uid=${resolutionContext.principal})" p:velocityEngine-ref="shibboleth.VelocityEngine"
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-props-context.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-props-context.xml
index 23b4676..79d44a3 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-props-context.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-attribute-resolver-spring-props-context.xml
@@ -15,20 +15,6 @@
                 </constructor-arg>
                 <constructor-arg index="1">
                     <bean class="org.ldaptive.DefaultConnectionFactory">
-                        <property name="provider">
-                            <bean class="org.ldaptive.provider.jndi.JndiProvider">
-                                <property name="providerConfig">
-                                    <bean class="org.ldaptive.provider.jndi.JndiProviderConfig">
-                                        <property name="properties">
-                                            <map>
-                                                <entry key="name1" value="%{jndi.property1}" />
-                                                <entry key="name2" value="%{jndi.property2}" />
-                                            </map>
-                                        </property>
-                                    </bean>
-                                </property>
-                            </bean>
-                        </property>
                         <property name="connectionConfig">
                             <bean class="org.ldaptive.ConnectionConfig" p:ldapUrl="%{connectionConfig.ldapURL}"
                                 p:useStartTLS="%{connectionConfig.useStartTLS}"
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v2.properties b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v2.properties
index c1a509c..8fb999d 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v2.properties
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v2.properties
@@ -14,9 +14,6 @@ search.filter=(uid=${resolutionContext.principal})
 search.returnAttributes=uid,homephone,mail
 search.timeLimit=PT7S
 
-jndi.property1=value1
-jndi.property2=value2
-
 connectionPool.blockWaitTime=PT5S
 connectionPool.expirationTime=PT10M
 connectionPool.minPoolSize=5
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v3.properties b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v3.properties
index 69203de..8d90f8f 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v3.properties
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/ldap-v3.properties
@@ -1,7 +1,7 @@
 connectionConfig.ldapURL=ldap://localhost:10389
 connectionConfig.useStartTLS=true
-connectionConfig.connectTimeout=2000
-connectionConfig.responseTimeout=4000
+connectionConfig.connectTimeout=PT2S
+connectionConfig.responseTimeout=PT4S
 connectionConfig.bindDn=cn=Directory Manager
 connectionConfig.bindCredential=password
 
@@ -12,20 +12,17 @@ noRetryDelay=PT5M
 search.baseDn=ou=people,dc=shibboleth,dc=net
 search.filter=(uid=${resolutionContext.principal})
 search.returnAttributes=uid,homephone,mail
-search.timeLimit=7000
+search.timeLimit=PT7S
 
-jndi.property1=value1
-jndi.property2=value2
-
-connectionPool.blockWaitTime=5000
+connectionPool.blockWaitTime=PT5S
 connectionPool.minPoolSize=5
 connectionPool.maxPoolSize=10
 connectionPool.validatePeriodically=true
-connectionPool.validatePeriod=900
+connectionPool.validatePeriod=PT15M
 connectionPool.validator.baseDn=dc=shibboleth,dc=net
 connectionPool.validator.filter=(ou=people)
-connectionPool.pruneStrategy.prunePeriod=300
-connectionPool.pruneStrategy.idleTime=600
+connectionPool.pruneStrategy.prunePeriod=PT5M
+connectionPool.pruneStrategy.idleTime=PT10M
 connectionPool.failFastInitialize=false
 
 cache.cacheBuilderSpec=expireAfterAccess=10s,maximumSize=25
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-hybrid.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-hybrid.xml
index 7ab6cff..67321e5 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-hybrid.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-hybrid.xml
@@ -7,8 +7,6 @@
         useStartTLS="true" searchTimeLimit="PT7S"
         executableSearchBuilderRef="filter" mappingStrategyRef="mappings" validatorRef="validator" noRetryDelay="PT5M"
         connectTimeout="PT2S" responseTimeout="PT4S">
-        <LDAPProperty name="name1" value="value1" />
-        <LDAPProperty name="name2" value="value2" />
         <StartTLSTrustCredential xsi:type="security:X509Inline" xmlns:security="urn:mace:shibboleth:2.0:security"
             id="LDAPtoIdPCredential">
             <security:Certificate>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml
deleted file mode 100644
index 0d0942c..0000000
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-jndi.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<AttributeResolver xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="urn:mace:shibboleth:2.0:security"
-        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd
-                            urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd">
-
-    <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
-        ldapURL="ldap://localhost:10389"
-        baseDN="ou=people,dc=shibboleth,dc=net"
-        principal="cn=Directory Manager"
-        principalCredential="password"
-        useStartTLS="true"
-        searchTimeLimit="PT7S"
-        noResultIsError="true"
-        multipleResultsIsError="true"
-        noRetryDelay="PT5M"
-        trustFile="net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap.crt"
-        connectTimeout="PT2S"
-        responseTimeout="PT4S">
-        
-        <LDAPProperty name="name1" value="value1"/>
-        <LDAPProperty name="java.naming.ldap.attributes.binary" value="jpegPhoto employeeNumber"/>
-        <LDAPProperty name="java.naming.ldap.derefAliases" value="finding"/>
-
-        <ReturnAttributes>cn sn jpegPhoto employeeNumber</ReturnAttributes>
-
-        <FilterTemplate>
-            <![CDATA[
-                (uid=${resolutionContext.principal})
-            ]]>
-        </FilterTemplate>
-        
-    </DataConnector>
-    
-</AttributeResolver>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-multi.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-multi.xml
index 960316c..c0ee482 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-multi.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-multi.xml
@@ -54,11 +54,6 @@
             <sec:Certificate>src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/client.crt</sec:Certificate>
         </StartTLSTrustCredential>
 
-
-        <LDAPProperty name="name2" value="value2"/>
-                
-        <LDAPProperty name="name1" value="value1"/>
-        
         <ResultCacheBean>cache</ResultCacheBean>
         <ResultCacheBean>cache</ResultCacheBean>
         
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-nosec.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-nosec.xml
index 709a3e5..b0d1a51 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-nosec.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-nosec.xml
@@ -42,12 +42,8 @@
             <sec:Certificate>src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/client.crt</sec:Certificate>
         </StartTLSAuthenticationCredential>
 
-        <LDAPProperty name="name2" value="value2"/>
-                
         <ReturnAttributes>a b g t</ReturnAttributes>
         
-        <LDAPProperty name="name1" value="value1"/>
-        
         <ReturnAttributes>a b g t</ReturnAttributes>
         
         <FilterTemplate>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-props.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-props.xml
index 7dc1bf6..cc87424 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-props.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2-props.xml
@@ -21,8 +21,6 @@
             ]]>
         </FilterTemplate>
         <ReturnAttributes>%{search.returnAttributes}</ReturnAttributes>
-        <LDAPProperty name="name1" value="%{jndi.property1}"/>
-        <LDAPProperty name="name2" value="%{jndi.property2}"/>
         <StartTLSTrustCredential xsi:type="security:X509Inline" xmlns:security="urn:mace:shibboleth:2.0:security" id="LDAPtoIdPCredential">
             <security:Certificate>
               MIICATCCAWoCCQCZy4ovDlQTvDANBgkqhkiG9w0BAQUFADBFMRMwEQYKCZImiZPy
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml
index 508ddfd..ff1c684 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/ldap/resolver/ldap-attribute-resolver-v2.xml
@@ -58,12 +58,8 @@
 
         <InputAttributeDefinition ref="321"/>
 
-        <LDAPProperty name="name2" value="value2"/>
-                
         <ReturnAttributes>a b g t employeeNumber</ReturnAttributes>
         
-        <LDAPProperty name="name1" value="value1"/>
-        
         <ReturnAttributes>a b g t employeeNumber</ReturnAttributes>
 
         <BinaryAttributes>g employeeNumber</BinaryAttributes>
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PooledTemplateSearchDnResolver.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PooledTemplateSearchDnResolver.java
index 76cc4b6..93324ac 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PooledTemplateSearchDnResolver.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PooledTemplateSearchDnResolver.java
@@ -76,9 +76,9 @@ public class PooledTemplateSearchDnResolver extends AbstractTemplateSearchDnReso
     @Override public String toString() {
         return String.format(
                 "[%s@%d::factory=%s, templateName=%s, baseDn=%s, userFilter=%s, userFilterParameters=%s, "
-                        + "allowMultipleDns=%s, subtreeSearch=%s, derefAliases=%s, followReferrals=%s]",
+                        + "allowMultipleDns=%s, subtreeSearch=%s, derefAliases=%s]",
                 getClass().getName(), hashCode(), factory, getTemplate().getTemplateName(), getBaseDn(),
                 getUserFilter(), Arrays.toString(getUserFilterParameters()), getAllowMultipleDns(), getSubtreeSearch(),
-                getDerefAliases(), getFollowReferrals());
+                getDerefAliases());
     }
 }
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/TemplateSearchDnResolver.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/TemplateSearchDnResolver.java
index f0d415d..b09c59a 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/TemplateSearchDnResolver.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/TemplateSearchDnResolver.java
@@ -77,9 +77,9 @@ public class TemplateSearchDnResolver extends AbstractTemplateSearchDnResolver i
     @Override public String toString() {
         return String.format(
                 "[%s@%d::factory=%s, templateName=%s, baseDn=%s, userFilter=%s, userFilterParameters=%s, "
-                        + "allowMultipleDns=%s, subtreeSearch=%s, derefAliases=%s, followReferrals=%s]",
+                        + "allowMultipleDns=%s, subtreeSearch=%s, derefAliases=%s]",
                 getClass().getName(), hashCode(), factory, getTemplate().getTemplateName(), getBaseDn(),
                 getUserFilter(), Arrays.toString(getUserFilterParameters()), getAllowMultipleDns(), getSubtreeSearch(),
-                getDerefAliases(), getFollowReferrals());
+                getDerefAliases());
     }
 }
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/LDAPAuthenticationFactoryBean.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/LDAPAuthenticationFactoryBean.java
new file mode 100644
index 0000000..2636d45
--- /dev/null
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/LDAPAuthenticationFactoryBean.java
@@ -0,0 +1,474 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.authn.config;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import net.shibboleth.idp.authn.PooledTemplateSearchDnResolver;
+import org.apache.velocity.app.VelocityEngine;
+import org.ldaptive.BindConnectionInitializer;
+import org.ldaptive.ConnectionConfig;
+import org.ldaptive.ConnectionInitializer;
+import org.ldaptive.Credential;
+import org.ldaptive.DefaultConnectionFactory;
+import org.ldaptive.LdapURL;
+import org.ldaptive.auth.Authenticator;
+import org.ldaptive.auth.FormatDnResolver;
+import org.ldaptive.auth.PooledBindAuthenticationHandler;
+import org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler;
+import org.ldaptive.auth.ext.EDirectoryAuthenticationResponseHandler;
+import org.ldaptive.auth.ext.FreeIPAAuthenticationResponseHandler;
+import org.ldaptive.auth.ext.PasswordExpirationAuthenticationResponseHandler;
+import org.ldaptive.auth.ext.PasswordPolicyAuthenticationRequestHandler;
+import org.ldaptive.auth.ext.PasswordPolicyAuthenticationResponseHandler;
+import org.ldaptive.pool.BlockingConnectionPool;
+import org.ldaptive.pool.IdlePruneStrategy;
+import org.ldaptive.pool.PoolConfig;
+import org.ldaptive.pool.PooledConnectionFactory;
+import org.ldaptive.pool.SearchValidator;
+import org.ldaptive.ssl.CredentialConfig;
+import org.ldaptive.ssl.SslConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+
+/** LDAP Authentication configuration. See ldap-authn-config.xml */
+public class LDAPAuthenticationFactoryBean extends AbstractFactoryBean<Authenticator> {
+
+  /** Class logger. */
+  @Nonnull
+  private final Logger log = LoggerFactory.getLogger(LDAPAuthenticationFactoryBean.class);
+
+  /** Enum that defines authenticator configuration. Labels maps to values in ldap.properties. */
+  public enum AuthenticatorType {
+    ANON_SEARCH("anonSearchAuthenticator"),
+    BIND_SEARCH("bindSearchAuthenticator"),
+    DIRECT("directAuthenticator"),
+    AD("adAuthenticator");
+
+    /** Label for this type. */
+    private final String label;
+
+    AuthenticatorType(final String s) {
+      label = s;
+    }
+
+    public String label() {
+      return label;
+    }
+
+    public static AuthenticatorType fromLabel(final String s) {
+      for (AuthenticatorType at : AuthenticatorType.values()) {
+        if (at.label().equals(s)) {
+          return at;
+        }
+      }
+      return null;
+    }
+  }
+
+  /** Enum that defines LDAP trust configuration. Labels maps to values in ldap.properties. */
+  public enum TrustType {
+    JVM("jvmTrust"),
+    CERTIFICATE("certificateTrust"),
+    KEYSTORE("keyStoreTrust");
+
+    /** Label for this type. */
+    private final String label;
+
+    TrustType(final String s) {
+      label = s;
+    }
+
+    public String label() {
+      return label;
+    }
+
+    public static TrustType fromLabel(final String s) {
+      for (TrustType tt : TrustType.values()) {
+        if (tt.label().equals(s)) {
+          return tt;
+        }
+      }
+      return null;
+    }
+  }
+
+  /** Type of authenticator to configure. */
+  private AuthenticatorType authenticatorType;
+
+  /** Type of trust model to configure. */
+  private TrustType trustType;
+
+  /** LDAP URL. */
+  private String ldapUrl;
+
+  /** Whether to use startTLS for connections. */
+  private boolean useStartTLS;
+
+  /** Whether to use LDAPS for connections. */
+  private boolean useSSL;
+
+  /** Wait time for connects. */
+  private Duration connectTimeout;
+
+  /** Wait time for operation responses. */
+  private Duration responseTimeout;
+
+  /** Trust configuration when using certificate based trust. */
+  private CredentialConfig trustCertificatesCredentialConfig;
+
+  /** Trust configuration when using truststore based trust. */
+  private CredentialConfig truststoreCredentialConfig;
+
+  /** Wait time for getting a connection from the pool. */
+  private Duration blockWaitTime;
+
+  /** Minimum pool size. */
+  private int minPoolSize;
+
+  /** Maximum pool size. */
+  private int maxPoolSize;
+
+  /** Whether to validate connections when checked out from the pool. */
+  private boolean validateOnCheckout;
+
+  /** Whether to validate connections periodically on a background thread. */
+  private boolean validatePeriodically;
+
+  /** Period at which to validate periodically. */
+  private Duration validatePeriod;
+
+  /** Period at which to check and enforce the idle time. */
+  private Duration prunePeriod;
+
+  /** Time at which a connection has been idle and should be removed from the pool. */
+  private Duration idleTime;
+
+  /** Java format string used to construct an LDAP DN. See {@link String#format(String, Object...)}. */
+  private String dnFormat;
+
+  /** Base DN used to search for users. */
+  private String baseDn;
+
+  /** LDAP filter used to search for users. */
+  private String userFilter;
+
+  /** Whether to use a SUBTREE search with the baseDn. */
+  private boolean subtreeSearch;
+
+  /** Whether to return the LDAP entry even if the user BIND fails. */
+  private boolean resolveEntryOnFailure;
+
+  /** Velocity engine used to materialize the LDAP filter. */
+  private VelocityEngine velocityEngine;
+
+  /** Privileged entry used to search for users. */
+  private String bindDn;
+
+  /** Credential for the privileged entry. */
+  private String bindDnCredential;
+
+  /** Whether to use the password policy control with the BIND operation. See draft-behera-ldap-password-policy. */
+  private boolean usePasswordPolicy;
+
+  /** Whether to use the password expiration control with the BIND operation. See draft-vchu-ldap-pwd-policy. */
+  private boolean usePasswordExpiration;
+
+  /** Whether to use account state data as defined by the FreeIPA directory schema. */
+  private boolean isFreeIPA;
+
+  /** Whether to use account state data as defined by the EDirectory schema. */
+  private boolean isEDirectory;
+
+  public void setAuthenticatorType(final String type) {
+    authenticatorType = AuthenticatorType.fromLabel(type);
+  }
+
+  public void setTrustType(final String type) {
+    trustType = TrustType.fromLabel(type);
+  }
+
+  public void setLdapUrl(final String url) {
+    ldapUrl = url;
+  }
+
+  public void setUseStartTLS(final boolean b) {
+    useStartTLS = b;
+  }
+
+  public void setUseSSL(final boolean b) {
+    useSSL = b;
+  }
+
+  public void setConnectTimeout(final Duration timeout) {
+    connectTimeout = timeout;
+  }
+
+  public void setResponseTimeout(final Duration timeout) {
+    responseTimeout = timeout;
+  }
+
+  public void setTrustCertificatesCredentialConfig(final CredentialConfig config) {
+    trustCertificatesCredentialConfig = config;
+  }
+
+  public void setTruststoreCredentialConfig(final CredentialConfig config) {
+    truststoreCredentialConfig = config;
+  }
+
+  public void setBlockWaitTime(final Duration time) {
+    blockWaitTime = time;
+  }
+
+  public void setMinPoolSize(final int size) {
+    minPoolSize = size;
+  }
+
+  public void setMaxPoolSize(final int size) {
+    maxPoolSize = size;
+  }
+
+  public void setValidateOnCheckout(final boolean b) {
+    validateOnCheckout = b;
+  }
+
+  public void setValidatePeriodically(final boolean b) {
+    validatePeriodically = b;
+  }
+
+  public void setValidatePeriod(final Duration period) {
+    validatePeriod = period;
+  }
+
+  public void setPrunePeriod(final Duration period) {
+    prunePeriod = period;
+  }
+
+  public void setIdleTime(final Duration time) {
+    idleTime = time;
+  }
+
+  public void setDnFormat(final String format) {
+    dnFormat = format;
+  }
+
+  public void setBaseDn(final String dn) {
+    baseDn = dn;
+  }
+
+  public void setUserFilter(final String filter) {
+    userFilter = filter;
+  }
+
+  public void setSubtreeSearch(final boolean b) {
+    subtreeSearch = b;
+  }
+
+  public void setResolveEntryOnFailure(final boolean b) {
+    resolveEntryOnFailure = b;
+  }
+
+  public void setVelocityEngine(final VelocityEngine engine) {
+    velocityEngine = engine;
+  }
+
+  public void setBindDn(final String dn) {
+    bindDn = dn;
+  }
+
+  public void setBindDnCredential(final String credential) {
+    bindDnCredential = credential;
+  }
+
+  public void setUsePasswordPolicy(final boolean b) {
+    usePasswordPolicy = b;
+  }
+
+  public void setUsePasswordExpiration(final boolean b) {
+    usePasswordExpiration = b;
+  }
+
+  public void setFreeIPA(final boolean b) {
+    isFreeIPA = b;
+  }
+
+  public void setEDirectory(final boolean b) {
+    isEDirectory = b;
+  }
+
+  /**
+   * Returns a new SslConfig object derived from the configured {@link #trustType}. Default uses JVM trust.
+   *
+   * @return new SslConfig
+   */
+  protected SslConfig createSslConfig() {
+    final SslConfig config = new SslConfig();
+    switch(trustType) {
+    case CERTIFICATE:
+      config.setCredentialConfig(trustCertificatesCredentialConfig);
+      break;
+    case KEYSTORE:
+      config.setCredentialConfig(truststoreCredentialConfig);
+      break;
+    case JVM:
+    default:
+      break;
+    }
+    return config;
+  }
+
+  /**
+   * Returns a new ConnectionConfig without a connection initializer.
+   *
+   * @return  new ConnectionConfig
+   */
+  protected ConnectionConfig createConnectionConfig() {
+    return createConnectionConfig(null);
+  }
+
+  /**
+   * Returns a new ConnectionConfig with the supplied connection initializer.
+   *
+   * @param initializer to configure or null
+   *
+   * @return new ConnectionConfig
+   */
+  protected ConnectionConfig createConnectionConfig(@Nullable final ConnectionInitializer initializer) {
+    final ConnectionConfig config = new ConnectionConfig();
+    config.setLdapUrl(ldapUrl);
+    config.setUseStartTLS(useStartTLS);
+    config.setConnectTimeout(connectTimeout);
+    config.setResponseTimeout(responseTimeout);
+    config.setSslConfig(createSslConfig());
+    if (initializer != null) {
+      config.setConnectionInitializer(initializer);
+    }
+    return config;
+  }
+
+  /**
+   * Returns a new blocking connection pool. Wires a {@link SearchValidator} by default.
+   *
+   * @param name of the connection pool
+   * @param config to assign to the pool
+   *
+   * @return new blocking connection pool
+   */
+  protected BlockingConnectionPool createConnectionPool(final String name, final ConnectionConfig config)
+  {
+    final PoolConfig poolConfig = new PoolConfig();
+    poolConfig.setMinPoolSize(minPoolSize);
+    poolConfig.setMaxPoolSize(maxPoolSize);
+    poolConfig.setValidateOnCheckOut(validateOnCheckout);
+    poolConfig.setValidatePeriodically(validatePeriodically);
+    poolConfig.setValidatePeriod(validatePeriod);
+    final BlockingConnectionPool pool = new BlockingConnectionPool();
+    pool.setName(name);
+    pool.setBlockWaitTime(blockWaitTime);
+    pool.setPoolConfig(poolConfig);
+    pool.setPruneStrategy(new IdlePruneStrategy(prunePeriod, idleTime));
+    pool.setValidator(new SearchValidator());
+    pool.setFailFastInitialize(false);
+    pool.setConnectionFactory(new DefaultConnectionFactory(config));
+    pool.initialize();
+    return pool;
+  }
+
+  @Override
+  protected Authenticator createInstance() throws Exception {
+    // check for deprecated useSSL property
+    if (useSSL) {
+      log.warn("The useSSL property is deprecated, specify the use of LDAPS in your URL by using the ldaps:// scheme.");
+      final LdapURL url = new LdapURL(ldapUrl);
+      for (String s : url.getHostnamesWithSchemeAndPort()) {
+        if (!s.startsWith("ldaps://")) {
+          throw new IllegalArgumentException("useSSL property specified but URL scheme is not ldaps:// for " + s);
+        }
+      }
+    }
+    final Authenticator authenticator = new Authenticator();
+    authenticator.setAuthenticationHandler(
+      new PooledBindAuthenticationHandler(
+        new PooledConnectionFactory(createConnectionPool("bind-pool", createConnectionConfig()))));
+    switch(authenticatorType) {
+    case BIND_SEARCH:
+      final PooledTemplateSearchDnResolver bindSearchDnResolver =
+        new PooledTemplateSearchDnResolver(velocityEngine, userFilter);
+      bindSearchDnResolver.setBaseDn(baseDn);
+      bindSearchDnResolver.setSubtreeSearch(subtreeSearch);
+      bindSearchDnResolver.setConnectionFactory(
+        new PooledConnectionFactory(
+          createConnectionPool(
+            "search-pool",
+            createConnectionConfig(new BindConnectionInitializer(bindDn, new Credential(bindDnCredential))))));
+      authenticator.setDnResolver(bindSearchDnResolver);
+      authenticator.setResolveEntryOnFailure(resolveEntryOnFailure);
+      break;
+    case DIRECT:
+      authenticator.setDnResolver(new FormatDnResolver(dnFormat));
+      authenticator.setResolveEntryOnFailure(resolveEntryOnFailure);
+      break;
+    case AD:
+      authenticator.setDnResolver(new FormatDnResolver(dnFormat));
+      authenticator.setResolveEntryOnFailure(resolveEntryOnFailure);
+      authenticator.setAuthenticationResponseHandlers(new ActiveDirectoryAuthenticationResponseHandler());
+      break;
+    case ANON_SEARCH:
+      final PooledTemplateSearchDnResolver anonSearchDnResolver =
+        new PooledTemplateSearchDnResolver(velocityEngine, userFilter);
+      anonSearchDnResolver.setBaseDn(baseDn);
+      anonSearchDnResolver.setSubtreeSearch(subtreeSearch);
+      anonSearchDnResolver.setConnectionFactory(
+        new PooledConnectionFactory(
+          createConnectionPool(
+            "search-pool",
+            createConnectionConfig())));
+      authenticator.setDnResolver(anonSearchDnResolver);
+      authenticator.setResolveEntryOnFailure(resolveEntryOnFailure);
+    default:
+      break;
+    }
+    final List<String> retAttrs = new ArrayList<>();
+    if (usePasswordPolicy) {
+      authenticator.setAuthenticationRequestHandlers(new PasswordPolicyAuthenticationRequestHandler());
+      authenticator.setAuthenticationResponseHandlers(new PasswordPolicyAuthenticationResponseHandler());
+    } else if (usePasswordExpiration) {
+      authenticator.setAuthenticationResponseHandlers(new PasswordExpirationAuthenticationResponseHandler());
+    } else if (isEDirectory) {
+      retAttrs.addAll(Arrays.asList(EDirectoryAuthenticationResponseHandler.ATTRIBUTES));
+      authenticator.setAuthenticationResponseHandlers(new EDirectoryAuthenticationResponseHandler());
+    } else if (isFreeIPA) {
+      retAttrs.addAll(Arrays.asList(FreeIPAAuthenticationResponseHandler.ATTRIBUTES));
+      authenticator.setAuthenticationResponseHandlers(new FreeIPAAuthenticationResponseHandler());
+    }
+    if (!retAttrs.isEmpty()) {
+      authenticator.setReturnAttributes(retAttrs.toArray(new String[0]));
+    }
+    return authenticator;
+  }
+
+  @Override
+  public Class<?> getObjectType() {
+    return Authenticator.class;
+  }
+}
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/LDAPCredentialValidatorTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/LDAPCredentialValidatorTest.java
index a88c1b0..1164162 100644
--- a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/LDAPCredentialValidatorTest.java
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/LDAPCredentialValidatorTest.java
@@ -17,6 +17,7 @@
 
 package net.shibboleth.idp.authn.impl;
 
+import java.time.ZonedDateTime;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -417,7 +418,7 @@ public class LDAPCredentialValidatorTest extends BaseAuthenticationContextTest {
         warningAuthenticator.setAuthenticationResponseHandlers(new AuthenticationResponseHandler() {
             public void handle(AuthenticationResponse response) throws LdapException {
                 response.setAccountState(
-                        new AccountState(new AccountState.DefaultWarning(java.util.Calendar.getInstance(), 10)));
+                        new AccountState(new AccountState.DefaultWarning(ZonedDateTime.now(), 10)));
             }
         });
         validator.setAuthenticator(warningAuthenticator);
diff --git a/idp-conf/pom.xml b/idp-conf/pom.xml
index 426ca71..605aa9b 100644
--- a/idp-conf/pom.xml
+++ b/idp-conf/pom.xml
@@ -99,11 +99,6 @@
 
         <!-- Test Dependencies -->
         <dependency>
-            <groupId>org.ldaptive</groupId>
-            <artifactId>ldaptive-unboundid</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>com.unboundid</groupId>
             <artifactId>unboundid-ldapsdk</artifactId>
             <scope>test</scope>
diff --git a/idp-conf/src/main/resources/conf/authn/ldap-authn-config.xml b/idp-conf/src/main/resources/conf/authn/ldap-authn-config.xml
index 44e1b60..ebe0d76 100644
--- a/idp-conf/src/main/resources/conf/authn/ldap-authn-config.xml
+++ b/idp-conf/src/main/resources/conf/authn/ldap-authn-config.xml
@@ -5,129 +5,46 @@
        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>
 
-    <!-- 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:connectTimeoutDuration="%{idp.authn.LDAP.connectTimeout:PT3S}"
-        p:responseTimeoutDuration="%{idp.authn.LDAP.responseTimeout:PT3S}"
-        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" />
-
-    <!-- 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:blockWaitTimeDuration="%{idp.pool.LDAP.blockWaitTime:PT3S}"
-        p:poolConfig-ref="poolConfig"
-        p:pruneStrategy-ref="pruneStrategy"
-        p:validator-ref="searchValidator"
-        p: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:validatePeriodDuration="%{idp.pool.LDAP.validatePeriod:PT5M}" />
-    <bean id="pruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
-        p:prunePeriodDuration="%{idp.pool.LDAP.prunePeriod:PT5M}"
-        p:idleTimeDuration="%{idp.pool.LDAP.idleTime:PT10M}" />
-    <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="net.shibboleth.idp.authn.PooledTemplateSearchDnResolver"
-        p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
-        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
-        p:connectionFactory-ref="anonSearchPooledConnectionFactory" >
-        <constructor-arg index="0" ref="shibboleth.VelocityEngine" />
-        <constructor-arg index="1" value="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}" />
-    </bean>
-    <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" />
-
-    <!-- Bind Search Configuration -->
-    <bean name="bindSearchAuthenticator" class="org.ldaptive.auth.Authenticator" p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
-        <constructor-arg index="0" ref="bindSearchDnResolver" />
-        <constructor-arg index="1" ref="authHandler" />
-    </bean>
-    <bean id="bindSearchDnResolver" class="net.shibboleth.idp.authn.PooledTemplateSearchDnResolver"
-        p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
-        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
-        p:connectionFactory-ref="bindSearchPooledConnectionFactory" >
-        <constructor-arg index="0" ref="shibboleth.VelocityEngine" />
-        <constructor-arg index="1" value="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}" />
-    </bean>
-    <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>
-
-    <!-- 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>
-
-    <!-- Want to use ppolicy? Configure support by adding <bean id="authenticationResponseHandler" class="org.ldaptive.auth.ext.PasswordPolicyAuthenticationResponseHandler" 
-        /> add p:authenticationResponseHandlers-ref="authenticationResponseHandler" to the authenticator <bean id="authenticationControl" 
-        class="org.ldaptive.control.PasswordPolicyControl" /> add p:authenticationControls-ref="authenticationControl" to the authHandler -->
-
-    <!-- Active Directory Configuration -->
-    <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="shibboleth.authn.LDAP.trustCertificates" parent="shibboleth.X509ResourceCredentialConfig" p:trustCertificates="%{idp.authn.LDAP.trustCertificates:undefined}" />
+    <bean id="shibboleth.authn.LDAP.truststore" parent="shibboleth.KeystoreResourceCredentialConfig" p:truststore="%{idp.authn.LDAP.trustStore:undefined}" />
+
+    <bean id="shibboleth.authn.LDAP.authenticator" class="net.shibboleth.idp.authn.config.LDAPAuthenticationFactoryBean"
+          p:authenticatorType="%{idp.authn.LDAP.authenticator:anonSearchAuthenticator}"
+          p:trustType="%{idp.authn.LDAP.sslConfig:certificateTrust}"
+          p:ldapUrl="%{idp.authn.LDAP.ldapURL}"
+          p:useStartTLS="%{idp.authn.LDAP.useStartTLS:true}"
+          p:connectTimeout="%{idp.authn.LDAP.connectTimeout:PT3S}"
+          p:responseTimeout="%{idp.authn.LDAP.responseTimeout:PT3S}"
+          p:trustCertificatesCredentialConfig-ref="shibboleth.authn.LDAP.trustCertificates"
+          p:truststoreCredentialConfig-ref="shibboleth.authn.LDAP.truststore"
+          p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
+          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:PT5M}"
+          p:prunePeriod="%{idp.pool.LDAP.prunePeriod:PT5M}"
+          p:idleTime="%{idp.pool.LDAP.idleTime:PT10M}"
+          p:dnFormat="%{idp.authn.LDAP.dnFormat:undefined}"
+          p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
+          p:userFilter="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}"
+          p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
+          p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}"
+          p:velocityEngine-ref="shibboleth.VelocityEngine"
+          p:bindDn="#{'%{idp.authn.LDAP.bindDN:undefined}'.trim()}"
+          p:bindDnCredential="%{idp.authn.LDAP.bindDNCredential:undefined}"
+          p:usePasswordPolicy="%{idp.authn.LDAP.usePasswordPolicy:false}"
+          p:usePasswordExpiration="%{idp.authn.LDAP.usePasswordExpiration:false}"
+          p:freeIPA="%{idp.authn.LDAP.freeIPADirectory:false}"
+          p:EDirectory="%{idp.authn.LDAP.eDirectory:false}"
+    />
 
 </beans>
diff --git a/idp-conf/src/main/resources/system/conf/global-system.xml b/idp-conf/src/main/resources/system/conf/global-system.xml
index 084ff3d..f719000 100644
--- a/idp-conf/src/main/resources/system/conf/global-system.xml
+++ b/idp-conf/src/main/resources/system/conf/global-system.xml
@@ -58,7 +58,6 @@
         <property name="arguments">
             <props>
                 <prop key="org.apache.xml.security.ignoreLineBreaks">%{idp.apache.xml.security.ignoreLineBreaks:true}</prop>
-                <prop key="org.ldaptive.provider">%{idp.ldaptive.provider:%{org.ldaptive.provider:org.ldaptive.provider.unboundid.UnboundIDProvider}}</prop>
             </props>
         </property>
     </bean>
diff --git a/idp-conf/src/test/java/net/shibboleth/idp/test/InMemoryDirectory.java b/idp-conf/src/test/java/net/shibboleth/idp/test/InMemoryDirectory.java
index 19f7b7a..068a888 100644
--- a/idp-conf/src/test/java/net/shibboleth/idp/test/InMemoryDirectory.java
+++ b/idp-conf/src/test/java/net/shibboleth/idp/test/InMemoryDirectory.java
@@ -23,9 +23,9 @@ import java.security.KeyStore;
 
 import javax.annotation.Nonnull;
 
+import com.unboundid.util.ssl.SSLUtil;
 import org.ldaptive.ssl.CredentialConfigFactory;
-import org.ldaptive.ssl.SslConfig;
-import org.ldaptive.ssl.TLSSocketFactory;
+import org.ldaptive.ssl.SSLContextInitializer;
 import org.springframework.core.io.Resource;
 
 import com.unboundid.ldap.listener.InMemoryDirectoryServer;
@@ -67,12 +67,11 @@ public class InMemoryDirectory {
             final KeyStore ks = KeyStore.getInstance("JKS");
             final String ksPass = "changeit";
             ks.load(keystore.getInputStream(), ksPass.toCharArray());
-            final TLSSocketFactory socketFactory = new TLSSocketFactory();
-            socketFactory.setSslConfig(new SslConfig(CredentialConfigFactory.createKeyStoreCredentialConfig(ks, ksPass)));
-            socketFactory.initialize();
-            
-            config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", null, port,
-                    socketFactory));
+            final SSLContextInitializer sslInit =
+                CredentialConfigFactory.createKeyStoreCredentialConfig(ks, ksPass).createSSLContextInitializer();
+            final SSLUtil sslUtil = new SSLUtil(sslInit.getKeyManagers(), sslInit.getTrustManagers());
+            config.setListenerConfigs(
+                InMemoryListenerConfig.createLDAPConfig("default", null, port, sslUtil.createSSLSocketFactory()));
         } catch (final GeneralSecurityException e) {
             throw new IOException("Error reading keystore", e);
         }
diff --git a/idp-distribution/pom.xml b/idp-distribution/pom.xml
index 7cd7f44..22e8c7e 100644
--- a/idp-distribution/pom.xml
+++ b/idp-distribution/pom.xml
@@ -77,16 +77,6 @@
             <version>${metrics.version}</version>
             <scope>runtime</scope>
         </dependency>
-        <dependency>
-            <groupId>org.ldaptive</groupId>
-            <artifactId>ldaptive-unboundid</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.unboundid</groupId>
-            <artifactId>unboundid-ldapsdk</artifactId>
-            <scope>runtime</scope>
-        </dependency>
         
         <!-- Test Dependencies -->
 
diff --git a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
index 0512951..9308298 100644
--- a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
+++ b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
@@ -775,13 +775,6 @@
                             </documentation>
                         </annotation>
                     </element>
-                    <element name="LDAPProperty" type="resolver:PropertyType">
-                        <annotation>
-                            <documentation>
-                                LDAP connection properties relevant to the underlying provider being used.
-                            </documentation>
-                        </annotation>
-                    </element>
                     <element name="StartTLSTrustCredential" type="sec:X509Credential">
                         <annotation>
                             <documentation>
@@ -816,7 +809,7 @@
                 <attribute name="connectionStrategy" type="resolver:ConnectionStrategyType">
                     <annotation>
                         <documentation>
-                            The LDAP connection strategy. Acceptable values are DEFAULT, ACTIVE_PASSIVE, ROUND_ROBIN, and RANDOM.
+                            The LDAP connection strategy. Acceptable values are ACTIVE_PASSIVE, ROUND_ROBIN and RANDOM.
                             Default value is ACTIVE_PASSIVE.
                         </documentation>
                     </annotation>
@@ -1581,7 +1574,6 @@
             <documentation>Supported connection strategies.</documentation>
         </annotation>
         <restriction base="string">
-            <enumeration value="DEFAULT"/>
             <enumeration value="ACTIVE_PASSIVE"/>
             <enumeration value="ROUND_ROBIN"/>
             <enumeration value="RANDOM"/>
@@ -1646,16 +1638,6 @@
                 </documentation>
             </annotation>
         </attribute>
-        <attribute name="blockWhenEmpty" type="resolver:string">
-            <annotation>
-                <documentation>
-                    Whether the pool should block when maxPoolSize objects are in use.
-                    If false, pool will grow beyond the maxPoolSize value.
-                    Note that a properly configured blocking pool will yield better performance.
-                    Default value is true.
-                </documentation>
-            </annotation>
-        </attribute>
         <attribute name="blockWaitTime" type="resolver:string">
             <annotation>
                 <documentation>
diff --git a/idp-war-distribution/pom.xml b/idp-war-distribution/pom.xml
index e8ce3e9..5bfe382 100644
--- a/idp-war-distribution/pom.xml
+++ b/idp-war-distribution/pom.xml
@@ -44,17 +44,6 @@
             <version>${metrics.version}</version>
             <scope>runtime</scope>
         </dependency>
-        <!-- IDP-1401 - UnboundID as default ldaptive LDAP provider -->
-        <dependency>
-            <groupId>org.ldaptive</groupId>
-            <artifactId>ldaptive-unboundid</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.unboundid</groupId>
-            <artifactId>unboundid-ldapsdk</artifactId>
-            <scope>runtime</scope>
-        </dependency>
     </dependencies>
 
     <distributionManagement>

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list