Temporary injected some code which will make some tests to fail, as I'm currently merging the ads-mina2 branch into the trunk.

The breakage is not serious, though.

git-svn-id: https://svn.apache.org/repos/asf/directory/apacheds/branches/apacheds-mina2@725642 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/SearchHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/SearchHandler.java
index 6258045..9702bb6 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/SearchHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/SearchHandler.java
@@ -31,6 +31,7 @@
 import org.apache.directory.server.core.filtering.EntryFilteringCursor;
 import org.apache.directory.server.core.partition.PartitionNexus;
 import org.apache.directory.server.ldap.LdapSession;
+import org.apache.directory.server.ldap.handlers.controls.PagedSearchCookie;
 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
@@ -52,10 +53,12 @@
 import org.apache.directory.shared.ldap.message.SearchResponseReference;
 import org.apache.directory.shared.ldap.message.SearchResponseReferenceImpl;
 import org.apache.directory.shared.ldap.message.control.ManageDsaITControl;
+import org.apache.directory.shared.ldap.message.control.PagedSearchControl;
 import org.apache.directory.shared.ldap.message.control.PersistentSearchControl;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.util.LdapURL;
+import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,6 +67,7 @@
 
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
+import javax.naming.ldap.PagedResultsControl;
 
 
 /**
@@ -179,18 +183,18 @@
             
             while ( cursor.next() )
             {
-            	if ( hasRootDSE )
-            	{
-            		// This is an error ! We should never find more than one rootDSE !
-            	    LOG.error( "Got back more than one entry for search on RootDSE which means " +
-            	    		"Cursor is not functioning properly!" );
-            	}
-            	else
-            	{
-            		hasRootDSE = true;
-	                ClonedServerEntry entry = cursor.get();
-	                session.getIoSession().write( generateResponse( session, req, entry ) );
-            	}
+                if ( hasRootDSE )
+                {
+                    // This is an error ! We should never find more than one rootDSE !
+                    LOG.error( "Got back more than one entry for search on RootDSE which means " +
+                            "Cursor is not functioning properly!" );
+                }
+                else
+                {
+                    hasRootDSE = true;
+                    ClonedServerEntry entry = cursor.get();
+                    session.getIoSession().write( generateResponse( session, req, entry ) );
+                }
             }
     
             // write the SearchResultDone message
@@ -198,7 +202,7 @@
         }
         finally
         {
-        	// Close the cursor now.
+            // Close the cursor now.
             if ( cursor != null )
             {
                 try
@@ -282,7 +286,7 @@
         // Don't bother setting size limits for administrators that don't ask for it
         if ( session.getCoreSession().isAnAdministrator() && req.getSizeLimit() == NO_SIZE_LIMIT )
         {
-            return NO_SIZE_LIMIT;
+            return Integer.MAX_VALUE;
         }
         
         // Don't bother setting size limits for administrators that don't ask for it
@@ -298,7 +302,7 @@
          */
         if ( ldapService.getMaxSizeLimit() == NO_SIZE_LIMIT && req.getSizeLimit() == NO_SIZE_LIMIT )
         {
-            return NO_SIZE_LIMIT;
+            return Integer.MAX_VALUE;
         }
         
         /*
@@ -306,7 +310,7 @@
          * is configured to limit the search size then we limit by the max size
          * allowed by the configuration 
          */
-        if ( req.getSizeLimit() == 0 )
+        if ( req.getSizeLimit() == NO_SIZE_LIMIT )
         {
             return ldapService.getMaxSizeLimit();
         }
@@ -335,6 +339,95 @@
     }
     
     
