You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2015/05/21 02:48:27 UTC

svn commit: r1680714 - in /jackrabbit/oak/branches/1.2: oak-auth-ldap/ oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/ oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/ oak-auth...

Author: tripod
Date: Thu May 21 00:48:27 2015
New Revision: 1680714

URL: http://svn.apache.org/r1680714
Log:
OAK-2897 Regression - lookupOnValidate does not work

Added:
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundConnectionValidator.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundLookupConnectionValidator.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/resources/logback-test.xml
      - copied, changed from r1680577, jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml
Removed:
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/OakPoolableLdapConnectionFactory.java
Modified:
    jackrabbit/oak/branches/1.2/oak-auth-ldap/pom.xml
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/PoolableUnboundConnectionFactory.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java
    jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml

Modified: jackrabbit/oak/branches/1.2/oak-auth-ldap/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/pom.xml?rev=1680714&r1=1680713&r2=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/pom.xml (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/pom.xml Thu May 21 00:48:27 2015
@@ -71,7 +71,7 @@
         <dependency>
             <groupId>org.apache.directory.api</groupId>
             <artifactId>api-all</artifactId>
-            <version>1.0.0-M20</version>
+            <version>1.0.0-M30</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -168,9 +168,21 @@
         </dependency>
         <dependency>
             <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-all</artifactId>
+            <version>2.0.0-M20</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
             <artifactId>apacheds-server-unit</artifactId>
             <version>1.5.5</version>
             <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.directory.server</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>

Modified: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java?rev=1680714&r1=1680713&r2=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java Thu May 21 00:48:27 2015
@@ -47,10 +47,14 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.ldap.client.api.AbstractPoolableLdapConnectionFactory;
+import org.apache.directory.ldap.client.api.DefaultLdapConnectionValidator;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapConnectionConfig;
 import org.apache.directory.ldap.client.api.LdapConnectionPool;
+import org.apache.directory.ldap.client.api.LookupLdapConnectionValidator;
 import org.apache.directory.ldap.client.api.NoVerificationTrustManager;
+import org.apache.directory.ldap.client.api.ValidatingPoolableLdapConnectionFactory;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.ConfigurationPolicy;
@@ -99,7 +103,7 @@ public class LdapIdentityProvider implem
     /**
      * admin connection factory
      */
-    private OakPoolableLdapConnectionFactory adminConnectionFactory;
+    private AbstractPoolableLdapConnectionFactory adminConnectionFactory;
 
     /**
      * the connection pool with unbound connections
@@ -482,8 +486,12 @@ public class LdapIdentityProvider implem
             cc.setName(bindDN);
             cc.setCredentials(config.getBindPassword());
         }
-        adminConnectionFactory = new OakPoolableLdapConnectionFactory(cc);
-        adminConnectionFactory.setLookupOnValidate(config.getAdminPoolConfig().lookupOnValidate());
+        adminConnectionFactory = new ValidatingPoolableLdapConnectionFactory(cc);
+        if (config.getAdminPoolConfig().lookupOnValidate()) {
+            adminConnectionFactory.setValidator(new LookupLdapConnectionValidator());
+        } else {
+            adminConnectionFactory.setValidator(new DefaultLdapConnectionValidator());
+        }
         if (config.getAdminPoolConfig().getMaxActive() != 0) {
             adminPool = new LdapConnectionPool(adminConnectionFactory);
             adminPool.setTestOnBorrow(true);
@@ -495,7 +503,11 @@ public class LdapIdentityProvider implem
         cc = createConnectionConfig();
 
         userConnectionFactory = new PoolableUnboundConnectionFactory(cc);
-        userConnectionFactory.setLookupOnValidate(config.getUserPoolConfig().lookupOnValidate());
+        if (config.getUserPoolConfig().lookupOnValidate()) {
+            userConnectionFactory.setValidator(new UnboundLookupConnectionValidator());
+        } else {
+            userConnectionFactory.setValidator(new UnboundConnectionValidator());
+        }
         if (config.getUserPoolConfig().getMaxActive() != 0) {
             userPool = new UnboundLdapConnectionPool(userConnectionFactory);
             userPool.setTestOnBorrow(true);
@@ -540,21 +552,18 @@ public class LdapIdentityProvider implem
 
         // Process the request
         SearchCursor searchCursor = null;
+        Entry resultEntry = null;
         try {
             searchCursor = connection.search(req);
             while (searchCursor.next()) {
-                Response response = searchCursor.get();
-
-                // process the SearchResultEntry
-                if (response instanceof SearchResultEntry) {
-                    Entry resultEntry = ((SearchResultEntry) response).getEntry();
-                    if (searchCursor.next()) {
-                        log.warn("search for {} returned more than one entry. discarding additional ones.", searchFilter);
-                    }
-                    if (log.isDebugEnabled()) {
-                        log.debug("search below {} with {} found {}", idConfig.getBaseDN(), searchFilter, resultEntry.getDn());
+                if (resultEntry != null) {
+                    log.warn("search for {} returned more than one entry. discarding additional ones.", searchFilter);
+                } else {
+                    // process the SearchResultEntry
+                    Response response = searchCursor.get();
+                    if (response instanceof SearchResultEntry) {
+                        resultEntry = ((SearchResultEntry) response).getEntry();
                     }
-                    return resultEntry;
                 }
             }
         } finally {
@@ -563,9 +572,13 @@ public class LdapIdentityProvider implem
             }
         }
         if (log.isDebugEnabled()) {
-            log.debug("search below {} with {} found 0 entries.", idConfig.getBaseDN(), searchFilter);
+            if (resultEntry == null) {
+                log.debug("search below {} with {} found 0 entries.", idConfig.getBaseDN(), searchFilter);
+            } else {
+                log.debug("search below {} with {} found {}", idConfig.getBaseDN(), searchFilter, resultEntry.getDn());
+            }
         }
-        return null;
+        return resultEntry;
     }
 
     /**

Modified: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/PoolableUnboundConnectionFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/PoolableUnboundConnectionFactory.java?rev=1680714&r1=1680713&r2=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/PoolableUnboundConnectionFactory.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/PoolableUnboundConnectionFactory.java Thu May 21 00:48:27 2015
@@ -19,12 +19,12 @@ package org.apache.jackrabbit.oak.securi
 import java.io.IOException;
 
 import org.apache.commons.pool.PoolableObjectFactory;
-import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapConnectionValidator;
 import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.LookupLdapConnectionValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,9 +45,9 @@ public class PoolableUnboundConnectionFa
     private LdapConnectionConfig config;
 
     /**
-     * flag controlling the validation behavior
+     * internal validator
      */
-    private boolean lookupOnValidate;
+    private LdapConnectionValidator validator = new LookupLdapConnectionValidator();
 
     /**
      * Creates a new instance of PoolableUnboundConnectionFactory
@@ -59,18 +59,19 @@ public class PoolableUnboundConnectionFa
     }
 
     /**
-     * Checks if a lookup is performed during {@link #validateObject(LdapConnection)}.
-     * @return {@code true} if a lookup is performed.
+     * gets the connection validator
+     * @return the connection validator
      */
-    public boolean getLookupOnValidate() {
-        return lookupOnValidate;
+    public LdapConnectionValidator getValidator() {
+        return validator;
     }
 
     /**
-     * @see #getLookupOnValidate()
+     * Sets the connection validator that is used when the connection is taken out of the pool
+     * @param validator the validator
      */
-    public void setLookupOnValidate(boolean lookupOnValidate) {
-        this.lookupOnValidate = lookupOnValidate;
+    public void setValidator(LdapConnectionValidator validator) {
+        this.validator = validator;
     }
 
     /**
@@ -115,16 +116,7 @@ public class PoolableUnboundConnectionFa
      * {@inheritDoc}
      */
     public boolean validateObject(LdapConnection connection) {
-        boolean valid = false;
-        if (connection.isConnected()) {
-            if (lookupOnValidate) {
-                try {
-                    valid = connection.lookup(Dn.ROOT_DSE, SchemaConstants.NO_ATTRIBUTE) != null;
-                } catch (LdapException le) {
-                    log.debug("error during connection validation: {}", le.toString());
-                }
-            }
-        }
+        boolean valid = validator == null || validator.validate(connection);
         log.debug("validating connection {}: {}", connection, valid);
         return valid;
     }

Added: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundConnectionValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundConnectionValidator.java?rev=1680714&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundConnectionValidator.java (added)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundConnectionValidator.java Thu May 21 00:48:27 2015
@@ -0,0 +1,40 @@
+/**
+ * **********************************************************************
+ * <p/>
+ * ADOBE CONFIDENTIAL
+ * ___________________
+ * <p/>
+ * Copyright ${today.year} Adobe Systems Incorporated
+ * All Rights Reserved.
+ * <p/>
+ * NOTICE:  All information contained herein is, and remains
+ * the property of Adobe Systems Incorporated and its suppliers,
+ * if any.  The intellectual and technical concepts contained
+ * herein are proprietary to Adobe Systems Incorporated and its
+ * suppliers and are protected by trade secret or copyright law.
+ * Dissemination of this information or reproduction of this material
+ * is strictly forbidden unless prior written permission is obtained
+ * from Adobe Systems Incorporated.
+ * ************************************************************************
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionValidator;
+
+/**
+ * {@code UnboundConnectionValidator}...
+ */
+public class UnboundConnectionValidator implements LdapConnectionValidator {
+
+    /**
+     * Returns true if <code>connection</code> is connected
+     *
+     * @param connection The connection to validate
+     * @return True, if the connection is still valid
+     */
+    @Override
+    public boolean validate( LdapConnection connection ) {
+        return connection.isConnected();
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundLookupConnectionValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundLookupConnectionValidator.java?rev=1680714&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundLookupConnectionValidator.java (added)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/UnboundLookupConnectionValidator.java Thu May 21 00:48:27 2015
@@ -0,0 +1,56 @@
+/**
+ * **********************************************************************
+ * <p/>
+ * ADOBE CONFIDENTIAL
+ * ___________________
+ * <p/>
+ * Copyright ${today.year} Adobe Systems Incorporated
+ * All Rights Reserved.
+ * <p/>
+ * NOTICE:  All information contained herein is, and remains
+ * the property of Adobe Systems Incorporated and its suppliers,
+ * if any.  The intellectual and technical concepts contained
+ * herein are proprietary to Adobe Systems Incorporated and its
+ * suppliers and are protected by trade secret or copyright law.
+ * Dissemination of this information or reproduction of this material
+ * is strictly forbidden unless prior written permission is obtained
+ * from Adobe Systems Incorporated.
+ * ************************************************************************
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code UnboundConnectionValidator}...
+ */
+public class UnboundLookupConnectionValidator implements LdapConnectionValidator {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(UnboundLookupConnectionValidator.class);
+
+    /**
+     * Returns true if <code>connection</code> is connected, authenticated, and
+     * a lookup on the rootDSE returns a non-null response.
+     *
+     * @param connection The connection to validate
+     * @return True, if the connection is still valid
+     */
+    public boolean validate(LdapConnection connection) {
+        try {
+            return connection.isConnected()
+                    && (connection.lookup(Dn.ROOT_DSE, SchemaConstants.NO_ATTRIBUTE) != null);
+        } catch (LdapException e) {
+            log.info("validating failed: {}", e);
+            return false;
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java?rev=1680714&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java (added)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/AbstractServer.java Thu May 21 00:48:27 2015
@@ -0,0 +1,421 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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 org.apache.jackrabbit.oak.security.authentication.ldap;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
+import org.apache.directory.api.ldap.schema.extractor.SchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.api.ldap.schema.loader.LdifSchemaLoader;
+import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.core.DefaultDirectoryService;
+import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.InstanceLayout;
+import org.apache.directory.server.core.api.schema.SchemaPartition;
+import org.apache.directory.server.core.factory.JdbmPartitionFactory;
+import org.apache.directory.server.core.jndi.CoreContextFactory;
+import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
+import org.apache.directory.server.core.partition.ldif.LdifPartition;
+import org.apache.directory.server.ldap.LdapServer;
+import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
+import org.apache.directory.server.ldap.handlers.extended.StoredProcedureExtendedOperationHandler;
+import org.apache.directory.server.ldap.handlers.sasl.MechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.gssapi.GssapiMechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
+import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
+import org.apache.directory.server.protocol.shared.transport.TcpTransport;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
+import org.apache.mina.util.AvailablePortFinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A simple testcase for testing JNDI provider functionality.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 784530 $
+ */
+public abstract class AbstractServer {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractServer.class);
+    private static final List<LdifEntry> EMPTY_LIST = Collections.unmodifiableList(new ArrayList<LdifEntry>(0));
+    private static final String CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
+
+    /**
+     * the context root for the system partition
+     */
+    protected LdapContext sysRoot;
+
+    /**
+     * the context root for the rootDSE
+     */
+    protected CoreSession rootDSE;
+
+    /**
+     * the context root for the schema
+     */
+    protected LdapContext schemaRoot;
+
+    /**
+     * flag whether to delete database files for each test or not
+     */
+    protected boolean doDelete = true;
+
+    protected int port = -1;
+
+    protected DirectoryService directoryService;
+
+    protected LdapServer ldapServer;
+
+
+    /**
+     * If there is an LDIF file with the same name as the test class
+     * but with the .ldif extension then it is read and the entries
+     * it contains are added to the server.  It appears as though the
+     * administor adds these entries to the server.
+     *
+     * @param verifyEntries whether or not all entry additions are checked
+     *                      to see if they were in fact correctly added to the server
+     * @return a list of entries added to the server in the order they were added
+     * @throws NamingException of the load fails
+     */
+    protected List<LdifEntry> loadTestLdif(boolean verifyEntries) throws Exception {
+        return loadLdif(getClass().getResourceAsStream(getClass().getSimpleName() + ".ldif"), verifyEntries);
+    }
+
+
+    /**
+     * Loads an LDIF from an input stream and adds the entries it contains to
+     * the server.  It appears as though the administrator added these entries
+     * to the server.
+     *
+     * @param in            the input stream containing the LDIF entries to load
+     * @param verifyEntries whether or not all entry additions are checked
+     *                      to see if they were in fact correctly added to the server
+     * @return a list of entries added to the server in the order they were added
+     * @throws NamingException of the load fails
+     */
+    protected List<LdifEntry> loadLdif(InputStream in, boolean verifyEntries) throws Exception {
+        if (in == null) {
+            return EMPTY_LIST;
+        }
+
+        LdifReader ldifReader = new LdifReader(in);
+        return loadLdif(ldifReader, verifyEntries);
+    }
+
+    protected List<LdifEntry> loadLdif(LdifReader ldifReader, boolean verifyEntries) throws Exception {
+        List<LdifEntry> entries = new ArrayList<LdifEntry>();
+        for (LdifEntry ldifEntry : ldifReader) {
+            Dn dn = ldifEntry.getDn();
+            if (ldifEntry.isEntry()) {
+                org.apache.directory.api.ldap.model.entry.Entry items = ldifEntry.getEntry();
+                rootDSE.add(new DefaultEntry(directoryService.getSchemaManager(), items));
+                if (verifyEntries) {
+                    verify(ldifEntry);
+                    LOG.info("Successfully verified addition of entry {}", dn);
+                } else {
+                    LOG.info("Added entry {} without verification", dn);
+                }
+                entries.add(ldifEntry);
+            }
+        }
+        return entries;
+    }
+
+    /**
+     * Inject an ldif String into the server. DN must be relative to the
+     * root.
+     *
+     * @param ldif the entries to inject
+     * @throws NamingException if the entries cannot be added
+     */
+    protected void injectEntries(String ldif) throws Exception {
+        LdifReader reader = new LdifReader();
+        loadLdif(reader, false);
+    }
+
+    /**
+     * Verifies that an entry exists in the directory with the
+     * specified attributes.
+     *
+     * @param entry the entry to verify
+     * @throws NamingException if there are problems accessing the entry
+     */
+    protected void verify(LdifEntry entry) throws Exception {
+//        Entry readEntry = rootDSE.lookup( entry.getDn() );
+//
+//        for ( EntryAttribute readAttribute:readEntry )
+//        {
+//            String id = readAttribute.getId();
+//            EntryAttribute origAttribute = entry.getEntry().get( id );
+//
+//            for ( Value<?> value:origAttribute )
+//            {
+//                if ( ! readAttribute.contains( value ) )
+//                {
+//                    LOG.error( "Failed to verify entry addition of {}. {} attribute in original " +
+//                            "entry missing from read entry.", entry.getDn(), id );
+//                    throw new AssertionFailedError( "Failed to verify entry addition of " + entry.getDn()  );
+//                }
+//            }
+//        }
+    }
+
+
+    /**
+     * Common code to get an initial context via a simple bind to the
+     * server over the wire using the SUN JNDI LDAP provider. Do not use
+     * this method until after the setUp() method is called to start the
+     * server otherwise it will fail.
+     *
+     * @return an LDAP context as the the administrator to the rootDSE
+     * @throws NamingException if the server cannot be contacted
+     */
+    protected LdapContext getWiredContext() throws Exception {
+        return getWiredContext(ServerDNConstants.ADMIN_SYSTEM_DN, "secret");
+    }
+
+
+    /**
+     * Common code to get an initial context via a simple bind to the
+     * server over the wire using the SUN JNDI LDAP provider. Do not use
+     * this method until after the setUp() method is called to start the
+     * server otherwise it will fail.
+     *
+     * @param bindPrincipalDn the DN of the principal to bind as
+     * @param password        the password of the bind principal
+     * @return an LDAP context as the the administrator to the rootDSE
+     * @throws NamingException if the server cannot be contacted
+     */
+    protected LdapContext getWiredContext(String bindPrincipalDn, String password) throws Exception {
+//        if ( ! apacheDS.isStarted() )
+//        {
+//            throw new ConfigurationException( "The server is not online! Cannot connect to it." );
+//        }
+
+        Hashtable<String, String> env = new Hashtable<String, String>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY, CTX_FACTORY);
+        env.put(Context.PROVIDER_URL, "ldap://localhost:" + port);
+        env.put(Context.SECURITY_PRINCIPAL, bindPrincipalDn);
+        env.put(Context.SECURITY_CREDENTIALS, password);
+        env.put(Context.SECURITY_AUTHENTICATION, "simple");
+        return new InitialLdapContext(env, null);
+    }
+
+
+    /**
+     * Get's the initial context factory for the provider's ou=system context
+     * root.
+     */
+    protected void setUp() throws Exception {
+        File cwd = new File("target", "apacheds");
+        doDelete(cwd);
+
+        directoryService = new DefaultDirectoryService();
+        directoryService.setShutdownHookEnabled(false);
+        directoryService.setInstanceLayout(new InstanceLayout(cwd));
+        directoryService.setSystemPartition(createSystemPartition(directoryService, cwd));
+
+
+        port = AvailablePortFinder.getNextAvailable(1024);
+        ldapServer = new LdapServer();
+        ldapServer.setTransports(new TcpTransport(port));
+        ldapServer.setDirectoryService(directoryService);
+
+        setupSaslMechanisms(ldapServer);
+
+        directoryService.startup();
+
+        ldapServer.addExtendedOperationHandler(new StartTlsHandler());
+        ldapServer.addExtendedOperationHandler(new StoredProcedureExtendedOperationHandler());
+
+        ldapServer.start();
+        setContexts(ServerDNConstants.ADMIN_SYSTEM_DN, "secret");
+    }
+
+    private JdbmPartition createSystemPartition(DirectoryService service,
+                                                final File workingDirectory) throws Exception {
+        JdbmPartitionFactory partitionFactory = new JdbmPartitionFactory();
+        JdbmPartition systemPartition = partitionFactory.createPartition(
+                service.getSchemaManager(),
+                service.getDnFactory(), "system", ServerDNConstants.SYSTEM_DN, 500,
+                new File(workingDirectory, "system"));
+        partitionFactory.addIndex(systemPartition, SchemaConstants.OBJECT_CLASS_AT, 100);
+        systemPartition.setSchemaManager(service.getSchemaManager());
+        return systemPartition;
+    }
+
+    private void setupSaslMechanisms(LdapServer server) {
+        Map<String, MechanismHandler> mechanismHandlerMap = new HashMap<String, MechanismHandler>();
+
+        mechanismHandlerMap.put(SupportedSaslMechanisms.PLAIN, new PlainMechanismHandler());
+
+        CramMd5MechanismHandler cramMd5MechanismHandler = new CramMd5MechanismHandler();
+        mechanismHandlerMap.put(SupportedSaslMechanisms.CRAM_MD5, cramMd5MechanismHandler);
+
+        DigestMd5MechanismHandler digestMd5MechanismHandler = new DigestMd5MechanismHandler();
+        mechanismHandlerMap.put(SupportedSaslMechanisms.DIGEST_MD5, digestMd5MechanismHandler);
+
+        GssapiMechanismHandler gssapiMechanismHandler = new GssapiMechanismHandler();
+        mechanismHandlerMap.put(SupportedSaslMechanisms.GSSAPI, gssapiMechanismHandler);
+
+        NtlmMechanismHandler ntlmMechanismHandler = new NtlmMechanismHandler();
+        // TODO - set some sort of default NtlmProvider implementation here
+        // ntlmMechanismHandler.setNtlmProvider( provider );
+        // TODO - or set FQCN of some sort of default NtlmProvider implementation here
+        // ntlmMechanismHandler.setNtlmProviderFqcn( "com.foo.BarNtlmProvider" );
+        mechanismHandlerMap.put(SupportedSaslMechanisms.NTLM, ntlmMechanismHandler);
+        mechanismHandlerMap.put(SupportedSaslMechanisms.GSS_SPNEGO, ntlmMechanismHandler);
+
+        ldapServer.setSaslMechanismHandlers(mechanismHandlerMap);
+    }
+
+
+    /**
+     * Deletes the Eve working directory.
+     *
+     * @param wkdir the directory to delete
+     * @throws IOException if the directory cannot be deleted
+     */
+    protected void doDelete(File wkdir) throws IOException {
+        if (doDelete) {
+            if (wkdir.exists()) {
+                FileUtils.deleteDirectory(wkdir);
+            }
+
+            if (wkdir.exists()) {
+                throw new IOException("Failed to delete: " + wkdir);
+            }
+        }
+    }
+
+
+    /**
+     * Sets the contexts for this base class.  Values of user and password used to
+     * set the respective JNDI properties.  These values can be overriden by the
+     * overrides properties.
+     *
+     * @param user   the username for authenticating as this user
+     * @param passwd the password of the user
+     * @throws NamingException if there is a failure of any kind
+     */
+    protected void setContexts(String user, String passwd) throws Exception {
+        Hashtable<String, Object> env = new Hashtable<String, Object>();
+        env.put(DirectoryService.JNDI_KEY, directoryService);
+        env.put(Context.SECURITY_PRINCIPAL, user);
+        env.put(Context.SECURITY_CREDENTIALS, passwd);
+        env.put(Context.SECURITY_AUTHENTICATION, "simple");
+        env.put(Context.INITIAL_CONTEXT_FACTORY, CoreContextFactory.class.getName());
+        setContexts(env);
+    }
+
+
+    /**
+     * Sets the contexts of this class taking into account the extras and overrides
+     * properties.
+     *
+     * @param env an environment to use while setting up the system root.
+     * @throws NamingException if there is a failure of any kind
+     */
+    protected void setContexts(Hashtable<String, Object> env) throws Exception {
+        Hashtable<String, Object> envFinal = new Hashtable<String, Object>(env);
+        envFinal.put(Context.PROVIDER_URL, ServerDNConstants.SYSTEM_DN);
+        sysRoot = new InitialLdapContext(envFinal, null);
+
+        envFinal.put(Context.PROVIDER_URL, "");
+        rootDSE = directoryService.getAdminSession();
+
+        envFinal.put(Context.PROVIDER_URL, ServerDNConstants.CN_SCHEMA_DN);
+        schemaRoot = new InitialLdapContext(envFinal, null);
+    }
+
+
+    /**
+     * Sets the system context root to null.
+     */
+    protected void tearDown() throws Exception {
+        ldapServer.stop();
+        try {
+            directoryService.shutdown();
+        } catch (Exception e) {
+        }
+
+        sysRoot = null;
+    }
+
+
+//    /**
+//     * Imports the LDIF entries packaged with the Eve JNDI provider jar into
+//     * the newly created system partition to prime it up for operation.  Note
+//     * that only ou=system entries will be added - entries for other partitions
+//     * cannot be imported and will blow chunks.
+//     *
+//     * @throws NamingException if there are problems reading the ldif file and
+//     * adding those entries to the system partition
+//     * @param in the input stream with the ldif
+//     */
+//    protected void importLdif( InputStream in ) throws NamingException
+//    {
+//        try
+//        {
+//            for ( LdifEntry ldifEntry:new LdifReader( in ) )
+//            {
+//                rootDSE.add(
+//                    new DefaultServerEntry(
+//                        rootDSE.getDirectoryService().getRegistries(), ldifEntry.getEntry() ) );
+//            }
+//        }
+//        catch ( Exception e )
+//        {
+//            String msg = "failed while trying to parse system ldif file";
+//            NamingException ne = new LdapConfigurationException( msg );
+//            ne.setRootCause( e );
+//            throw ne;
+//        }
+//    }
+//
+//
+}

Modified: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java?rev=1680714&r1=1680713&r2=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java Thu May 21 00:48:27 2015
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.oak.security.authentication.ldap;
 
-import java.io.File;
 import java.io.InputStream;
 
 import javax.naming.directory.BasicAttributes;
@@ -24,9 +23,8 @@ import javax.naming.directory.DirContext
 import javax.naming.ldap.LdapContext;
 
 import org.apache.directory.server.constants.ServerDNConstants;
-import org.apache.directory.server.unit.AbstractServerTest;
 
-class InternalLdapServer extends AbstractServerTest {
+class InternalLdapServer extends AbstractServer {
 
     public static final String GROUP_MEMBER_ATTR = "member";
     public static final String GROUP_CLASS_ATTR = "groupOfNames";
@@ -42,12 +40,6 @@ class InternalLdapServer extends Abstrac
         super.tearDown();
     }
 
-    @Override
-    protected void configureDirectoryService() throws Exception {
-        directoryService.setWorkingDirectory(new File("target", "apacheds"));
-        doDelete(directoryService.getWorkingDirectory());
-    }
-
     public int getPort() {
         return port;
     }

Modified: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java?rev=1680714&r1=1680713&r2=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderTest.java Thu May 21 00:48:27 2015
@@ -31,7 +31,6 @@ import org.apache.jackrabbit.oak.securit
 import org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapProviderConfig;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
 import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
 import org.apache.jackrabbit.util.Text;
@@ -58,7 +57,7 @@ public class LdapProviderTest {
 
     public static final String IDP_NAME = "ldap";
 
-    protected ExternalIdentityProvider idp;
+    protected LdapIdentityProvider idp;
 
     protected LdapProviderConfig providerConfig;
 
@@ -91,9 +90,11 @@ public class LdapProviderTest {
         if (!USE_COMMON_LDAP_FIXTURE) {
             LDAP_SERVER.tearDown();
         }
+        idp.close();
+        idp = null;
     }
 
-    protected ExternalIdentityProvider createIDP() {
+    protected LdapIdentityProvider createIDP() {
         providerConfig = new LdapProviderConfig()
                 .setName(IDP_NAME)
                 .setHostname("127.0.0.1")
@@ -173,6 +174,82 @@ public class LdapProviderTest {
     }
 
     @Test
+    public void testAuthenticateValidateFalseFalse() throws Exception {
+        providerConfig.getAdminPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(false);
+        providerConfig.getUserPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(false);
+        idp.close();
+        idp = new LdapIdentityProvider(providerConfig);
+
+        SimpleCredentials creds = new SimpleCredentials(TEST_USER1_UID, "pass".toCharArray());
+        for (int i=0; i<8; i++) {
+            ExternalUser user = idp.authenticate(creds);
+            assertNotNull("User 1 must authenticate", user);
+            assertEquals("User Ref", TEST_USER1_DN, user.getExternalId().getId());
+        }
+    }
+
+    @Test
+    public void testAuthenticateValidateFalseTrue() throws Exception {
+        providerConfig.getAdminPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(false);
+        providerConfig.getUserPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(true);
+        idp.close();
+        idp = new LdapIdentityProvider(providerConfig);
+
+        SimpleCredentials creds = new SimpleCredentials(TEST_USER1_UID, "pass".toCharArray());
+        for (int i=0; i<8; i++) {
+            ExternalUser user = idp.authenticate(creds);
+            assertNotNull("User 1 must authenticate", user);
+            assertEquals("User Ref", TEST_USER1_DN, user.getExternalId().getId());
+        }
+    }
+
+    @Test
+    public void testAuthenticateValidateTrueFalse() throws Exception {
+        providerConfig.getAdminPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(true);
+        providerConfig.getUserPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(false);
+        idp.close();
+        idp = new LdapIdentityProvider(providerConfig);
+
+        SimpleCredentials creds = new SimpleCredentials(TEST_USER1_UID, "pass".toCharArray());
+        for (int i=0; i<8; i++) {
+            ExternalUser user = idp.authenticate(creds);
+            assertNotNull("User 1 must authenticate (i=" + i + ")", user);
+            assertEquals("User Ref", TEST_USER1_DN, user.getExternalId().getId());
+        }
+    }
+
+    @Test
+    public void testAuthenticateValidateTrueTrue() throws Exception {
+        providerConfig.getAdminPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(true);
+        providerConfig.getUserPoolConfig()
+                .setMaxActive(2)
+                .setLookupOnValidate(true);
+        idp.close();
+        idp = new LdapIdentityProvider(providerConfig);
+
+        SimpleCredentials creds = new SimpleCredentials(TEST_USER1_UID, "pass".toCharArray());
+        for (int i=0; i<8; i++) {
+            ExternalUser user = idp.authenticate(creds);
+            assertNotNull("User 1 must authenticate (i=" + i + ")", user);
+            assertEquals("User Ref", TEST_USER1_DN, user.getExternalId().getId());
+        }
+    }
+
+    @Test
     public void testAuthenticateCaseInsensitive() throws Exception {
         SimpleCredentials creds = new SimpleCredentials(TEST_USER1_UID.toUpperCase(), "pass".toCharArray());
         ExternalUser user = idp.authenticate(creds);

Copied: jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/resources/logback-test.xml (from r1680577, jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/resources/logback-test.xml?p2=jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/resources/logback-test.xml&p1=jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml&r1=1680577&r2=1680714&rev=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml (original)
+++ jackrabbit/oak/branches/1.2/oak-auth-ldap/src/test/resources/logback-test.xml Thu May 21 00:48:27 2015
@@ -29,11 +29,14 @@
         </encoder>
     </appender>
 
+    <logger name="org.apache.directory.ldap" level="DEBUG" />
+    <logger name="org.apache.jackrabbit.oak.security.authentication.ldap" level="DEBUG" />
+
     <root level="INFO">
         <!--
-        <appender-ref ref="console"/>
-        -->
         <appender-ref ref="file"/>
+        -->
+        <appender-ref ref="console"/>
     </root>
 
 </configuration>

Modified: jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml?rev=1680714&r1=1680713&r2=1680714&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/test/resources/logback-test.xml Thu May 21 00:48:27 2015
@@ -1,39 +1,39 @@
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF 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.
-  -->
+        <!--
+           Licensed to the Apache Software Foundation (ASF) under one or more
+           contributor license agreements.  See the NOTICE file distributed with
+           this work for additional information regarding copyright ownership.
+           The ASF 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.
+          -->
 <configuration>
 
-    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder>
-            <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n</pattern>
-        </encoder>
-    </appender>
-
-    <appender name="file" class="ch.qos.logback.core.FileAppender">
-        <file>target/unit-tests.log</file>
-        <encoder>
-            <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n</pattern>
-        </encoder>
-    </appender>
-
-    <root level="INFO">
-        <!--
-        <appender-ref ref="console"/>
-        -->
-        <appender-ref ref="file"/>
-    </root>
+<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+        <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n</pattern>
+    </encoder>
+</appender>
+
+<appender name="file" class="ch.qos.logback.core.FileAppender">
+    <file>target/unit-tests.log</file>
+    <encoder>
+        <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n</pattern>
+    </encoder>
+</appender>
+
+<root level="INFO">
+    <!--
+    <appender-ref ref="console"/>
+    -->
+    <appender-ref ref="file"/>
+</root>
 
 </configuration>