directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lucasthei...@apache.org
Subject svn commit: r1653145 [2/2] - in /directory/shared/trunk: asn1/api/ asn1/api/src/main/java/org/apache/directory/api/asn1/util/ asn1/api/src/test/java/org/apache/directory/api/asn1/util/ asn1/api/src/test/resources/ asn1/ber/src/main/java/org/apache/dire...
Date Mon, 19 Jan 2015 22:49:34 GMT
Added: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java?rev=1653145&view=auto
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java
(added)
+++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java
Mon Jan 19 22:49:33 2015
@@ -0,0 +1,36 @@
+
+package org.apache.directory.ldap.client.api;
+
+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;
+
+/**
+ * An implementation of {@link LdapConnectionValidator} that attempts a simple
+ * lookup on the rootDSE.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+final public class LookupLdapConnectionValidator implements LdapConnectionValidator
+{
+    /**
+     * 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.isAuthenticated()
+                && ( connection.lookup( Dn.ROOT_DSE, SchemaConstants.NO_ATTRIBUTE
) != null );
+        }
+        catch ( LdapException e )
+        {
+            return false;
+        }
+    }
+}
\ No newline at end of file

Propchange: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/LookupLdapConnectionValidator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java?rev=1653145&view=auto
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java
(added)
+++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java
Mon Jan 19 22:49:33 2015
@@ -0,0 +1,147 @@
+
+package org.apache.directory.ldap.client.api;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.util.Oid;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.BindResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.name.Dn;
+
+public final class MonitoringLdapConnection extends LdapConnectionWrapper
+{
+    private static final Oid START_TLS_OID;
+
+    
+    static 
+    {
+       try
+        {
+            START_TLS_OID = Oid.fromString( StartTlsRequest.EXTENSION_OID );
+        }
+        catch ( DecoderException e )
+        {
+            throw new IllegalStateException( "StartTlsRequest.EXTENSION_OID is not a valid
oid... This cant happen" );
+        }
+    }
+
+
+    private boolean bindCalled = false;
+    private boolean startTlsCalled = false;
+    
+    MonitoringLdapConnection( LdapConnection connection ) 
+    {
+        super( connection );
+    }
+    
+    public boolean bindCalled() {
+        return bindCalled;
+    }
+    
+    public void resetMonitors() {
+        bindCalled = false;
+        startTlsCalled = false;
+    }
+    
+    public boolean startTlsCalled() {
+        return startTlsCalled;
+    }
+
+    @Override
+    public void bind() throws LdapException
+    {
+        connection.bind();
+        bindCalled = true;
+    }
+
+    @Override
+    public void anonymousBind() throws LdapException
+    {
+        connection.anonymousBind();
+        bindCalled = true;
+    }
+
+    @Override
+    public void bind( String name ) throws LdapException
+    {
+        connection.bind( name );
+        bindCalled = true;
+    }
+
+    @Override
+    public void bind( String name, String credentials ) throws LdapException
+    {
+        connection.bind( name, credentials );
+        bindCalled = true;
+    }
+
+    @Override
+    public void bind( Dn name ) throws LdapException
+    {
+        connection.bind( name );
+        bindCalled = true;
+    }
+
+    @Override
+    public void bind( Dn name, String credentials ) throws LdapException
+    {
+        connection.bind( name, credentials );
+        bindCalled = true;
+    }
+
+    @Override
+    public BindResponse bind( BindRequest bindRequest ) throws LdapException
+    {
+        BindResponse response = connection.bind( bindRequest );
+        bindCalled = true;
+        return response;
+    }
+
+    @Override
+    public ExtendedResponse extended( String oid ) throws LdapException
+    {
+        if ( StartTlsRequest.EXTENSION_OID.equals( oid ) ) {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid );
+    }
+
+    @Override
+    public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
+    {
+        if ( StartTlsRequest.EXTENSION_OID.equals( oid ) ) {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid, value );
+    }
+
+    @Override
+    public ExtendedResponse extended( Oid oid ) throws LdapException
+    {
+        if ( START_TLS_OID.equals( oid ) ) {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid );
+    }
+
+    @Override
+    public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
+    {
+        if ( START_TLS_OID.equals( oid ) ) {
+            startTlsCalled = true;
+        }
+        return connection.extended( oid, value );
+    }
+
+    @Override
+    public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
+    {
+        if ( extendedRequest.hasControl( StartTlsRequest.EXTENSION_OID ) ) {
+            startTlsCalled = true;
+        }
+        return connection.extended( extendedRequest );
+    }
+}
\ No newline at end of file

Propchange: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/MonitoringLdapConnection.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java?rev=1653145&r1=1653144&r2=1653145&view=diff
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java
(original)
+++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactory.java
Mon Jan 19 22:49:33 2015
@@ -21,23 +21,38 @@
 package org.apache.directory.ldap.client.api;
 
 
-import java.io.IOException;
-
-import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.asn1.util.Oid;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 /**
- * A factory for creating LdapConnection objects managed by LdapConnectionPool. The connections
are validated
- * before being returned, which leads to a round-trip to the server. It also re-bind the
connection when
- * it's being put back to the pool, to reset the LDAPSession.
+ * A factory for creating LdapConnection objects managed by LdapConnectionPool. 
+ * A bind operation is executed upon return if any of the following operations 
+ * were performed on the connection while it was checked out:
+ * 
+ * <ul>
+ * <li>{@link LdapConnection#bind() bind()}</li>
+ * <li>{@link LdapConnection#anonymousBind() anonymousBind()}</li>
+ * <li>{@link LdapConnection#bind(String) bind(String)}</li>
+ * <li>{@link LdapConnection#bind(String, String) bind(String, String)}</li>
+ * <li>{@link LdapConnection#bind(Dn) bind(Dn)}</li>
+ * <li>{@link LdapConnection#bind(Dn, String) bind(Dn, String)}</li>
+ * <li>{@link LdapConnection#bind(BindRequest) bind(BindRequest)}</li>
+ * <li>{@link LdapConnection#extended(String) extended(String)} <i>where oid
is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(String, byte[]) extended(String, byte[])} <i>where
oid is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(Oid) extended(String)} <i>where oid is
StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(Oid, byte[]) extended(String, byte[])} <i>where
oid is StartTLS</i></li>
+ * <li>{@link LdapConnection#extended(ExtendedRequest) extended(ExtendedRequest)} <i>where
ExtendedRequest is StartTLS</i></li>
+ * </ul>
  * 
- * This is quite a costly - but secure - way to handle connections in a pool. If one would
like to use a 
- * less expensive pool factory, the {@link DefaultPoolableLdapConnectionFactory} is most
certainly a better
- * choice.
+ * This is a <i>MOSTLY</i> safe way to handle connections in a pool. If one 
+ * would like to use a slightly less expensive pool factory, the 
+ * {@link DefaultPoolableLdapConnectionFactory} may be the right choice.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -48,7 +63,7 @@ public class ValidatingPoolableLdapConne
 
 
     /**
-     * Creates a new instance of PoolableLdapConnectionFactory.
+     * Creates a new instance of ValidatingPoolableLdapConnectionFactory.
      *
      * @param config the configuration for creating LdapConnections
      */
