You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2008/08/04 09:46:40 UTC

svn commit: r682279 - in /directory/apacheds/branches/bigbang: protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/ server-integ/ server-integ/src/main/java/org/apache/directory/server/integ/ server-integ/src/test/java/org/apach...

Author: akarasulu
Date: Mon Aug  4 00:46:39 2008
New Revision: 682279

URL: http://svn.apache.org/viewvc?rev=682279&view=rev
Log:
adding code and tests to handle referrals in compare operations

Added:
    directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/
    directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/compare/
    directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/compare/CompareIT.java
Modified:
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewCompareHandler.java
    directory/apacheds/branches/bigbang/server-integ/.classpath
    directory/apacheds/branches/bigbang/server-integ/pom.xml
    directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/ServerIntegrationUtils.java
    directory/apacheds/branches/bigbang/server-integ/src/test/resources/log4j.properties

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewCompareHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewCompareHandler.java?rev=682279&r1=682278&r2=682279&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewCompareHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewCompareHandler.java Mon Aug  4 00:46:39 2008
@@ -20,13 +20,20 @@
 package org.apache.directory.server.newldap.handlers;
 
 
+import javax.naming.InvalidNameException;
+import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
-import javax.naming.ReferralException;
 
+import org.apache.directory.server.core.entry.ClonedServerEntry;
 import org.apache.directory.server.newldap.LdapSession;
+import org.apache.directory.shared.ldap.NotImplementedException;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Value;
 import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.message.CompareRequest;
 import org.apache.directory.shared.ldap.message.LdapResult;
+import org.apache.directory.shared.ldap.message.ManageDsaITControl;
 import org.apache.directory.shared.ldap.message.ReferralImpl;
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
 import org.apache.directory.shared.ldap.name.LdapDN;