+    private SearchResponseDone readResults( LdapSession session, SearchRequest req, 
+        LdapResult ldapResult,  EntryFilteringCursor cursor, int sizeLimit, boolean isPaged, 
+        PagedSearchCookie cookieInstance, PagedResultsControl pagedResultsControl ) throws Exception
+    {
+        req.addAbandonListener( new SearchAbandonListener( ldapService, cursor ) );
+        setTimeLimitsOnCursor( req, session, cursor );
+        LOG.debug( "using {} for size limit", sizeLimit );
+        int cookieValue = 0;
+        
+        int count = 0;
+        
+        while ( (count < sizeLimit ) && cursor.next() )
+        {
+            if ( session.getIoSession().isClosing() )
+            {
+                break;
+            }
+            
+            ClonedServerEntry entry = cursor.get();
+            session.getIoSession().write( generateResponse( session, req, entry ) );
+            count++;
+        }
+        
+        // DO NOT WRITE THE RESPONSE - JUST RETURN IT
+        ldapResult.setResultCode( ResultCodeEnum.SUCCESS );
+
+        if ( count < sizeLimit )
+        {
+            // That means we don't have anymore entry
+            if ( isPaged )
+            {
+                // If we are here, it means we have returned all the entries
+                // We have to remove the cookie from the session
+                cookieValue = cookieInstance.getCookieValue();
+                PagedSearchCookie psCookie = 
+                    (PagedSearchCookie)session.getIoSession().removeAttribute( cookieValue );
+                
+                // Close the cursor if there is one
+                if ( psCookie != null )
+                {
+                    cursor = psCookie.getCursor();
+                    
+                    if ( cursor != null )
+                    {
+                        cursor.close();
+                    }
+                }
+                
+                pagedResultsControl = new PagedResultsControl( 0, true );
+                req.getResultResponse().add( pagedResultsControl );
+            }
+
+            return ( SearchResponseDone ) req.getResultResponse();
+        }
+        else
+        {
+            // We have reached the limit
+            if ( isPaged )
+            {
+                // We stop here. We have to add a ResponseControl
+                // DO NOT WRITE THE RESPONSE - JUST RETURN IT
+                ldapResult.setResultCode( ResultCodeEnum.SUCCESS );
+                req.getResultResponse().add( pagedResultsControl );
+                
+                // Stores the cursor into the session
+                cookieInstance.setCursor( cursor );
+                return ( SearchResponseDone ) req.getResultResponse();
+            }
+            else
+            {
+                int serverLimit = session.getCoreSession().getDirectoryService().getMaxSizeLimit();
+                
+                if ( serverLimit == 0 )
+                {
+                    serverLimit = Integer.MAX_VALUE;
+                }
+                
+                // DO NOT WRITE THE RESPONSE - JUST RETURN IT
+                if ( count > serverLimit ) 
+                {
+                    // Special case if the user has requested more elements than the limit
+                    ldapResult.setResultCode( ResultCodeEnum.SIZE_LIMIT_EXCEEDED );
+                }
+                
+                return ( SearchResponseDone ) req.getResultResponse();
+            }
+        }
+    }
+    
     /**
      * Conducts a simple search across the result set returning each entry 
      * back except for the search response done.  This is calculated but not
@@ -349,68 +442,152 @@
     private SearchResponseDone doSimpleSearch( LdapSession session, SearchRequest req ) 
         throws Exception
     {
+        LdapResult ldapResult = req.getResultResponse().getLdapResult();
+        PagedResultsControl pagedResultsControl = null;
+        EntryFilteringCursor cursor = null;
+        int sizeLimit = getSearchSizeLimits( req, session );
+        boolean isPaged = false;
+        PagedSearchCookie cookieInstance = null;
+
+        // Check that the PagedSearchControl is present or not.
+        // Check if we are using the Paged Search Control
+        Object control = req.getControls().get( PagedSearchControl.CONTROL_OID );
+        PagedSearchControl pagedSearchControl = null;
+        
+        if ( control != null )
+        {
+            pagedSearchControl = ( PagedSearchControl )control;
+        }
+        
+        if ( pagedSearchControl != null )
+        {
+            // We have the following cases :
+            // 1) The SIZE is above the size-limit : the request is treated as if it
+            // was a simple search
+            // 2) The cookie is empty : this is a new request
+            // 3) The cookie is not empty, but the request is not the same : this is 
+            // a new request (we have to discard the cookie and do a new search from
+            // the beginning)
+            // 4) The cookie is not empty and the request is the same, we return
+            // the next SIZE elements
+            // 5) The SIZE is 0 and the cookie is the same than the previous one : this
+            // is a abandon request for this paged search.
+            int size = pagedSearchControl.getSize();
+            byte [] cookie= pagedSearchControl.getCookie();
+            
+            // Case 5
+            if ( size == 0 )
+            {
+                // Remove the cookie from the session, if it's not null
+                if ( !StringTools.isEmpty( cookie ) )
+                {
+                    int cookieValue = pagedSearchControl.getCookieValue();
+                    PagedSearchCookie psCookie = 
+                        (PagedSearchCookie)session.getIoSession().removeAttribute( cookieValue );
+                    pagedResultsControl = new PagedResultsControl( 0, psCookie.getCookie(), true );
+                    
+                    // Close the cursor
+                    cursor = psCookie.getCursor();
+                    
+                    if ( cursor != null )
+                    {
+                        cursor.close();
+                    }
+                }
+                else
+                {
+                    pagedResultsControl = new PagedResultsControl( 0, true );
+                }
+                
+                // and return
+                // DO NOT WRITE THE RESPONSE - JUST RETURN IT
+                ldapResult.setResultCode( ResultCodeEnum.SUCCESS );
+                req.getResultResponse().add( pagedResultsControl );
+                return ( SearchResponseDone ) req.getResultResponse();
+            }
+            
+            if ( sizeLimit < size )
+            {
+                // Case 1
+                cursor = session.getCoreSession().search( req );
+            }
+            else
+            {
+                isPaged = true;
+                sizeLimit = size;
+                
+                // Now, depending on the cookie, we will deal with case 2, 3 and 4
+                if ( StringTools.isEmpty( cookie ) )
+                {
+                    // Case 2 : create the cookie
+                    cookieInstance = new PagedSearchCookie( req );
+                    cookie = cookieInstance.getCookie();
+                    int cookieValue = cookieInstance.getCookieValue();
+
+                    session.getIoSession().setAttribute( cookieValue, cookieInstance );
+                    pagedResultsControl = new PagedResultsControl( 0, cookie, true );
+                }
+                else
+                {
+                    int cookieValue = pagedSearchControl.getCookieValue();
+                    cookieInstance = 
+                        (PagedSearchCookie)session.getIoSession().getAttribute( cookieValue );
+                    
+                    if ( cookieInstance.hasSameRequest( req, session ) )
+                    {
+                        // Case 4 : continue the search
+                        cursor = cookieInstance.getCursor();
+                        
+                        // get the cookie
+                        cookie = cookieInstance.getCookie();
+                        isPaged = true;
+                        sizeLimit = size;
+                        pagedResultsControl = new PagedResultsControl( 0, cookie, true );
+                    }
+                    else
+                    {
+                        // case 3 : create a new cursor
+                        // We have to close the cursor
+                        cursor = cookieInstance.getCursor();
+                        
+                        if ( cursor != null )
+                        {
+                            cursor.close();
+                        }
+                        
+                        // Now create a new cookie and stores it into the session
+                        cookieInstance = new PagedSearchCookie( req );
+                        cookie = cookieInstance.getCookie();
+                        cookieValue = cookieInstance.getCookieValue();
+
+                        session.getIoSession().setAttribute( cookieValue, cookieInstance );
+                        pagedResultsControl = new PagedResultsControl( 0, cookie, true );
+                    }
+                }
+            }
+        }
+        
+        // Check that we have a cursor or not. 
+        if ( cursor == null )
+        {
+            // No cursor : do a search.
+            cursor = session.getCoreSession().search( req );
+
+            // Position the cursor at the beginning
+            cursor.beforeFirst();
+        }
+        
         /*
          * Iterate through all search results building and sending back responses
          * for each search result returned.
          */