@@ -59,74 +74,63 @@ public class ValidatingPoolableLdapConne
 
 
     /**
-     * Creates a new instance of PoolableLdapConnectionFactory.
+     * Creates a new instance of ValidatingPoolableLdapConnectionFactory.  The
+     * <code>connectionFactoryClass</code> must have a public constructor accepting
+     * an <code>LdapConnectionConfig</code> object or an 
+     * <code>IllegalArgumentException</code> will be thrown.
      *
-     * @param connectionFactory the connection factory for creating LdapConnections
+     * @param config the configuration for creating LdapConnections
+     * @param connectionFactoryClass An implementation class of for the 
+     * LDAP connection factory.
+     * @throws IllegalArgumentException If the instantiation of an instance of 
+     * the <code>connectionFactoryClass</code> fails.
      */
-    public ValidatingPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory
)
+    public ValidatingPoolableLdapConnectionFactory( LdapConnectionConfig config,
+        Class<? extends LdapConnectionFactory> connectionFactoryClass )
     {
-        this.connectionFactory = connectionFactory;
+        this( newLdapConnectionFactory( config, connectionFactoryClass ) );
     }
 
 
     /**
-     * {@inheritDoc}
-     * 
-     * There is nothing to do to activate a connection.
+     * Creates a new instance of ValidatingPoolableLdapConnectionFactory.
+     *
+     * @param connectionFactory the connection factory for creating LdapConnections
      */