@@ -46,13 +53,201 @@
 {
     private static final Logger LOG = LoggerFactory.getLogger( NewCompareHandler.class );
     
-
     /** Speedup for logs */
     private static final boolean IS_DEBUG = LOG.isDebugEnabled();
 
     
+    /**
+     * Main entry point for handler.
+     * 
+     * @see LdapRequestHandler#handle(LdapSession, org.apache.directory.shared.ldap.message.Request)
+     */
     public void handle( LdapSession session, CompareRequest req ) throws Exception
     {
+        LOG.debug( "Handling compare request: {}", req );
+        
+        if ( req.getControls().containsKey( ManageDsaITControl.CONTROL_OID ) )
+        {
+            LOG.debug( "ManageDsaITControl detected." );
+            handleIgnoringReferrals( session, req );
+        }
+        else
+        {
+            LOG.debug( "ManageDsaITControl NOT detected." );
+            handleWithReferrals( session, req );
+        }
+    }
+    
+    
+    /**
+     * Handles processing with referrals without ManageDsaIT control.
+     */
+    private void handleWithReferrals( LdapSession session, CompareRequest req )
+    {
+        LdapResult result = req.getResultResponse().getLdapResult();
+        ClonedServerEntry entry = null;
+
+        // -------------------------------------------------------------------
+        // Lookup Entry
+        // -------------------------------------------------------------------
+        
+        // try to lookup the entry but ignore exceptions when it does not   
+        // exist since entry may not exist but may have an ancestor that is a 
+        // referral - would rather attempt a lookup that fails then do check 
+        // for existence than have to do another lookup to get entry info
+
+        try
+        {
+            entry = session.getCoreSession().lookup( req.getName() );
+        }
+        catch ( NameNotFoundException e )
+        {
+            /* ignore */
+        }
+        catch ( Exception e )
+        {
+            /* serious and needs handling */
+            handleException( session, req, e );
+            return;
+        }
+        
+        // -------------------------------------------------------------------
+        // Handle Existing Entry
+        // -------------------------------------------------------------------
+        
+        if ( entry != null )
+        {
+            try
+            {
+                if ( entry.getOriginalEntry().contains( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.REFERRAL_OC ) )
+                {
+                    // -------------------------------------------------------
+                    // Entry IS Referral
+                    // -------------------------------------------------------
+         
+                    LOG.debug( "Entry is a referral: {}", entry );
+                    
+                    ReferralImpl refs = new ReferralImpl();
+                    result.setReferral( refs );
+                    result.setResultCode( ResultCodeEnum.REFERRAL );
+                    result.setErrorMessage( "Encountered referral attempting to handle compare request." );
+                    result.setMatchedDn( req.getName() );
+
+                    EntryAttribute refAttr = entry.getOriginalEntry().get( SchemaConstants.REF_AT );
+                    for ( Value<?> refval : refAttr )
+                    {
+                        refs.addLdapUrl( ( String ) refval.get() );
+                    }
+
+                    session.getIoSession().write( req.getResultResponse() );
+                    return;
+                }
+                else
+                {
+                    LOG.debug( "Entry is NOT a referral: {}", entry );
+                    handleIgnoringReferrals( session, req );
+                    return;
+                }
+            }
+            catch ( Exception e )
+            {
+                handleException( session, req, e );
+            }
+        }
+
+        // -------------------------------------------------------------------
+        // Handle Non-existing Entry
+        // -------------------------------------------------------------------
+        
+        // if the entry is null we still have to check for a referral ancestor
+        // also the referrals need to be adjusted based on the ancestor's ref
+        // values to yield the correct path to the entry to be compared in the
+        // target DSAs
+        
+        if ( entry == null )
+        {
+            ClonedServerEntry referralAncestor = null;
+            LdapDN lastMatchedDn = null;
+            LdapDN dn = ( LdapDN ) req.getName().clone();
+            
+            while ( ! dn.isEmpty() )
+            {
+                try
+                {
+                    referralAncestor = session.getCoreSession().lookup( dn );
+                    EntryAttribute oc = referralAncestor.getOriginalEntry().get( SchemaConstants.OBJECT_CLASS_AT );
+                    
+                    // make sure referral ancestor is really a referral if not
+                    // then we null it out so the proper handling can occur 
+                    // down below - the reason for this is because we want the
+                    // farthest ancestor, not the closest one.
+                    
+                    if ( ! oc.contains( SchemaConstants.REFERRAL_OC ) )
+                    {
+                        referralAncestor = null;
+                    }
+
+                    // set last matched DN only if not set yet because we want 
+                    // the closest ancestor for this value regardless of what 
+                    // kind of entry (referral or normal) it is.
+                    
+                    if ( lastMatchedDn == null )
+                    {
+                        lastMatchedDn = ( LdapDN ) dn.clone();
+                    }
+                }
+                catch ( NameNotFoundException e )
+                {
+                    // update the DN as we strip last component 
+                    try
+                    {
+                        dn = ( LdapDN ) dn.remove( dn.size() - 1 );
+                    }
+                    catch ( InvalidNameException e1 )
+                    {
+                        // never happens
+                    }
+                }
+                catch ( Exception e )
+                {
+                    handleException( session, req, e );
+                }
+            }
+
+            if ( referralAncestor == null )
+            {
+                result.setMatchedDn( lastMatchedDn );
+                result.setErrorMessage( "Entry not found." );
+                result.setResultCode( ResultCodeEnum.NO_SUCH_OBJECT );
+                session.getIoSession().write( req.getResultResponse() );
+                return;
+            }
+              
+            // if we get here then we have a valid referral ancestor
+            handleReferralOnAncestor( session, req, referralAncestor );
+        }
+    }
+
+    
+    /**
+     * Handles processing with referrals without ManageDsaIT control and with 
+     * an ancestor that is a referral.  The original entry was not found and 
+     * the walk of the ancestry returned a referral.
+     * 
+     * @param referralAncestor the farthest referral ancestor of the missing 
+     * entry  
+     */
+    public void handleReferralOnAncestor( LdapSession session, CompareRequest req, ClonedServerEntry referralAncestor )
+    {
+        throw new NotImplementedException();
+    }
+    
+    
+    /**
+     * Handles processing without referrals with the ManageDsaIT control.
+     */
+    public void handleIgnoringReferrals( LdapSession session, CompareRequest req )
+    {
         LdapResult result = req.getResultResponse().getLdapResult();
 
         try
@@ -69,58 +264,54 @@
             result.setMatchedDn( req.getName() );
             session.getIoSession().write( req.getResultResponse() );
         }
-        catch ( ReferralException e )
+        catch ( Exception e )
         {
-            ReferralImpl refs = new ReferralImpl();
-            result.setReferral( refs );
-            result.setResultCode( ResultCodeEnum.REFERRAL );
-            result.setErrorMessage( "Encountered referral attempting to handle compare request." );
+            handleException( session, req, e );
+        }
+    }
+    
+    
+    /**
+     * Handles processing with referrals without ManageDsaIT control.
+     */
+    private void handleException( LdapSession session, CompareRequest req, Exception e )
+    {
+        LdapResult result = req.getResultResponse().getLdapResult();
 
-            result.setMatchedDn( (LdapDN)e.getResolvedName() );
+        String msg = "failed to compare entry " + req.getName() + ": " + e.getMessage();
+        LOG.error( msg, e );
 
-            do
-            {
-                refs.addLdapUrl( ( String ) e.getReferralInfo() );
-            }
-            while ( e.skipReferral() );
-            session.getIoSession().write( req.getResultResponse() );
-        }
-        catch ( Exception e )
+        if ( IS_DEBUG )
         {
-            String msg = "failed to compare entry " + req.getName() + ": " + e.getMessage();
+            msg += ":\n" + ExceptionUtils.getStackTrace( e );
+        }
 
