| /* |
| * 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 ); |
| } |
| } |