-    public void activateObject( LdapConnection connection )
+    public ValidatingPoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory
)
     {
-        LOG.debug( "Activating {}", connection );
+        this.connectionFactory = connectionFactory;
     }
 
 
     /**
      * {@inheritDoc}
      * 
-     * Destroying a connection will unbind it which will result on a shutdown
-     * of teh underlying protocol.
+     * There is nothing to do to activate a connection.
      */
-    public void destroyObject( LdapConnection connection )
+    @Override
+    public void activateObject( LdapConnection connection ) throws LdapException
     {
-        LOG.debug( "Destroying {}", connection );
-
-        if ( connection.isConnected() )
-        {
-            try
-            {
-                connection.unBind();
-            }
-            catch ( LdapException e )
-            {
-                LOG.error( "unable to unbind connection: {}", e.getMessage() );
-                LOG.debug( "unable to unbind connection:", e );
-            }
-        }
+        LOG.debug( "Activating {}", connection );
+        super.activateObject( connection );
 
-        try
-        {
-            connection.close();
-        }
-        catch ( IOException e )
-        {
-            LOG.error( "unable to close connection: {}", e.getMessage() );
-            LOG.debug( "unable to close connection:", e );
-        }
+        // clear the monitors
+        ( ( MonitoringLdapConnection ) connection ).resetMonitors();
     }
 
 
     /**
      * {@inheritDoc}
+     * 
      * Specifically, we are creating a new connection based on the LdapConnection Factory
      * we used to create this pool of connections. The default is to create bound connections.
      * 
      * @throws LdapException If unable to connect.
      */
-    public LdapConnection makeObject() throws LdapException
+    public MonitoringLdapConnection makeObject() throws LdapException
     {
         LOG.debug( "Creating a LDAP connection" );
-
-        return connectionFactory.newLdapConnection();
+        return new MonitoringLdapConnection( connectionFactory.newLdapConnection() );
     }
 
 
@@ -142,55 +146,21 @@ public class ValidatingPoolableLdapConne
     {
         LOG.debug( "Passivating {}", connection );
 
-        // in case connection configuration was modified, or rebound to a
-        // different identity, we reinitialize before returning to the pool.
-        connectionFactory.bindConnection(
-            connectionFactory.configureConnection( connection ) );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     * 
-     * Validating a connection is done in depth : first we check that the connection is still
-     * up, that the LdapSession is authenticated, and that we can retrieve some information

-     * from the server. If the connection is not authenticated, we re-bind.
-     */
-    public boolean validateObject( LdapConnection connection )
-    {
-        LOG.debug( "Validating {}", connection );
-
-        if ( connection.isConnected() )
+        if ( !connection.isConnected() || !connection.isAuthenticated()
+            || ( ( MonitoringLdapConnection ) connection ).bindCalled() )
         {
-            if ( connection.isAuthenticated() )
-            {
-                try
-                {
-                    return connection.lookup( Dn.ROOT_DSE, SchemaConstants.NO_ATTRIBUTE )
!= null;
-                }
-                catch ( LdapException le )
-                {
-                    return false;
-                }
-            }
-            else
-            {
-                // We have to bind the connection
-                try
-                {
-                    connectionFactory.bindConnection( connection );
-
-                    return true;
-                }
-                catch ( LdapException le )
-                {
-                    return false;
-                }
-            }
+            LOG.debug( "rebind due to bind on connection {}", connection );
+            connectionFactory.bindConnection( connection );
         }
-        else
+        if ( ( ( MonitoringLdapConnection ) connection ).startTlsCalled() )
         {
-            return false;
+            LOG.debug( "unbind/rebind due to startTls on {}", connection );
+            // unbind to clear the tls
+            connection.unBind();
+            connectionFactory.bindConnection( connection );
         }
+
+        // in case connection had configuration changed
+        connectionFactory.configureConnection( connection );
     }
 }