-            if ( IS_DEBUG )
-            {
-                msg += ":\n" + ExceptionUtils.getStackTrace( e );
-            }
+        ResultCodeEnum code;
 
-            ResultCodeEnum code;
+        if ( e instanceof LdapException )
+        {
+            code = ( ( LdapException ) e ).getResultCode();
+        }
+        else
+        {
+            code = ResultCodeEnum.getBestEstimate( e, req.getType() );
+        }
 
-            if ( e instanceof LdapException )
-            {
-                code = ( ( LdapException ) e ).getResultCode();
-            }
-            else
-            {
-                code = ResultCodeEnum.getBestEstimate( e, req.getType() );
-            }
+        result.setResultCode( code );
+        result.setErrorMessage( msg );
 
-            result.setResultCode( code );
-            result.setErrorMessage( msg );
+        if ( e instanceof NamingException )
+        {
+            NamingException ne = ( NamingException ) e;
 
-            if ( e instanceof NamingException )
+            if ( ( ne.getResolvedName() != null )
+                && ( ( code == ResultCodeEnum.NO_SUCH_OBJECT ) || ( code == ResultCodeEnum.ALIAS_PROBLEM )
+                    || ( code == ResultCodeEnum.INVALID_DN_SYNTAX ) || ( code == ResultCodeEnum.ALIAS_DEREFERENCING_PROBLEM ) ) )
             {
-                NamingException ne = ( NamingException ) e;
-
-                if ( ( ne.getResolvedName() != null )
-                    && ( ( code == ResultCodeEnum.NO_SUCH_OBJECT ) || ( code == ResultCodeEnum.ALIAS_PROBLEM )
-                        || ( code == ResultCodeEnum.INVALID_DN_SYNTAX ) || ( code == ResultCodeEnum.ALIAS_DEREFERENCING_PROBLEM ) ) )
-                {
-                    result.setMatchedDn( (LdapDN)ne.getResolvedName() );
-                }
+                result.setMatchedDn( (LdapDN)ne.getResolvedName() );
             }
-
-            session.getIoSession().write( req.getResultResponse() );
         }
+
+        session.getIoSession().write( req.getResultResponse() );
     }
 }
\ No newline at end of file

Modified: directory/apacheds/branches/bigbang/server-integ/.classpath
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/server-integ/.classpath?rev=682279&r1=682278&r2=682279&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/server-integ/.classpath (original)
+++ directory/apacheds/branches/bigbang/server-integ/.classpath Mon Aug  4 00:46:39 2008
@@ -48,6 +48,7 @@
       <attribute value="jar:file:/home/akarasulu/ramdisk/.m2/repository/junit/junit/4.4/junit-4.4-javadoc.jar!/" name="javadoc_location"/>
     </attributes>
   </classpathentry>
