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/08 01:55:37 UTC

svn commit: r683763 - /directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/

Author: akarasulu
Date: Thu Aug  7 16:55:36 2008
New Revision: 683763

URL: http://svn.apache.org/viewvc?rev=683763&view=rev
Log:
adding referral handling for search operation with base and continuation based
knowledge referrence handling according to http://www.faqs.org/rfcs/rfc3296.html

 o renamed this base class to better indicate it's nature for dealing with 
   referral handling
 o added code for dealing with search specific LdapURL aspects specifically 
   associated with the requirement to include the scope parameter in the ref
 o added support for continuations according to 3296 in the search handler
 o search handler extends the base class yet includes it's own extensions in 
   its class
 o changing filter to make sure referrals are returned even when the filter
   does not match it in the absence of the manage dsa it control


Added:
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/ReferralAwareRequestHandler.java
      - copied, changed from r683643, directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/SingleReplyRequestHandler.java
Removed:
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/SingleReplyRequestHandler.java
Modified:
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewAddHandler.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewBindHandler.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewCompareHandler.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewDeleteHandler.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyDnHandler.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyHandler.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewSearchHandler.java

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewAddHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewAddHandler.java?rev=683763&r1=683762&r2=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewAddHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewAddHandler.java Thu Aug  7 16:55:36 2008
@@ -37,14 +37,14 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class NewAddHandler extends SingleReplyRequestHandler<AddRequest>
+public class NewAddHandler extends ReferralAwareRequestHandler<AddRequest>
 {
 	/** The logger for this class */
     private static final Logger LOG = LoggerFactory.getLogger( NewAddHandler.class );
     
     
     /**
-     * @see SingleReplyRequestHandler#handleIgnoringReferrals(LdapSession, LdapDN, ClonedServerEntry, 
+     * @see ReferralAwareRequestHandler#handleIgnoringReferrals(LdapSession, LdapDN, ClonedServerEntry, 
      * org.apache.directory.shared.ldap.message.SingleReplyRequest)
      */
     public void handleIgnoringReferrals( LdapSession session, LdapDN reqTargetDn, 

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewBindHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewBindHandler.java?rev=683763&r1=683762&r2=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewBindHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewBindHandler.java Thu Aug  7 16:55:36 2008
@@ -134,7 +134,7 @@
              *      https://issues.apache.org/jira/browse/DIRSERVER-1217
              *      
              * NOTE: if this is done then this handler should extend the 
-             * a modified form of the SingleReplyRequestHandler so it can 
+             * a modified form of the ReferralAwareRequestHandler so it can 
              * detect conditions where ancestors of the DN are referrals
              * and delegate appropriately.
              */

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=683763&r1=683762&r2=683763&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 Thu Aug  7 16:55:36 2008
@@ -37,13 +37,13 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 664302 $
  */
-public class NewCompareHandler extends SingleReplyRequestHandler<CompareRequest>
+public class NewCompareHandler extends ReferralAwareRequestHandler<CompareRequest>
 {
     private static final Logger LOG = LoggerFactory.getLogger( NewCompareHandler.class );
 
     
     /**
-     * @see SingleReplyRequestHandler#handleIgnoringReferrals(LdapSession, LdapDN, 
+     * @see ReferralAwareRequestHandler#handleIgnoringReferrals(LdapSession, LdapDN, 
      * org.apache.directory.server.core.entry.ClonedServerEntry, 
      * org.apache.directory.shared.ldap.message.SingleReplyRequest)
      */

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewDeleteHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewDeleteHandler.java?rev=683763&r1=683762&r2=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewDeleteHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewDeleteHandler.java Thu Aug  7 16:55:36 2008
@@ -37,7 +37,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 664302 $
  */
-public class NewDeleteHandler extends SingleReplyRequestHandler<DeleteRequest>
+public class NewDeleteHandler extends ReferralAwareRequestHandler<DeleteRequest>
 {
     private static final Logger LOG = LoggerFactory.getLogger( NewDeleteHandler.class );
 

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyDnHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyDnHandler.java?rev=683763&r1=683762&r2=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyDnHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyDnHandler.java Thu Aug  7 16:55:36 2008
@@ -37,7 +37,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 664302 $
  */
-public class NewModifyDnHandler extends SingleReplyRequestHandler<ModifyDnRequest>
+public class NewModifyDnHandler extends ReferralAwareRequestHandler<ModifyDnRequest>
 {
     private static final Logger LOG = LoggerFactory.getLogger( NewModifyDnHandler.class );
 

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyHandler.java?rev=683763&r1=683762&r2=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewModifyHandler.java Thu Aug  7 16:55:36 2008
@@ -37,13 +37,13 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 664302 $
  */
-public class NewModifyHandler extends SingleReplyRequestHandler<ModifyRequest>
+public class NewModifyHandler extends ReferralAwareRequestHandler<ModifyRequest>
 {
     private static final Logger LOG = LoggerFactory.getLogger( NewModifyHandler.class );
 
 
     /**
-     * @see SingleReplyRequestHandler#handleIgnoringReferrals(LdapSession, LdapDN, ClonedServerEntry, 
+     * @see ReferralAwareRequestHandler#handleIgnoringReferrals(LdapSession, LdapDN, ClonedServerEntry, 
      * org.apache.directory.shared.ldap.message.SingleReplyRequest)
      */
     @Override

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewSearchHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewSearchHandler.java?rev=683763&r1=683762&r2=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewSearchHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/NewSearchHandler.java Thu Aug  7 16:55:36 2008
@@ -22,14 +22,18 @@
 
 import org.apache.directory.server.core.entry.ClonedServerEntry;
 import org.apache.directory.server.core.entry.ServerEntryUtils;
+import org.apache.directory.server.core.entry.ServerStringValue;
 import org.apache.directory.server.core.event.NotificationCriteria;
 import org.apache.directory.server.core.filtering.EntryFilteringCursor;
 import org.apache.directory.server.newldap.LdapSession;
+import org.apache.directory.shared.ldap.codec.util.LdapURL;
+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;
 import org.apache.directory.shared.ldap.entry.Value;
-import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.exception.OperationAbandonedException;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
+import org.apache.directory.shared.ldap.filter.OrNode;
 import org.apache.directory.shared.ldap.filter.PresenceNode;
 import org.apache.directory.shared.ldap.message.AbandonListener;
 import org.apache.directory.shared.ldap.message.LdapResult;
@@ -46,12 +50,11 @@
 import org.apache.directory.shared.ldap.message.SearchResponseReference;
 import org.apache.directory.shared.ldap.message.SearchResponseReferenceImpl;
 import org.apache.directory.shared.ldap.name.LdapDN;
-import org.apache.directory.shared.ldap.util.ExceptionUtils;
+import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.naming.NamingException;
-import javax.naming.ReferralException;
 
 
 /**
@@ -60,13 +63,30 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 664302 $
  */
-public class NewSearchHandler extends LdapRequestHandler<SearchRequest>
+public class NewSearchHandler extends ReferralAwareRequestHandler<SearchRequest>
 {
     private static final Logger LOG = LoggerFactory.getLogger( NewSearchHandler.class );
 
     /** Speedup for logs */
     private static final boolean IS_DEBUG = LOG.isDebugEnabled();
     
+    AttributeType objectClassAttributeType;
+    
+    private EqualityNode<String> getOcIsReferralAssertion( LdapSession session ) throws Exception
+    {
+        if ( objectClassAttributeType == null )
+        {
+            objectClassAttributeType = session.getCoreSession().getDirectoryService().getRegistries()
+                .getAttributeTypeRegistry().lookup( SchemaConstants.OBJECT_CLASS_AT );
+        }
+        
+        EqualityNode<String> ocIsReferral = new EqualityNode<String>( 
+            SchemaConstants.OBJECT_CLASS_AT,
+            new ServerStringValue( objectClassAttributeType, SchemaConstants.REFERRAL_OC ) );
+        
+        return ocIsReferral;
+    }
+    
     
     private void handlePersistentSearch( LdapSession session, SearchRequest req, 
         PersistentSearchControl psearchControl ) throws Exception 
@@ -129,7 +149,7 @@
             	{
             		hasRootDSE = true;
 	                ClonedServerEntry entry = cursor.get();
-	                session.getIoSession().write( generateResponse( req, entry ) );
+	                session.getIoSession().write( generateResponse( session, req, entry ) );
             	}
             }
     
@@ -189,7 +209,7 @@
             while ( cursor.next() )
             {
                 ClonedServerEntry entry = cursor.get();
-                session.getIoSession().write( generateResponse( req, entry ) );
+                session.getIoSession().write( generateResponse( session, req, entry ) );
             }
     
             LdapResult ldapResult = req.getResultResponse().getLdapResult();
@@ -228,7 +248,7 @@
      * @return the response for the entry
      * @throws Exception if there are problems in generating the response
      */
-    private Response generateResponse( SearchRequest req, ClonedServerEntry entry ) throws Exception
+    private Response generateResponse( LdapSession session, SearchRequest req, ClonedServerEntry entry ) throws Exception
     {
         EntryAttribute ref = entry.getOriginalEntry().get( SchemaConstants.REF_AT );
         boolean hasManageDsaItControl = req.getControls().containsKey( ManageDsaITControl.CONTROL_OID );
@@ -242,7 +262,36 @@
             for ( Value<?> val : ref )
             {
                 String url = ( String ) val.get();
-                respRef.getReferral().addLdapUrl( url );
+                
+                if ( ! url.startsWith( "ldap" ) )
+                {
+                    respRef.getReferral().addLdapUrl( url );
+                }
+                
+                LdapURL ldapUrl = new LdapURL();
+                ldapUrl.setForceScopeRendering( true );
+                try
+                {
+                    ldapUrl.parse( url.toCharArray() );
+                }
+                catch ( LdapURLEncodingException e )
+                {
+                    LOG.error( "Bad URL ({}) for ref in {}.  Reference will be ignored.", url, entry );
+                }
+
+                switch( req.getScope() )
+                {
+                    case SUBTREE:
+                        ldapUrl.setScope( SearchScope.SUBTREE.getJndiScope() );
+                        break;
+                    case ONELEVEL: // one level here is object level on remote server
+                        ldapUrl.setScope( SearchScope.OBJECT.getJndiScope() );
+                        break;
+                    default:
+                        throw new IllegalStateException( "Unexpected base scope." );
+                }
+                
+                respRef.getReferral().addLdapUrl( ldapUrl.toString() );
             }
             
             return respRef;
@@ -260,12 +309,68 @@
     
     
     /**
-     * Main message handing method for search requests.
+     * Alters the filter expression based on the presence of the 
+     * ManageDsaIT control.  If the control is not present, the search
+     * filter will be altered to become a disjunction with two terms.
+     * The first term is the original filter.  The second term is a
+     * (objectClass=referral) assertion.  When OR'd together these will
+     * make sure we get all referrals so we can process continuations 
+     * properly without having the filter remove them from the result 
+     * set.
+     * 
+     * NOTE: original filter is first since most entries are not referrals 
+     * so it has a higher probability on average of accepting and shorting 
+     * evaluation before having to waste cycles trying to evaluate if the 
+     * entry is a referral.
+     *
+     * @param session the session to use to construct the filter (schema access)
+     * @param req the request to get the original filter from
+     * @throws Exception if there are schema access problems
+     */
+    public void modifyFilter( LdapSession session, SearchRequest req ) throws Exception
+    {
+        if ( req.hasControl( ManageDsaITControl.CONTROL_OID ) )
+        {
+            return;
+        }
+        
+        /*
+         * Most of the time the search filter is just (objectClass=*) and if 
+         * this is the case then there's no reason at all to OR this with an
+         * (objectClass=referral).  If we detect this case then we leave it 
+         * as is to represent the OR condition:
+         * 
+         *  (| (objectClass=referral)(objectClass=*)) == (objectClass=*)
+         */
+        if ( req.getFilter() instanceof PresenceNode )
+        {
+            PresenceNode presenceNode = ( PresenceNode ) req.getFilter();
+            
+            AttributeType at = session.getCoreSession().getDirectoryService()
+                .getRegistries().getAttributeTypeRegistry().lookup( presenceNode.getAttribute() );
+            if ( at.getOid().equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+            {
+                return;
+            }
+        }
+
+        // using varags to add two expressions to an OR node 
+        req.setFilter( new OrNode( req.getFilter(), getOcIsReferralAssertion( session ) ) );
+    }
+    
+    
+    /**
+     * Main message handing method for search requests.  This will be called 
+     * even if the ManageDsaIT control is present because the super class does
+     * not know that the search operation has more to do after finding the 
+     * base.  The call to this means that finding the base can ignore 
+     * referrals.
      * 
      * @param session the associated session
      * @param req the received SearchRequest
      */
-    public void handle( LdapSession session, SearchRequest req ) throws Exception
+    public void handleIgnoringReferrals( LdapSession session, LdapDN reqTargetDn, 
+        ClonedServerEntry entry, SearchRequest req )
     {
         if ( IS_DEBUG )
         {
@@ -277,6 +382,9 @@
 
         try
         {
+            // modify the filter to affect continuation support
+            modifyFilter( session, req );
+            
             // ===============================================================
             // Handle search in rootDSE differently.
             // ===============================================================
@@ -306,24 +414,7 @@
             SearchResponseDone done = doSimpleSearch( session, req );
             session.getIoSession().write( done );
         }
-        catch ( ReferralException e )
-        {
-            LdapResult result = req.getResultResponse().getLdapResult();
-            ReferralImpl refs = new ReferralImpl();
-            result.setReferral( refs );
-            result.setResultCode( ResultCodeEnum.REFERRAL );
-            result.setErrorMessage( "Encountered referral attempting to handle add request." );
-
-            do
-            {
-                refs.addLdapUrl( ( String ) e.getReferralInfo() );
-            }
-            while ( e.skipReferral() );
-            
-            session.getIoSession().write( req.getResultResponse() );
-            session.unregisterOutstandingRequest( req );
-        }
-        catch ( NamingException e )
+        catch ( Exception e )
         {
             /*
              * From RFC 2251 Section 4.11:
@@ -342,37 +433,7 @@
                 return;
             }
 
-            String msg = "failed on search operation: " + e.getMessage();
-            
-            if ( LOG.isDebugEnabled() )
-            {
-                msg += ":\n" + req + ":\n" + ExceptionUtils.getStackTrace( e );
-            }
-
-            ResultCodeEnum code;
-            
-            if ( e instanceof LdapException )
-            {
-                code = ( ( LdapException ) e ).getResultCode();
-            }
-            else
-            {
-                code = ResultCodeEnum.getBestEstimate( e, req.getType() );
-            }
-
-            LdapResult result = req.getResultResponse().getLdapResult();
-            result.setResultCode( code );
-            result.setErrorMessage( msg );
-
-            if ( ( e.getResolvedName() != null )
-                && ( ( code == ResultCodeEnum.NO_SUCH_OBJECT ) || ( code == ResultCodeEnum.ALIAS_PROBLEM )
-                    || ( code == ResultCodeEnum.INVALID_DN_SYNTAX ) || ( code == ResultCodeEnum.ALIAS_DEREFERENCING_PROBLEM ) ) )
-            {
-                result.setMatchedDn( (LdapDN)e.getResolvedName() );
-            }
-
-            session.getIoSession().write( req.getResultResponse() );
-            session.unregisterOutstandingRequest( req );
+            handleException( session, req, e );
         }
     }
 

Copied: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/ReferralAwareRequestHandler.java (from r683643, directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/SingleReplyRequestHandler.java)
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/ReferralAwareRequestHandler.java?p2=directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/ReferralAwareRequestHandler.java&p1=directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/SingleReplyRequestHandler.java&r1=683643&r2=683763&rev=683763&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/SingleReplyRequestHandler.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/ReferralAwareRequestHandler.java Thu Aug  7 16:55:36 2008
@@ -44,9 +44,11 @@
 import org.apache.directory.shared.ldap.message.Referral;
 import org.apache.directory.shared.ldap.message.ReferralImpl;
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
-import org.apache.directory.shared.ldap.message.SingleReplyRequest;
+import org.apache.directory.shared.ldap.message.ResultResponseRequest;
+import org.apache.directory.shared.ldap.message.SearchRequest;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.util.ExceptionUtils;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -61,9 +63,9 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public abstract class SingleReplyRequestHandler<T extends SingleReplyRequest> extends LdapRequestHandler<T>
+public abstract class ReferralAwareRequestHandler<T extends ResultResponseRequest> extends LdapRequestHandler<T>
 {
-    private static final Logger LOG = LoggerFactory.getLogger( SingleReplyRequestHandler.class );
+    private static final Logger LOG = LoggerFactory.getLogger( ReferralAwareRequestHandler.class );
     
     /** Speedup for logs */
     private static final boolean IS_DEBUG = LOG.isDebugEnabled();
@@ -79,27 +81,27 @@
         
         LdapDN reqTargetDn = null;
         
-        switch ( req.getResponseType() )
+        switch ( req.getType() )
         {
-            case ADD_RESPONSE:
+            case ADD_REQUEST:
                 reqTargetDn = ( ( AddRequest ) req ).getEntry();
                 break;
-            case BIND_RESPONSE:
+            case BIND_REQUEST:
                 // not used for bind but may be in future
                 reqTargetDn = ( ( BindRequest ) req ).getName();
                 break;
-            case COMPARE_RESPONSE:
+            case COMPARE_REQUEST:
                 reqTargetDn = ( ( CompareRequest ) req ).getName();
                 break;
-            case DEL_RESPONSE:
+            case DEL_REQUEST:
                 reqTargetDn = ( ( DeleteRequest ) req ).getName();
                 break;
-            case EXTENDED_RESP:
+            case EXTENDED_REQ:
                 throw new IllegalStateException( 
                     "Although ExtendedRequests are SingleReplyRequests they're not handled" +
                     " using this base class.  They have no target entry unlike the rest of" +
                     " the SingleReplyRequests" );
-            case MOD_DN_RESPONSE:
+            case MOD_DN_REQUEST:
                 /*
                  * Special handling needed because of the new superior entry 
                  * as specified in RFC 3296 section 5.6.2 here: 
@@ -126,9 +128,12 @@
                     }
                 }
                 return;
-            case MODIFY_RESPONSE:
+            case MODIFY_REQUEST:
                 reqTargetDn = ( ( ModifyRequest ) req ).getName();
                 break;
+            case SEARCH_REQUEST:
+                reqTargetDn = ( ( SearchRequest ) req ).getBase();
+                break;
             default:
                 throw new IllegalStateException( 
                     "Unidentified single reply request/response type: " + req );
@@ -420,7 +425,15 @@
                 if ( isEntryReferral( entry ) )
                 {
                     LOG.debug( "Entry is a referral: {}", entry );
-                    handleReferralEntry( session, reqTargetDn, req, entry );
+                    
+                    if ( req instanceof SearchRequest )
+                    {
+                        handleReferralEntryForSearch( session, ( SearchRequest ) req, entry );
+                    }
+                    else
+                    {
+                        handleReferralEntry( session, reqTargetDn, req, entry );
+                    }
                     return;
                 }
                 else
@@ -474,7 +487,17 @@
             // if we get here then we have a valid referral ancestor
             try
             {
-                Referral referral = getReferralOnAncestor( session, reqTargetDn, req, referralAncestor );
+                Referral referral = null;
+                
+                if ( req instanceof SearchRequest )
+                {
+                    referral = getReferralOnAncestorForSearch( session, ( SearchRequest ) req, referralAncestor );
+                }
+                else
+                {
+                    referral = getReferralOnAncestor( session, reqTargetDn, req, referralAncestor );
+                }
+                
                 result.setResultCode( ResultCodeEnum.REFERRAL );
                 result.setReferral( referral );
                 session.getIoSession().write( req.getResultResponse() );
@@ -517,6 +540,60 @@
     
     
     /**
+     * Handles processing a referral response on a target entry which is a 
+     * referral.  It will for any request that returns an LdapResult in it's 
+     * response.
+     *
+     * @param session the session to use for processing
+     * @param reqTargetDn the dn of the target entry of the request
+     * @param req the request
+     * @param entry the entry associated with the request
+     */
+    private void handleReferralEntryForSearch( LdapSession session, SearchRequest req, ClonedServerEntry entry )
+        throws Exception
+    {
+        LdapResult result = req.getResultResponse().getLdapResult();
+        ReferralImpl referral = new ReferralImpl();
+        result.setReferral( referral );
+        result.setResultCode( ResultCodeEnum.REFERRAL );
+        result.setErrorMessage( "Encountered referral attempting to handle request." );
+        result.setMatchedDn( req.getBase() );
+
+        EntryAttribute refAttr = entry.getOriginalEntry().get( SchemaConstants.REF_AT );
+        for ( Value<?> refval : refAttr )
+        {
+            String refstr = ( String ) refval.get();
+            
+            // need to add non-ldap URLs as-is
+            if ( ! refstr.startsWith( "ldap" ) )
+            {
+                referral.addLdapUrl( refstr );
+                continue;
+            }
+            
+            // parse the ref value and normalize the DN  
+            LdapURL ldapUrl = new LdapURL();
+            try
+            {
+                ldapUrl.parse( refstr.toCharArray() );
+            }
+            catch ( LdapURLEncodingException e )
+            {
+                LOG.error( "Bad URL ({}) for ref in {}.  Reference will be ignored.", refstr, entry );
+                continue;
+            }
+            
+            ldapUrl.setForceScopeRendering( true );
+            ldapUrl.setAttributes( req.getAttributes() );
+            ldapUrl.setScope( req.getScope().getJndiScope() );
+            referral.addLdapUrl( ldapUrl.toString() );
+        }
+
+        session.getIoSession().write( req.getResultResponse() );
+    }
+    
+    
+    /**
      * 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.
@@ -616,6 +693,88 @@
     
     
     /**
+     * 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 Referral getReferralOnAncestorForSearch( LdapSession session, SearchRequest req, 
+        ClonedServerEntry referralAncestor ) throws Exception
+    {
+        LOG.debug( "Inside getReferralOnAncestor()" );
+     
+        ServerAttribute refAttr = ( ServerAttribute ) referralAncestor.getOriginalEntry()
+            .get( SchemaConstants.REF_AT );
+        Referral referral = new ReferralImpl();
+
+        for ( Value<?> value : refAttr )
+        {
+            String ref = ( String ) value.get();
+
+            LOG.debug( "Calculating LdapURL for referrence value {}", ref );
+
+            // need to add non-ldap URLs as-is
+            if ( ! ref.startsWith( "ldap" ) )
+            {
+                referral.addLdapUrl( ref );
+                continue;
+            }
+            
+            // Parse the ref value   
+            LdapURL ldapUrl = new LdapURL();
+            try
+            {
+                ldapUrl.parse( ref.toCharArray() );
+            }
+            catch ( LdapURLEncodingException e )
+            {
+                LOG.error( "Bad URL ({}) for ref in {}.  Reference will be ignored.", ref, referralAncestor );
+            }
+            
+            // Normalize the DN to check for same dn
+            LdapDN urlDn = new LdapDN( ldapUrl.getDn().getUpName() );
+            urlDn.normalize( session.getCoreSession().getDirectoryService().getRegistries()
+                .getAttributeTypeRegistry().getNormalizerMapping() ); 
+            
+            if ( urlDn.getNormName().equals( req.getBase().getNormName() ) )
+            {
+                ldapUrl.setForceScopeRendering( true );
+                ldapUrl.setAttributes( req.getAttributes() );
+                ldapUrl.setScope( req.getScope().getJndiScope() );
+                referral.addLdapUrl( ldapUrl.toString() );
+                continue;
+            }
+            
+            /*
+             * If we get here then the DN of the referral was not the same as the 
+             * DN of the ref LDAP URL.  We must calculate the remaining (difference)
+             * name past the farthest referral DN which the target name extends.
+             */
+            int diff = req.getBase().size() - referralAncestor.getDn().size();
+            LdapDN extra = new LdapDN();
+
+            // TODO - fix this by access unormalized RDN values
+            // seems we have to do this because get returns normalized rdns
+            LdapDN reqUnnormalizedDn = new LdapDN( req.getBase().getUpName() );
+            for ( int jj = 0; jj < diff; jj++ )
+            {
+                extra.add( reqUnnormalizedDn.get( referralAncestor.getDn().size() + jj ) );
+            }
+
+            ldapUrl.getDn().addAll( extra );
+            ldapUrl.setForceScopeRendering( true );
+            ldapUrl.setAttributes( req.getAttributes() );
+            ldapUrl.setScope( req.getScope().getJndiScope() );
+            referral.addLdapUrl( ldapUrl.toString() );
+        }
+        
+        return referral;
+    }
+    
+    
+    /**
      * Handles processing with referrals without ManageDsaIT control.
      */
     public void handleException( LdapSession session, T req, Exception e )