Added: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java?rev=1653145&view=auto
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
(added)
+++ directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
Mon Jan 19 22:49:33 2015
@@ -0,0 +1,17 @@
+package org.apache.directory.ldap.client.api;
+
+/**
+ * An interface for defining wrapper objects.  An implementation of this class
+ * <b>MUST</b> implement <code>T</code> as well
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface Wrapper<T>
+{
+    /**
+     * Returns the wrapped object.
+     *
+     * @return The wrapped object
+     */
+    public T wrapped();
+}

Propchange: directory/shared/trunk/ldap/client/api/src/main/java/org/apache/directory/ldap/client/api/Wrapper.java
------------------------------------------------------------------------------
    svn:executable = *

Added: directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java?rev=1653145&view=auto
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java
(added)
+++ directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java
Mon Jan 19 22:49:33 2015
@@ -0,0 +1,35 @@
+package org.apache.directory.ldap.client.api;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.ldap.client.api.DefaultLdapConnectionFactory;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+
+public class MockLdapConnectionFactory extends DefaultLdapConnectionFactory 
+{
+    Queue<LdapConnection> connections = new LinkedList<LdapConnection>();
+    
+    public MockLdapConnectionFactory( LdapConnectionConfig config ) {
+        super( config );
+    }
+    
+    public MockLdapConnectionFactory addConnection( LdapConnection connection ) {
+        this.connections.add( connection );
+        return this;
+    }
+
+    @Override
+    public LdapConnection newLdapConnection() throws LdapException
+    {
+        return bindConnection( this.connections.remove() );
+    }
+
+    @Override
+    public LdapConnection newUnboundLdapConnection()
+    {
+        return this.connections.remove();
+    }
+}
\ No newline at end of file