+  <classpathentry kind="var" path="M2_REPO/ldapsdk/ldapsdk/4.1/ldapsdk-4.1.jar"/>
   <classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.14/log4j-1.2.14.jar" sourcepath="M2_REPO/log4j/log4j/1.2.14/log4j-1.2.14-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/mina/mina-core/1.1.6/mina-core-1.1.6.jar" sourcepath="M2_REPO/org/apache/mina/mina-core/1.1.6/mina-core-1.1.6-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/mina/mina-filter-ssl/1.1.6/mina-filter-ssl-1.1.6.jar" sourcepath="M2_REPO/org/apache/mina/mina-filter-ssl/1.1.6/mina-filter-ssl-1.1.6-sources.jar"/>

Modified: directory/apacheds/branches/bigbang/server-integ/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/server-integ/pom.xml?rev=682279&r1=682278&r2=682279&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/server-integ/pom.xml (original)
+++ directory/apacheds/branches/bigbang/server-integ/pom.xml Mon Aug  4 00:46:39 2008
@@ -66,6 +66,11 @@
     </dependency>  
 
     <dependency>
+      <groupId>ldapsdk</groupId>
+      <artifactId>ldapsdk</artifactId>
+    </dependency>  
+
+    <dependency>
       <groupId>org.apache.directory.server</groupId>
       <artifactId>apacheds-bootstrap-partition</artifactId>
       <version>${pom.version}</version>

Modified: directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/ServerIntegrationUtils.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/ServerIntegrationUtils.java?rev=682279&r1=682278&r2=682279&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/ServerIntegrationUtils.java (original)
+++ directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/ServerIntegrationUtils.java Mon Aug  4 00:46:39 2008
@@ -26,6 +26,8 @@
 import javax.naming.ldap.InitialLdapContext;
 import javax.naming.ldap.LdapContext;
 
+import netscape.ldap.LDAPConnection;
+
 import org.apache.directory.server.constants.ServerDNConstants;
 import org.apache.directory.server.core.integ.IntegrationUtils;
 import org.apache.directory.server.newldap.LdapServer;
@@ -39,6 +41,12 @@
     private static final Logger LOG = LoggerFactory.getLogger( ServerIntegrationUtils.class );
     private static final String CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
 