-        EntryFilteringCursor cursor = null;
-        
         try
         {
-            LdapResult ldapResult = req.getResultResponse().getLdapResult();
-            cursor = session.getCoreSession().search( req );
-            req.addAbandonListener( new SearchAbandonListener( ldapService, cursor ) );
-            setTimeLimitsOnCursor( req, session, cursor );
-            final int sizeLimit = getSearchSizeLimits( req, session );
-            LOG.debug( "using {} for size limit", sizeLimit );
-            
-            // Position the cursor at the beginning
-            cursor.beforeFirst();
-
-            if ( sizeLimit == NO_SIZE_LIMIT )
-            {
-                while ( cursor.next() )
-                {
-                    if ( session.getIoSession().isClosing() )
-                    {
-                        break;
-                    }
-                    ClonedServerEntry entry = cursor.get();
-                    Response response = generateResponse( session, req, entry );
-                    session.getIoSession().write( response );
-                }
-            }
-            else
-            {
-                int count = 0;
-                while ( cursor.next() )
-                {
-                    if ( session.getIoSession().isClosing() )
-                    {
-                        break;
-                    }
-                    if ( count < sizeLimit )
-                    {
-                        ClonedServerEntry entry = cursor.get();
-                        session.getIoSession().write( generateResponse( session, req, entry ) );
-                        count++;
-                    }
-                    else
-                    {
-                        // DO NOT WRITE THE RESPONSE - JUST RETURN IT
-                        ldapResult.setResultCode( ResultCodeEnum.SIZE_LIMIT_EXCEEDED );
-                        return ( SearchResponseDone ) req.getResultResponse();
-                    }  
-                }
-            }
-    
-            // DO NOT WRITE THE RESPONSE - JUST RETURN IT
-            ldapResult.setResultCode( ResultCodeEnum.SUCCESS );
-            return ( SearchResponseDone ) req.getResultResponse();
+            readResults( session, req, ldapResult, cursor, sizeLimit, isPaged, cookieInstance, pagedResultsControl );
         }
         finally
         {
-            if ( cursor != null )
+            if ( ( cursor != null ) && !isPaged )
             {
                 try
                 {
@@ -422,6 +599,8 @@
                 }
             }
         }