Propchange: directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/MockLdapConnectionFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java?rev=1653145&view=auto
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java
(added)
+++ directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java
Mon Jan 19 22:49:33 2015
@@ -0,0 +1,517 @@
+package org.apache.directory.ldap.client.api;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import org.apache.directory.api.asn1.DecoderException;
+import org.apache.directory.api.asn1.util.Oid;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequest;
+import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.BindRequest;
+import org.apache.directory.api.ldap.model.message.BindRequestImpl;
+import org.apache.directory.api.ldap.model.message.BindResponse;
+import org.apache.directory.api.ldap.model.message.ExtendedRequest;
+import org.apache.directory.api.ldap.model.message.ExtendedResponse;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.verification.VerificationMode;
+
+
+public class ValidatingPoolableLdapConnectionFactoryTest
+{
+    private static final String ADMIN_CREDENTIALS = "secret";
+    private static final String ADMIN_DN = "uid=admin, ou=system";
+    private static final MockUtil MOCK_UTIL = new MockUtil();
+
+
+    @Test
+    public void testPoolWithBind()
+    {
+        PoolTester tester = new PoolTester();
+        
+        // no bind
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind()
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind();
+                    verify( connection, times( 1 ) ).bind();
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // anonymousBind()
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.anonymousBind();
+                    verify( connection, times( 1 ) ).anonymousBind();
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind( "" );
+                    verify( connection, times( 1 ) ).bind( "" );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // admin bind( String, String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind( ADMIN_DN, ADMIN_CREDENTIALS );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( String, String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.bind( "", "" );
+                    verify( connection, times( 1 ) ).bind( "", "" );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( Dn )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    Dn dn = new Dn();
+                    connection.bind( dn );
+                    verify( connection, times( 1 ) ).bind( dn );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( Dn, String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    Dn dn = new Dn();
+                    connection.bind( dn, "" );
+                    verify( connection, times( 1 ) ).bind( dn, "" );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+
+        // bind( BindRequest );
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    BindRequest bindRequest = new BindRequestImpl();
+                    connection.bind( bindRequest );
+                    verify( connection, times( 1 ) ).bind( bindRequest );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+    }
+
+
+    @Test
+    public void testPoolWithStartTls()
+    {
+        PoolTester tester = new PoolTester();
+        
+        // extended( String )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.extended( StartTlsRequest.EXTENSION_OID );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+        
+        // extended( String, byte[] )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.extended( StartTlsRequest.EXTENSION_OID, new byte[] {} );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+        
+        // extended( Oid )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    try
+                    {
+                        connection.extended( Oid.fromString( StartTlsRequest.EXTENSION_OID
) );
+                    }
+                    catch ( DecoderException e )
+                    {
+                        throw new IllegalArgumentException( "invalid oid: " + StartTlsRequest.EXTENSION_OID
);
+                    }
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+        
+        // extended( Oid, byte[] )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    try
+                    {
+                        connection.extended( Oid.fromString( StartTlsRequest.EXTENSION_OID
), new byte[] {} );
+                    }
+                    catch ( DecoderException e )
+                    {
+                        throw new IllegalArgumentException( "invalid oid: " + StartTlsRequest.EXTENSION_OID
);
+                    }
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+        
+        // extended( ExtendedRequest )
+        tester.execute(
+            new WithConnection()
+            {
+                @Override
+                public void execute( LdapConnection connection, Counts counts ) throws LdapException
+                {
+                    connection.extended( new StartTlsRequestImpl() );
+                    verifyAdminBind( connection, times( counts.adminBindCount ) );
+                }
+            } );
+    }
+
+
+    private static final void verifyAdminBind( LdapConnection connection, VerificationMode
mode ) throws LdapException
+    {
+        verify( connection, mode ).bind( ADMIN_DN, ADMIN_CREDENTIALS );
+    }
+    
+    
+    private static final LdapConnection verify( LdapConnection connection, VerificationMode
mode )
+    {
+        if ( MOCK_UTIL.isMock( connection ) )
+        {
+            return org.mockito.Mockito.verify( connection, mode );
+        }
+        else
+        {
+            if ( connection instanceof Wrapper )
+            {
+                @SuppressWarnings("unchecked")
+                LdapConnection unwrapped = ( ( Wrapper<LdapConnection> ) connection
).wrapped();
+                return verify( unwrapped, mode );
+            }
+        }
+        throw new NotAMockException( "connection is not a mock, nor a wrapper for a connection
that is one" );
+    }
+
+    private static final class Counts {
+        private int adminBindCount = 0;
+        private int unBindCount = 0;
+    }
+
+    public static final class InternalMonitoringLdapConnection extends LdapConnectionWrapper
+    {
+        private static final Oid START_TLS_OID;
+        
+        static
+        {
+            try
+            {
+                START_TLS_OID = Oid.fromString( StartTlsRequest.EXTENSION_OID );
+            }
+            catch ( DecoderException e )
+            {
+                throw new IllegalStateException( "StartTlsRequest.EXTENSION_OID is not a
valid oid...  IMPOSSIBLE" );
+            }
+        }
+
+        private int borrowedCount = 0;
+        private boolean bindCalled = false;
+        private Counts counts = new Counts();
+        private boolean startTlsCalled = false;
+        private boolean unBindCalled = false;
+        
+        InternalMonitoringLdapConnection( LdapConnection connection ) 
+        {
+            super( connection );
+        }
+        
+        private int incrementBorrowedCount() {
+            return ++borrowedCount;
+        }
+        
+        public boolean bindCalled() {
+            return bindCalled;
+        }
+        
+        public void resetMonitors() {
+            bindCalled = false;
+            startTlsCalled = false;
+            unBindCalled = false;
+        }
+        
+        public boolean startTlsCalled() {
+            return startTlsCalled;
+        }
+        
+        public boolean unBindCalled() {
+            return unBindCalled;
+        }
+
+        @Override
+        public void bind() throws LdapException
+        {
+            connection.bind();
+            bindCalled = true;
+        }
+
+        @Override
+        public void anonymousBind() throws LdapException
+        {
+            connection.anonymousBind();
+            bindCalled = true;
+        }
+
+        @Override
+        public void bind( String name ) throws LdapException
+        {
+            connection.bind( name );
+            bindCalled = true;
+        }
+
+        @Override
+        public void bind( String name, String credentials ) throws LdapException
+        {
+            connection.bind( name, credentials );
+            if ( ADMIN_DN.equals( name )
+                && ADMIN_CREDENTIALS.equals( credentials ) ) {
+                counts.adminBindCount++;
+            }
+            bindCalled = true;
+        }
+
+        @Override
+        public void bind( Dn name ) throws LdapException
+        {
+            connection.bind( name );
+            bindCalled = true;
+        }
+
+        @Override
+        public void bind( Dn name, String credentials ) throws LdapException
+        {
+            connection.bind( name, credentials );
+            bindCalled = true;
+        }
+
+        @Override
+        public BindResponse bind( BindRequest bindRequest ) throws LdapException
+        {
+            BindResponse response = connection.bind( bindRequest );
+            bindCalled = true;
+            return response;
+        }
+
+        @Override
+        public ExtendedResponse extended( String oid ) throws LdapException
+        {
+            if ( StartTlsRequest.EXTENSION_OID.equals( oid ) ) {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid );
+        }
+
+        @Override
+        public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
+        {
+            if ( StartTlsRequest.EXTENSION_OID.equals( oid ) ) {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid, value );
+        }
+
+        @Override
+        public ExtendedResponse extended( Oid oid ) throws LdapException
+        {
+            if ( START_TLS_OID.equals( oid ) ) {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid );
+        }
+
+        @Override
+        public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
+        {
+            if ( START_TLS_OID.equals( oid ) ) {
+                startTlsCalled = true;
+            }
+            return connection.extended( oid, value );
+        }
+
+        @Override
+        public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
+        {
+            if ( extendedRequest.hasControl( StartTlsRequest.EXTENSION_OID ) ) {
+                startTlsCalled = true;
+            }
+            return connection.extended( extendedRequest );
+        }
+        
+        @Override
+        public void unBind() throws LdapException {
+            counts.unBindCount++;
+            unBindCalled = true;
+            connection.unBind();
+        }
+    }
+    
+    
+    private static class PoolTester
+    {
+        private LdapConnectionConfig config;
+        private LdapConnectionPool pool;
+        private LdapConnectionValidator validator;
+
+
+        public PoolTester()
+        {
+            LdapConnection mockConnection = mock( LdapConnection.class );
+            when( mockConnection.isAuthenticated() ).thenReturn( true );
+            when( mockConnection.isConnected() ).thenReturn( true );
+
+            config = new LdapConnectionConfig();
+            config.setName( ADMIN_DN );
+            config.setCredentials( ADMIN_CREDENTIALS );
+
+            MockLdapConnectionFactory mockConnectionFactory = new MockLdapConnectionFactory(
config );
+            mockConnectionFactory.addConnection( 
+                new InternalMonitoringLdapConnection( mockConnection ) );
+
+            validator = mock( LdapConnectionValidator.class );
+            when( validator.validate( any( LdapConnection.class ) ) ).thenReturn( true );
+            ValidatingPoolableLdapConnectionFactory poolableFactory = 
+                new ValidatingPoolableLdapConnectionFactory( mockConnectionFactory );
+            poolableFactory.setValidator( validator );
+
+            pool = new LdapConnectionPool( poolableFactory );
+            pool.setMaxActive( 1 );
+            pool.setTestOnBorrow( true );
+            pool.setTestOnReturn( true );
+        }
+
+
+        public void execute( WithConnection withConnection )
+        {
+            LdapConnection connection = null;
+            InternalMonitoringLdapConnection internal = null;
+            int borrowedCount = 0;
+            try
+            {
+                connection = pool.getConnection();
+                assertNotNull( connection );
+                internal = (InternalMonitoringLdapConnection)((LdapConnectionWrapper)connection).wrapped();
+                borrowedCount = internal.incrementBorrowedCount();
+                org.mockito.Mockito.verify( validator, times( 2 * borrowedCount - 1 ) ).validate(
connection );
+                internal.resetMonitors();
+
+                withConnection.execute( connection, internal.counts );
+            }
+            catch ( LdapException e )
+            {
+                fail( "unable to getConnection(): " + e.getMessage() );
+            }
+            finally
+            {
+                try
+                {
+                    int adminBindCount = internal.counts.adminBindCount;
+                    pool.releaseConnection( connection );
+                    org.mockito.Mockito.verify( validator, times( 2 * borrowedCount ) ).validate(
connection );
+
+                    if ( internal.startTlsCalled() )
+                    {
+                        verify( connection, times( internal.counts.unBindCount ) ).unBind();
+                    }
+
+                    int expectedCount = internal.bindCalled() || internal.startTlsCalled()
|| internal.unBindCalled()
+                        ? adminBindCount + 1
+                        : adminBindCount;
+                    verifyAdminBind( connection, times( expectedCount ) );
+                }
+                catch ( LdapException e )
+                {
+                    fail( "unable to releaseConnection(): " + e.getMessage() );
+                }
+            }
+        }
+    }
+    
+    
+    private static interface WithConnection
+    {
+        /** 
+         * Executes code using the supplied connection.
+         * 
+         * @param connection The ldap connection
+         * @param counts The counters for specific calls
+         */
+        public void execute( LdapConnection connection, Counts counts ) throws LdapException;
+    }
+}

Propchange: directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/ValidatingPoolableLdapConnectionFactoryTest.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: directory/shared/trunk/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java?rev=1653145&r1=1653144&r2=1653145&view=diff
==============================================================================
--- directory/shared/trunk/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java
(original)
+++ directory/shared/trunk/ldap/codec/core/src/main/java/org/apache/directory/api/ldap/codec/actions/extendedResponse/StoreExtendedResponseName.java
Mon Jan 19 22:49:33 2015
@@ -85,7 +85,7 @@ public class StoreExtendedResponseName e
         }
         else
         {
-            String responseName = new Oid( Strings.asciiBytesToString( tlv.getValue().getData()
) )
+            String responseName = Oid.fromString( Strings.asciiBytesToString( tlv.getValue().getData()
) )
                 .toString();
 
             extendedResponse = LdapApiServiceFactory.getSingleton().newExtendedResponse(
responseName,

Modified: directory/shared/trunk/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java?rev=1653145&r1=1653144&r2=1653145&view=diff
==============================================================================
--- directory/shared/trunk/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java
(original)
+++ directory/shared/trunk/ldap/extras/codec-api/src/main/java/org/apache/directory/api/ldap/extras/extended/startTls/StartTlsRequest.java
Mon Jan 19 22:49:33 2015
@@ -24,12 +24,12 @@ import org.apache.directory.api.ldap.mod
 
 
 /**
- * The RFC 4511 StartTLS request
+ * The <a href="http://tools.ietf.org/html/rfc4511">RFC 4511</a> StartTLS request
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public interface StartTlsRequest extends ExtendedRequest
 {
-    /** The OID for the StartTLS extended operation request. */
-    String EXTENSION_OID = "1.3.6.1.4.1.1466.20037";
+    /** The OID string for the StartTLS extended operation request. */
+    static final String EXTENSION_OID = "1.3.6.1.4.1.1466.20037";
 }



Mime
View raw message