+    private static final String DEFAULT_HOST = "localhost";
+    private static final int DEFAULT_PORT = 10389;
+    private static final String DEFAULT_ADMIN = ServerDNConstants.ADMIN_SYSTEM_DN;
+    private static final String DEFAULT_PASSWORD = "secret";
+
+
 
     /**
      * Creates a JNDI LdapContext with a connection over the wire using the 
@@ -75,4 +83,88 @@
         env.put( Context.SECURITY_AUTHENTICATION, "simple" );
         return new InitialLdapContext( env, controls );
     }
+
+    
+    /**
+     * Creates a JNDI LdapContext with a connection over the wire using the 
+     * SUN LDAP provider.  The connection is made using the administrative 
+     * user as the principalDN.  The context is to the rootDSE.
+     *
+     * @param ldapServer the LDAP server to get the connection to
+     * @return an LdapContext as the administrative user to the RootDSE
+     * @throws Exception if there are problems creating the context
+     */
+    public static LdapContext getWiredContextThrowOnRefferal( LdapServer ldapServer ) throws Exception
+    {
+        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getIpPort() );
+        Hashtable<String, String> env = new Hashtable<String, String>();
+        env.put( Context.INITIAL_CONTEXT_FACTORY, CTX_FACTORY );
+        env.put( Context.PROVIDER_URL, "ldap://localhost:" + ldapServer.getIpPort() );
+        env.put( Context.SECURITY_PRINCIPAL, ServerDNConstants.ADMIN_SYSTEM_DN );
+        env.put( Context.SECURITY_CREDENTIALS, "secret" );
+        env.put( Context.SECURITY_AUTHENTICATION, "simple" );
+        env.put( Context.REFERRAL, "throw" );
+        return new InitialLdapContext( env, null );
+    }
+
+    
+    /**
+     * Creates a JNDI LdapContext with a connection over the wire using the 
+     * SUN LDAP provider.  The connection is made using the administrative 
+     * user as the principalDN.  The context is to the rootDSE.
+     *
+     * @param ldapServer the LDAP server to get the connection to
+     * @return an LdapContext as the administrative user to the RootDSE
+     * @throws Exception if there are problems creating the context
+     */
+    public static LdapContext getWiredContextFollowOnRefferal( LdapServer ldapServer ) throws Exception
+    {
+        LOG.debug( "Creating a wired context to local LDAP server on port {}", ldapServer.getIpPort() );
+        Hashtable<String, String> env = new Hashtable<String, String>();
+        env.put( Context.INITIAL_CONTEXT_FACTORY, CTX_FACTORY );
+        env.put( Context.PROVIDER_URL, "ldap://localhost:" + ldapServer.getIpPort() );
+        env.put( Context.SECURITY_PRINCIPAL, ServerDNConstants.ADMIN_SYSTEM_DN );
+        env.put( Context.SECURITY_CREDENTIALS, "secret" );
+        env.put( Context.SECURITY_AUTHENTICATION, "simple" );
+        env.put( Context.REFERRAL, "follow" );
+        return new InitialLdapContext( env, null );
+    }
+
+    
+    public static LDAPConnection getWiredConnection( LdapServer ldapServer ) throws Exception
+    {
+        String testServer = System.getProperty( "ldap.test.server", null );
+        
+        if ( testServer == null )
+        {
+            return getWiredConnection( ldapServer, ServerDNConstants.ADMIN_SYSTEM_DN, "secret" );
+        }
+        
+        LOG.debug( "ldap.test.server = " + testServer );
+        
+        String admin = System.getProperty( testServer + ".admin", DEFAULT_ADMIN );
+        LOG.debug( testServer + ".admin = " + admin );
+
+        String password = System.getProperty( testServer + ".password", DEFAULT_PASSWORD );
+        LOG.debug( testServer + ".password = " + password );
+
+        String host = System.getProperty( testServer + ".host", DEFAULT_HOST );
+        LOG.debug( testServer + ".host = " + host );
+
+        int port = Integer.parseInt( System.getProperty( testServer + ".port", Integer.toString( DEFAULT_PORT ) ) );
+        LOG.debug( testServer + ".port = " + port );
+        
+        LDAPConnection conn = new LDAPConnection();
+        conn.connect( 3, host, port, admin, password );
+        return conn;
+    }
+
+    
+    public static LDAPConnection getWiredConnection( LdapServer ldapServer, String principalDn, String password ) 
+        throws Exception
+    {
+        LDAPConnection conn = new LDAPConnection();
+        conn.connect( 3, "localhost", ldapServer.getIpPort(), principalDn, password );
+        return conn;
+    }
 }