+        
+        return ( SearchResponseDone ) req.getResultResponse();
     }
     
 
@@ -598,9 +777,6 @@
 
         try
         {
-            // modify the filter to affect continuation support
-            modifyFilter( session, req );
-            
             // ===============================================================
             // Handle search in rootDSE differently.
             // ===============================================================
@@ -611,6 +787,9 @@
                 return;
             }
 
+            // modify the filter to affect continuation support
+            modifyFilter( session, req );
+            
             // ===============================================================
             // Handle psearch differently
             // ===============================================================
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
new file mode 100644
index 0000000..d5c4405
--- /dev/null
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/PagedSearchIT.java
@@ -0,0 +1,203 @@
+/*
+ *  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.directory.server.operations.search;
+
+ 
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.ReferralException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.Control;
+import javax.naming.ldap.LdapContext;
+import javax.naming.ldap.ManageReferralControl;
+import javax.naming.ldap.PagedResultsResponseControl;
+
+import org.apache.directory.server.core.entry.DefaultServerEntry;
+import org.apache.directory.server.core.integ.annotations.ApplyLdifs;
+import org.apache.directory.server.integ.SiRunner;
+
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContextThrowOnRefferal;
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;
+
+import org.apache.directory.server.ldap.LdapService;
+import org.apache.directory.shared.ldap.ldif.LdifEntry;
+import org.apache.directory.shared.ldap.ldif.LdifReader;
+import org.apache.directory.shared.ldap.message.control.PagedSearchControl;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+
+/**
+ * Test the PagedSearchControl
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 545029 $
+ */
+@RunWith ( SiRunner.class )
+@ApplyLdifs( {
+    // Add 10 new entries
+    "dn: dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: domain\n" +
+    "dc: users\n" +
+    "\n" +
+    "dn: cn=user0,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user0\n" +
+    "sn: user 0\n" +
+    "\n" +
+    "dn: cn=user1,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user1\n" +
+    "sn: user 1\n" +
+    "\n" +
+    "dn: cn=user2,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user2\n" +
+    "sn: user 2\n" +
+    "\n" +
+    "dn: cn=user3,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user3\n" +
+    "sn: user 3\n" +
+    "\n" +
+    "dn: cn=user4,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user4\n" +
+    "sn: user 4\n" +
+    "\n" +
+    "dn: cn=user5,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user5\n" +
+    "sn: user 5\n" +
+    "\n" +
+    "dn: cn=user6,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user6\n" +
+    "sn: user 6\n" +
+    "\n" +
+    "dn: cn=user7,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user7\n" +
+    "sn: user 7\n" +
+    "\n" +
+    "dn: cn=user8,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user8\n" +
+    "sn: user 8\n" +
+    "\n" +
+    "dn: cn=user9,dc=users,ou=system\n" +
+    "objectClass: top\n" +
+    "objectClass: person\n" +
+    "cn: user9\n" +
+    "sn: user 9\n" +
+    "\n"
+    }
+)
+public class PagedSearchIT
+{
+    public static LdapService ldapService;
+
+    
+    @Test
+    public void testSearchPagedSearch5Entries() throws Exception
+    {
+        DirContext ctx = getWiredContext( ldapService );
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        PagedSearchControl pagedSearchControl = new PagedSearchControl();
+        pagedSearchControl.setSize( 5 );
+
+        ((LdapContext)ctx).setRequestControls( new Control[] {pagedSearchControl} );
+        
+        NamingEnumeration<SearchResult> list = ctx.search( "dc=users,ou=system", "(cn=*)", controls );
+        
+        List<SearchResult> results = new ArrayList<SearchResult>();
+        
+        while ( list.hasMore() )
+        {
+            SearchResult result = list.next();
+            results.add( result );
+        }
+        
+        assertEquals( 5, results.size() );
+        
+        // check that we have correctly read the 5 first entries
+        for ( int i = 0; i < 5; i++ )
+        {
+            SearchResult entry = results.get( i );
+            assertEquals( "user" + i, entry.getAttributes().get( "cn" ).get() );
+        }
+        
+        // Now read the 5 next ones
+        Control[] responseControls = ((LdapContext)ctx).getResponseControls();
+        
+        PagedResultsResponseControl responseControl = (PagedResultsResponseControl)responseControls[0];
+        pagedSearchControl.setCookie( responseControl.getCookie() );
+        ((LdapContext)ctx).setRequestControls( new Control[] {pagedSearchControl} );
+        
+        list = ctx.search( "dc=users,ou=system", "(cn=*)", controls );
+        
+        results = new ArrayList<SearchResult>();
+        
+        while ( list.hasMore() )
+        {
+            SearchResult result = list.next();
+            results.add( result );
+        }
+        
+        assertEquals( 5, results.size() );
+        
+        // check that we have correctly read the 5 first entries
+        for ( int i = 5; i < 10; i++ )
+        {
+            SearchResult entry = results.get( i-5 );
+            assertEquals( "user" + i, entry.getAttributes().get( "cn" ).get() );
+        }
+        
+    }
+}
\ No newline at end of file
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchLimitsIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchLimitsIT.java
index ccf9cc8..24f4ce6 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchLimitsIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchLimitsIT.java
@@ -33,7 +33,10 @@
 import org.apache.directory.server.core.interceptor.context.SearchingOperationContext;
 import org.apache.directory.server.integ.SiRunner;
 import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 
 import org.apache.directory.server.ldap.LdapService;
 import org.junit.After;
