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 )