Added: directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/compare/CompareIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/compare/CompareIT.java?rev=682279&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/compare/CompareIT.java (added)
+++ directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/compare/CompareIT.java Mon Aug  4 00:46:39 2008
@@ -0,0 +1,278 @@
+/*
+ *   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.compare;
+
+
+import javax.naming.NamingEnumeration;
+import javax.naming.ReferralException;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.LdapContext;
+
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPConstraints;
+import netscape.ldap.LDAPControl;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPResponse;
+import netscape.ldap.LDAPResponseListener;
+
+import org.apache.directory.server.core.integ.Level;
+import org.apache.directory.server.core.integ.annotations.ApplyLdifs;
+import org.apache.directory.server.core.integ.annotations.CleanupLevel;
+import org.apache.directory.server.integ.SiRunner;
+import org.apache.directory.server.newldap.LdapServer;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredConnection;
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContextThrowOnRefferal;
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContextFollowOnRefferal;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+
+/**
+ * Tests the server to make sure standard compare operations work properly.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@RunWith ( SiRunner.class ) 
+@CleanupLevel ( Level.SUITE )
+@ApplyLdifs( {
+    // Entry # 1
+    "dn: uid=akarasulu,ou=users,ou=system\n" +
+    "objectClass: uidObject\n" +
+    "objectClass: person\n" +
+    "objectClass: top\n" +
+    "uid: akarasulu\n" +
+    "cn: Alex Karasulu\n" +
+    "sn: karasulu\n\n" + 
+    // Entry # 2
+    "dn: uid=akarasuluref,ou=users,ou=system\n" +
+    "objectClass: uidObject\n" +
+    "objectClass: referral\n" +
+    "objectClass: top\n" +
+    "uid: akarasuluref\n" +
+    "ref: ldap://localhost:10389/uid=akarasulu,ou=users,ou=system\n" + 
+    "ref: ldap://foo:10389/uid=akarasulu,ou=users,ou=system\n" +
+    "ref: ldap://bar:10389/uid=akarasulu,ou=users,ou=system\n\n" 
+    }
+)
+public class CompareIT
+{
+    private static final Logger LOG = LoggerFactory.getLogger( CompareIT.class );
+    
+    public static LdapServer ldapServer;
+    
+
+    /**
+     * Tests normal compare operation on normal non-referral entries without 
+     * the ManageDsaIT control.
+     */
+    @Test
+    public void testNormalCompare() throws Exception
+    {
+        LDAPConnection conn = getWiredConnection( ldapServer );
+        
+        // comparison success
+        LDAPAttribute attribute = new LDAPAttribute( "sn", "karasulu" );
+        assertTrue( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute ) );
+
+        // comparison failure
+        attribute = new LDAPAttribute( "sn", "lecharny" );
+        assertFalse( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute ) );
+        
+        conn.disconnect();
+    }
+    
+    
+    /**
+     * Tests normal compare operation on normal non-referral entries without 
+     * the ManageDsaIT control using an attribute that does not exist in the
+     * entry.
+     */
+    @Test
+    public void testNormalCompareMissingAttribute() throws Exception
+    {
+        LDAPConnection conn = getWiredConnection( ldapServer );
+        
+        // comparison success
+        LDAPAttribute attribute = new LDAPAttribute( "sn", "karasulu" );
+        assertTrue( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute ) );
+
+        // non-existing attribute
+        attribute = new LDAPAttribute( "mail", "akarasulu@apache.org" );
+        
+        try
+        {
+            conn.compare( "uid=akarasulu,ou=users,ou=system", attribute );
+            fail( "Should never get here" );
+        }
+        catch ( LDAPException e )
+        {
+            assertEquals( ResultCodeEnum.NO_SUCH_ATTRIBUTE.getValue(), e.getLDAPResultCode() ); 
+        }
+        
+        conn.disconnect();
+    }
+    
+    
+    /**
+     * Tests compare operation on referral entry with the ManageDsaIT control.
+     */
+    @Test
+    public void testOnReferralWithManageDsaITControl() throws Exception
+    {
+        LDAPConnection conn = getWiredConnection( ldapServer );
+        LDAPConstraints constraints = new LDAPConstraints();
+        constraints.setClientControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
+        constraints.setServerControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
+        conn.setConstraints( constraints );
+        
+        // comparison success
+        LDAPAttribute attribute = new LDAPAttribute( "uid", "akarasuluref" );
+        assertTrue( conn.compare( "uid=akarasuluref,ou=users,ou=system", attribute, constraints ) );
+
+        // comparison failure
+        attribute = new LDAPAttribute( "uid", "elecharny" );
+        assertFalse( conn.compare( "uid=akarasuluref,ou=users,ou=system", attribute, constraints ) );
+        
+        conn.disconnect();
+    }
+    
+    
+    /**
+     * Tests compare operation on normal and referral entries without the 
+     * ManageDsaIT control. Referrals are sent back to the client with a
+     * non-success result code.
+     */
+    @Test
+    public void testOnReferral() throws Exception
+    {
+        LDAPConnection conn = getWiredConnection( ldapServer );
+        LDAPConstraints constraints = new LDAPConstraints();
+        constraints.setReferrals( false );
+        conn.setConstraints( constraints );
+        
+        // comparison success
+        LDAPAttribute attribute = new LDAPAttribute( "uid", "akarasulu" );
+        assertTrue( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute, constraints ) );
+
+        // referrals failure
+        attribute = new LDAPAttribute( "uid", "akarasulu" );
+        LDAPResponseListener listener = null;
+        LDAPResponse response = null;
+
+        listener = conn.compare( "uid=akarasuluref,ou=users,ou=system", attribute, null, constraints );
+        response = listener.getResponse();
+        assertEquals( ResultCodeEnum.REFERRAL.getValue(), response.getResultCode() );
+
+        assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[0] );
+        assertEquals( "ldap://foo:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[1] );
+        assertEquals( "ldap://bar:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[2] );
+
+        conn.disconnect();
+    }
+    
+    
+    /**
+     * Tests compare operation on normal and referral entries without the 
+     * ManageDsaIT control using JNDI instead of the Netscape API. Referrals 
+     * are sent back to the client with a non-success result code.
+     */
+    @Test
+    public void testThrowOnReferralWithJndi() throws Exception
+    {
+        LdapContext ctx = getWiredContextThrowOnRefferal( ldapServer );
+        SearchControls controls = new SearchControls();
+        controls.setReturningAttributes( new String[0] );
+        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
+        
+        // comparison success
+        NamingEnumeration<SearchResult> answer = ctx.search( "uid=akarasulu,ou=users,ou=system", 
+            "(uid=akarasulu)", controls );
+        assertTrue( answer.hasMore() );
+        SearchResult result = answer.next();
+        assertEquals( "", result.getName() );
+        assertEquals( 0, result.getAttributes().size() );
+        assertFalse( answer.hasMore() );
+        answer.close();
+
+        // referrals failure
+        try
+        {
+            answer = ctx.search( "uid=akarasuluref,ou=users,ou=system", 
+                "(uid=akarasuluref)", controls );
+            fail( "Should never get here" );
+        }
+        catch ( ReferralException e )
+        {
+            // seems JNDI only returns the first referral URL and not all so we test for it
+            assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", e.getReferralInfo() );
+        }
+
+        ctx.close();
+    }
+    
+    
+    /**
+     * Tests compare operation on normal and referral entries without the 
+     * ManageDsaIT control using JNDI while chasing referrals instead of 
+     * the Netscape API. Referrals are sent back to the client with a 
+     * non-success result code.
+     */
+    @Test
+    public void testFollowOnReferralWithJndi() throws Exception
+    {
+        LdapContext ctx = getWiredContextFollowOnRefferal( ldapServer );
+        SearchControls controls = new SearchControls();
+        controls.setReturningAttributes( new String[0] );
+        controls.setSearchScope( SearchControls.OBJECT_SCOPE );
+        
+        // comparison success
+        NamingEnumeration<SearchResult> answer = ctx.search( "uid=akarasulu,ou=users,ou=system", 
+            "(uid=akarasulu)", controls );
+        assertTrue( answer.hasMore() );
+        SearchResult result = answer.next();
+        assertEquals( "", result.getName() );
+        assertEquals( 0, result.getAttributes().size() );
+        assertFalse( answer.hasMore() );
+        answer.close();
+
+        // referrals follow
+        answer = ctx.search( "uid=akarasuluref,ou=users,ou=system", 
+            "(uid=akarasulu)", controls );
+
+        assertTrue( answer.hasMore() );
+        result = answer.next();
+        assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", result.getName() );
+        assertEquals( 0, result.getAttributes().size() );
+        assertFalse( answer.hasMore() );
+        answer.close();
+        ctx.close();
+    }
+}

Modified: directory/apacheds/branches/bigbang/server-integ/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/server-integ/src/test/resources/log4j.properties?rev=682279&r1=682278&r2=682279&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/server-integ/src/test/resources/log4j.properties (original)
+++ directory/apacheds/branches/bigbang/server-integ/src/test/resources/log4j.properties Mon Aug  4 00:46:39 2008
@@ -27,3 +27,4 @@
 log4j.logger.org.apache.directory.shared=DEBUG
 log4j.logger.org.apache.directory.server.schema=ERROR
 log4j.logger.org.apache.directory.server.referral.ReferralIT=DEBUG
+log4j.logger.org.apache.directory.server.operations=DEBUG