blob: f0432532cb77bb72c34213945bc7848d72da8fc5 [file] [log] [blame]
/*
* 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.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.PartialResultException;
import javax.naming.ReferralException;
import javax.naming.ServiceUnavailableException;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.interceptor.InterceptorChain;
import org.apache.directory.server.core.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.interceptor.context.BindOperationContext;
import org.apache.directory.server.core.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
import org.apache.directory.server.core.interceptor.context.GetMatchedNameOperationContext;
import org.apache.directory.server.core.interceptor.context.GetRootDSEOperationContext;
import org.apache.directory.server.core.interceptor.context.GetSuffixOperationContext;
import org.apache.directory.server.core.interceptor.context.ListOperationContext;
import org.apache.directory.server.core.interceptor.context.ListSuffixOperationContext;
import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.interceptor.context.OperationContext;
import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.interceptor.context.UnbindOperationContext;
import org.apache.directory.server.core.invocation.InvocationStack;
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.LdapNamingException;
import org.apache.directory.shared.ldap.exception.LdapReferralException;
import org.apache.directory.shared.ldap.filter.SearchScope;
import org.apache.directory.shared.ldap.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.util.LdapURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The default implementation of an OperationManager.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
public class DefaultOperationManager implements OperationManager
{
/** The logger */
private static final Logger LOG = LoggerFactory.getLogger( DefaultOperationManager.class );
/** A logger specifically for change operations */
private static final Logger LOG_CHANGES = LoggerFactory.getLogger( "LOG_CHANGES" );
/** The directory service instance */
private final DirectoryService directoryService;
public DefaultOperationManager( DirectoryService directoryService )
{
this.directoryService = directoryService;
}
private LdapReferralException buildReferralException( ServerEntry parentEntry, LdapDN childDn )
throws NamingException, LdapURLEncodingException
{
// Get the Ref attributeType
EntryAttribute refs = parentEntry.get( SchemaConstants.REF_AT );
List<String> urls = new ArrayList<String>();
// manage each Referral, building the correct URL for each of them
for ( Value<?> url:refs )
{
// we have to replace the parent by the referral
LdapURL ldapUrl = new LdapURL( url.getString() );
// We have a problem with the DN : we can't use the UpName,
// as we may have some spaces around the ',' and '+'.
// So we have to take the RDN one by one, and create a
// new DN with the type and value UP form
LdapDN urlDn = (LdapDN)ldapUrl.getDn().addAll( childDn );
ldapUrl.setDn( urlDn );
urls.add( ldapUrl.toString() );
}
// Return with an exception
LdapReferralException lre = new LdapReferralException( urls );
lre.setRemainingName( childDn );
lre.setResolvedName( parentEntry.getDn() );
lre.setResolvedObj( parentEntry );
return lre;
}
private LdapReferralException buildReferralExceptionForSearch(
ServerEntry parentEntry, LdapDN childDn, SearchScope scope )
throws NamingException, LdapURLEncodingException
{
// Get the Ref attributeType
EntryAttribute refs = parentEntry.get( SchemaConstants.REF_AT );
List<String> urls = new ArrayList<String>();
// manage each Referral, building the correct URL for each of them
for ( Value<?> url:refs )
{
// we have to replace the parent by the referral
try
{
LdapURL ldapUrl = new LdapURL( url.getString() );
StringBuilder urlString = new StringBuilder();
if ( ( ldapUrl.getDn() == null ) || ( ldapUrl.getDn() == LdapDN.EMPTY_LDAPDN) )
{
ldapUrl.setDn( parentEntry.getDn() );
}
else
{
// We have a problem with the DN : we can't use the UpName,
// as we may have some spaces around the ',' and '+'.
// So we have to take the RDN one by one, and create a
// new DN with the type and value UP form
LdapDN urlDn = (LdapDN)ldapUrl.getDn().addAll( childDn );
ldapUrl.setDn( urlDn );
}
urlString.append( ldapUrl.toString() ).append( "??" );
switch ( scope )
{
case OBJECT :
urlString.append( "base" );
break;
case SUBTREE :
urlString.append( "sub" );
break;
case ONELEVEL :
urlString.append( "one" );
break;
}
urls.add( urlString.toString() );
}
catch ( LdapURLEncodingException luee )
{
// The URL is not correct, returns it as is
urls.add( url.getString() );
}
}
// Return with an exception
LdapReferralException lre = new LdapReferralException( urls );
lre.setRemainingName( childDn );
lre.setResolvedName( parentEntry.getDn() );
lre.setResolvedObj( parentEntry );
return lre;
}
private PartialResultException buildPartialResultException( LdapDN childDn )
{
PartialResultException pre = new PartialResultException( "cannot create an entry under a referral when the Context.REFERRAL is set to 'ignore'" );
pre.setRemainingName( childDn );
pre.setResolvedName( LdapDN.EMPTY_LDAPDN );
return pre;
}
/**
* {@inheritDoc}
*/
public void add( AddOperationContext opContext ) throws Exception
{
LOG.debug( ">> AddOperation : {}", opContext );
LOG_CHANGES.debug( ">> AddOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else
{
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
interceptorChain.add( opContext );
}
}
finally
{
pop();
}
LOG.debug( "<< AddOperation successful" );
LOG_CHANGES.debug( "<< AddOperation successful" );
}
/**
* {@inheritDoc}
*/
public void bind( BindOperationContext opContext ) throws Exception
{
LOG.debug( ">> BindOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
directoryService.getInterceptorChain().bind( opContext );
}
finally
{
pop();
LOG.debug( "<< BindOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public boolean compare( CompareOperationContext opContext ) throws Exception
{
LOG.debug( ">> CompareOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
// Check if we have an ancestor for this DN
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can delete it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
return interceptorChain.compare( opContext );
}
finally
{
pop();
LOG.debug( "<< CompareOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public void delete( DeleteOperationContext opContext ) throws Exception
{
LOG.debug( ">> DeleteOperation : {}", opContext );
LOG_CHANGES.debug( ">> DeleteOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can delete it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// We can't delete an entry which has an ancestor referral
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
interceptorChain.delete( opContext );
}
finally
{
pop();
}
LOG.debug( "<< DeleteOperation successful" );
LOG_CHANGES.debug( "<< DeleteOperation successful" );
}
/**
* {@inheritDoc}
*/
public LdapDN getMatchedName( GetMatchedNameOperationContext opContext ) throws Exception
{
LOG.debug( ">> GetMatchedNameOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().getMatchedName( opContext );
}
finally
{
pop();
LOG.debug( "<< GetMatchedNameOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public ClonedServerEntry getRootDSE( GetRootDSEOperationContext opContext )
throws Exception
{
LOG.debug( ">> GetRootDSEOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().getRootDSE( opContext );
}
finally
{
pop();
LOG.debug( "<< getRootDSEOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public LdapDN getSuffix( GetSuffixOperationContext opContext ) throws Exception
{
LOG.debug( ">> GetSuffixOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().getSuffix( opContext );
}
finally
{
pop();
LOG.debug( "<< GetSuffixOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public boolean hasEntry( EntryOperationContext opContext ) throws Exception
{
LOG.debug( ">> hasEntryOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().hasEntry( opContext );
}
finally
{
pop();
LOG.debug( "<< HasEntryOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public EntryFilteringCursor list( ListOperationContext opContext ) throws Exception
{
LOG.debug( ">> ListOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().list( opContext );
}
finally
{
pop();
LOG.debug( "<< ListOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public Set<String> listSuffixes( ListSuffixOperationContext opContext )
throws Exception
{
LOG.debug( ">> ListSuffixesOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().listSuffixes( opContext );
}
finally
{
pop();
LOG.debug( "<< ListSuffixesOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception
{
LOG.debug( ">> LookupOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
return directoryService.getInterceptorChain().lookup( opContext );
}
finally
{
pop();
LOG.debug( "<< LookupOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public void modify( ModifyOperationContext opContext ) throws Exception
{
LOG.debug( ">> ModifyOperation : {}", opContext );
LOG_CHANGES.debug( ">> ModifyOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
// Check if we have an ancestor for this DN
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can delete it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// We can't delete an entry which has an ancestor referral
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
interceptorChain.modify( opContext );
}
finally
{
pop();
LOG.debug( "<< ModifyOperation successful" );
LOG_CHANGES.debug( "<< ModifyOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public void move( MoveOperationContext opContext ) throws Exception
{
LOG.debug( ">> MoveOperation : {}", opContext );
LOG_CHANGES.debug( ">> MoveOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
// Check if we have an ancestor for this DN
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can delete it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// We can't delete an entry which has an ancestor referral
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
}
// Now, check the destination
// Normalize the opContext DN
LdapDN parentDn = opContext.getParent();
parentDn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// If he parent DN is a referral, or has a referral ancestor, we have to issue a AffectMultipleDsas result
// as stated by RFC 3296 Section 5.6.2
if ( directoryService.getReferralManager().isReferral( parentDn ) ||
directoryService.getReferralManager().hasParentReferral( parentDn ) )
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
LdapNamingException exception = new LdapNamingException( ResultCodeEnum.AFFECTS_MULTIPLE_DSAS );
exception.setRemainingName( dn );
throw exception;
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
interceptorChain.move( opContext );
}
finally
{
pop();
LOG.debug( "<< MoveOperation successful" );
LOG_CHANGES.debug( "<< MoveOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public void moveAndRename( MoveAndRenameOperationContext opContext ) throws Exception
{
LOG.debug( ">> MoveAndRenameOperation : {}", opContext );
LOG_CHANGES.debug( ">> MoveAndRenameOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
// Check if we have an ancestor for this DN
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can delete it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// We can't delete an entry which has an ancestor referral
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
}
// Now, check the destination
// Normalize the opContext DN
LdapDN parentDn = opContext.getParent();
parentDn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// If he parent DN is a referral, or has a referral ancestor, we have to issue a AffectMultipleDsas result
// as stated by RFC 3296 Section 5.6.2
if ( directoryService.getReferralManager().isReferral( parentDn ) ||
directoryService.getReferralManager().hasParentReferral( parentDn ) )
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
// The parent DN is a referral, we have to issue a AffectMultipleDsas result
// as stated by RFC 3296 Section 5.6.2
LdapNamingException exception = new LdapNamingException( ResultCodeEnum.AFFECTS_MULTIPLE_DSAS );
exception.setRemainingName( dn );
throw exception;
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
interceptorChain.moveAndRename( opContext );
}
finally
{
pop();
LOG.debug( "<< MoveAndRenameOperation successful" );
LOG_CHANGES.debug( "<< MoveAndRenameOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public void rename( RenameOperationContext opContext ) throws Exception
{
LOG.debug( ">> RenameOperation : {}", opContext );
LOG_CHANGES.debug( ">> RenameOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// Inject the newDn into the operation context
// Inject the new DN into the context
if ( !dn.isEmpty() )
{
LdapDN newDn = (LdapDN)dn.clone();
newDn.remove( dn.size() - 1 );
newDn.add( opContext.getNewRdn() );
opContext.setNewDn( newDn );
}
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
// Check if we have an ancestor for this DN
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can delete it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// We can't delete an entry which has an ancestor referral
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralException( parentEntry, childDn );
throw exception;
}
}
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
interceptorChain.rename( opContext );
}
finally
{
pop();
LOG.debug( "<< RenameOperation successful" );
LOG_CHANGES.debug( "<< RenameOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public EntryFilteringCursor search( SearchOperationContext opContext ) throws Exception
{
LOG.debug( ">> SearchOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
// Normalize the opContext DN
LdapDN dn = opContext.getDn();
dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() );
// We have to deal with the referral first
directoryService.getReferralManager().lockRead();
// Check if we have an ancestor for this DN
ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn );
if ( parentEntry != null )
{
// We have found a parent referral for the current DN
LdapDN childDn = (LdapDN)dn.getSuffix( parentEntry.getDn().size() );
if ( directoryService.getReferralManager().isReferral( dn ) )
{
// This is a referral. We can return it if the ManageDsaIt flag is true
// Otherwise, we just throw a LdapReferralException
if ( !opContext.isReferralIgnored() )
{
// Throw a Referral Exception
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralExceptionForSearch( parentEntry, childDn, opContext.getScope() );
throw exception;
}
}
else if ( directoryService.getReferralManager().hasParentReferral( dn ) )
{
// We can't search an entry which has an ancestor referral
// Depending on the Context.REFERRAL property value, we will throw
// a different exception.
if ( opContext.isReferralIgnored() )
{
directoryService.getReferralManager().unlock();
PartialResultException exception = buildPartialResultException( childDn );
throw exception;
}
else
{
// Unlock the referral manager
directoryService.getReferralManager().unlock();
ReferralException exception = buildReferralExceptionForSearch( parentEntry, childDn, opContext.getScope() );
throw exception;
}
}
}
// Unlock the ReferralManager
directoryService.getReferralManager().unlock();
// Call the Add method
InterceptorChain interceptorChain = directoryService.getInterceptorChain();
return interceptorChain.search( opContext );
}
finally
{
pop();
LOG.debug( "<< SearchOperation successful" );
}
}
/**
* {@inheritDoc}
*/
public void unbind( UnbindOperationContext opContext ) throws Exception
{
LOG.debug( ">> UnbindOperation : {}", opContext );
ensureStarted();
push( opContext );
try
{
directoryService.getInterceptorChain().unbind( opContext );
}
finally
{
pop();
}
LOG.debug( "<< UnbindOperation successful" );
}
private void ensureStarted() throws ServiceUnavailableException
{
if ( ! directoryService.isStarted() )
{
throw new ServiceUnavailableException( "Directory service is not started." );
}
}
private void pop()
{
// TODO - need to remove Context caller and PartitionNexusProxy from Invocations
InvocationStack stack = InvocationStack.getInstance();
stack.pop();
}
private void push( OperationContext opContext )
{
// TODO - need to remove Context caller and PartitionNexusProxy from Invocations
InvocationStack stack = InvocationStack.getInstance();
stack.push( opContext );
}
}