@@ -200,7 +203,7 @@
         ldapService.setMaxTimeLimit( LdapService.NO_TIME_LIMIT );
         delayInterceptor.setDelayMillis( 500 );
         
-        getActorsWithLimit( "(objectClass=*)", 499, 0 );
+        getActorsWithLimit( "(objectClass=*)", 499, LdapService.NO_SIZE_LIMIT );
     }
     
 
@@ -215,7 +218,7 @@
         ldapService.setMaxTimeLimit( 10000 ); // this is in seconds
         delayInterceptor.setDelayMillis( 500 );
         
-        getActorsWithLimit( "(objectClass=*)", 499, 0 );
+        getActorsWithLimit( "(objectClass=*)", 499, LdapService.NO_SIZE_LIMIT );
     }
 
     
@@ -230,7 +233,7 @@
         ldapService.setMaxTimeLimit( 1 ); // this is in seconds
         delayInterceptor.setDelayMillis( 1100 );
         
-        getActorsWithLimit( "(objectClass=*)", 100000, 0 );
+        getActorsWithLimit( "(objectClass=*)", 100000, LdapService.NO_SIZE_LIMIT );
     }
 
     
@@ -244,7 +247,8 @@
         ldapService.setMaxTimeLimit( 1 ); // this is in seconds
         delayInterceptor.setDelayMillis( 500 );
         
-        getActorsWithLimit( "(objectClass=*)", 0, 0 );
+        getActorsWithLimit( "(objectClass=*)", 
+            LdapService.NO_TIME_LIMIT, LdapService.NO_SIZE_LIMIT );
     }
 
     
@@ -258,7 +262,8 @@
         ldapService.setMaxTimeLimit( 1 ); // this is in seconds
         delayInterceptor.setDelayMillis( 500 );
         
-        getActorsWithLimitNonAdmin( "(objectClass=*)", 0, 0 );
+        getActorsWithLimitNonAdmin( "(objectClass=*)", 
+            LdapService.NO_TIME_LIMIT, LdapService.NO_SIZE_LIMIT );
     }
     
     
@@ -272,11 +277,20 @@
      * by request size limit value to cause a size limit exceeded exception on
      * the client.
      */
-    @Test ( expected = SizeLimitExceededException.class )
+    @Test
     public void testRequestConstrainedUnlimitByConfigurationSize() throws Exception
     {
         ldapService.setMaxSizeLimit( LdapService.NO_SIZE_LIMIT );
-        getActorsWithLimit( "(objectClass=*)", 0,  1 );
+        
+        try
+        {
+            getActorsWithLimit( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 1 );
+            assertTrue( true );
+        }
+        catch ( SizeLimitExceededException slee )
+        {
+            fail();
+        }
     }
     
 
@@ -285,11 +299,19 @@
      * which constrains size by request size limit value to cause a size limit 
      * exceeded exception on the client.
      */
-    @Test ( expected = SizeLimitExceededException.class )
+    @Test
     public void testRequestConstrainedLessThanConfigurationSize() throws Exception
     {
         ldapService.setMaxSizeLimit( 10000 ); 
-        getActorsWithLimit( "(objectClass=*)", 0, 1 );
+
+        try
+        {
+            getActorsWithLimit( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 1 );
+        }
+        catch ( SizeLimitExceededException slee )
+        {
+            fail();
+        }
     }
 
 
@@ -302,7 +324,7 @@
     public void testRequestConstrainedGreaterThanConfigurationSize() throws Exception
     {
         ldapService.setMaxSizeLimit( 1 ); 
-        Set<String> set = getActorsWithLimit( "(objectClass=*)", 0, 100000 );
+        Set<String> set = getActorsWithLimit( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 100000 );
         assertEquals( 4, set.size() );
     }
 
@@ -312,11 +334,13 @@
      * which constrains size by using server max limit value to cause a size 
      * limit exceeded exception on the client.
      */
-    @Test ( expected = SizeLimitExceededException.class )
+    @Test (expected = SizeLimitExceededException.class ) 
     public void testNonAdminRequestConstrainedGreaterThanConfigurationSize() throws Exception
     {
         ldapService.setMaxSizeLimit( 1 ); 
-        getActorsWithLimitNonAdmin( "(objectClass=*)", 0, 100000 );
+        
+        // We are not using the admin : it should fail
+        getActorsWithLimitNonAdmin( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 100000 );
     }
 
     
@@ -328,7 +352,9 @@
     public void testRequestUnlimitedConfigurationLimitedSize() throws Exception
     {
         ldapService.setMaxSizeLimit( 1 ); 
-        Set<String> set = getActorsWithLimit( "(objectClass=*)", 0, 0 );
+        Set<String> set = getActorsWithLimit( "(objectClass=*)", 
+            LdapService.NO_TIME_LIMIT, LdapService.NO_SIZE_LIMIT );
+        
         assertEquals( 4, set.size() );
     }
 
@@ -340,8 +366,9 @@
     @Test ( expected = SizeLimitExceededException.class ) 
     public void testNonAdminRequestUnlimitedConfigurationLimitedSize() throws Exception
     {
-        ldapService.setMaxSizeLimit( 1 ); // this is in seconds
-        getActorsWithLimitNonAdmin( "(objectClass=*)", 0, 0 );
+        ldapService.setMaxSizeLimit( 1 );
+        getActorsWithLimitNonAdmin( "(objectClass=*)", 
+            LdapService.NO_TIME_LIMIT, LdapService.NO_SIZE_LIMIT );
     }
 
 
@@ -350,12 +377,18 @@
      * Sets up the server with unlimited search size limit but constrains size
      * by request size limit value. The request size limit is less than the
      * expected number of result entries, so exception expected.
+     * 
+     * cf RFC 4511 :
+     *  "sizeLimitExceeded (4)
+     *   Indicates that the size limit specified by the client was
+     *   exceeded before the operation could be completed."
      */
-    @Test(expected = SizeLimitExceededException.class)
+    @Test ( expected = SizeLimitExceededException.class )
     public void testRequestConstraintedLessThanExpectedSize() throws Exception
     {
         ldapService.setMaxSizeLimit( LdapService.NO_SIZE_LIMIT );
-        getActorsWithLimit( "(objectClass=*)", 0, 3 );
+        
+        getActorsWithLimit( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 3 );
     }
 
 
@@ -369,7 +402,7 @@
     public void testRequestConstraintedEqualToExpectedSize() throws Exception
     {
         ldapService.setMaxSizeLimit( LdapService.NO_SIZE_LIMIT );
-        Set<String> set = getActorsWithLimit( "(objectClass=*)", 0, 4 );
+        Set<String> set = getActorsWithLimit( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 4 );
         assertEquals( 4, set.size() );
     }
 
@@ -384,7 +417,7 @@
     public void testRequestConstraintedGreaterThanExpectedSize() throws Exception
     {
         ldapService.setMaxSizeLimit( LdapService.NO_SIZE_LIMIT );
-        Set<String> set = getActorsWithLimit( "(objectClass=*)", 0, 5 );
+        Set<String> set = getActorsWithLimit( "(objectClass=*)", LdapService.NO_TIME_LIMIT, 5 );
         assertEquals( 4, set.size() );
     }
 
@@ -406,7 +439,8 @@
         controls.setCountLimit( 1 );
         controls.setSearchScope( SearchControls.OBJECT_SCOPE );
 
-        NamingEnumeration<SearchResult> namingEnumeration = ctx.search( "ou=actors,ou=system", filter, controls );
+        NamingEnumeration<SearchResult> namingEnumeration = 
+            ctx.search( "ou=actors,ou=system", filter, controls );
         assertTrue( namingEnumeration.hasMore() );
         namingEnumeration.next();
         assertFalse( namingEnumeration.hasMore() );
@@ -418,6 +452,10 @@
     // -----------------------------------------------------------------------
     
     
+    /**
+     * Do a search request from the ou=actors,ou=system base, with a principal
+     * which is the administrator.
+     */
     private Set<String> getActorsWithLimit( String filter, int timeLimitMillis, int sizeLimit ) throws Exception
     {
         DirContext ctx = getWiredContext( ldapService );
@@ -427,7 +465,9 @@
         controls.setCountLimit( sizeLimit );
         controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
         
-        NamingEnumeration<SearchResult> namingEnumeration = ctx.search( "ou=actors,ou=system", filter, controls );
+        NamingEnumeration<SearchResult> namingEnumeration = 
+            ctx.search( "ou=actors,ou=system", filter, controls );
+        
         while( namingEnumeration.hasMore() )
         {
             results.add( namingEnumeration.next().getNameInNamespace() );
@@ -436,7 +476,10 @@
         return results;
     }
 
-    
+    /**
+     * Do a search request from the ou=actors,ou=system base, with a principal
+     * which is not the administrator.
+     */
     private Set<String> getActorsWithLimitNonAdmin( String filter, int timeLimitMillis, int sizeLimit ) 
         throws Exception
     {
@@ -447,7 +490,9 @@
         controls.setCountLimit( sizeLimit );
         controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
         
-        NamingEnumeration<SearchResult> namingEnumeration = ctx.search( "ou=actors,ou=system", filter, controls );
+        NamingEnumeration<SearchResult> namingEnumeration = 
+            ctx.search( "ou=actors,ou=system", filter, controls );
+        
         while( namingEnumeration.hasMore() )
         {
             results.add( namingEnumeration.next().getNameInNamespace() );