001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.core; 021 022 023 import java.util.ArrayList; 024 import java.util.List; 025 import java.util.Set; 026 027 import org.apache.directory.server.core.entry.ClonedServerEntry; 028 import org.apache.directory.server.core.filtering.EntryFilteringCursor; 029 import org.apache.directory.server.core.interceptor.InterceptorChain; 030 import org.apache.directory.server.core.interceptor.context.AddOperationContext; 031 import org.apache.directory.server.core.interceptor.context.BindOperationContext; 032 import org.apache.directory.server.core.interceptor.context.CompareOperationContext; 033 import org.apache.directory.server.core.interceptor.context.DeleteOperationContext; 034 import org.apache.directory.server.core.interceptor.context.EntryOperationContext; 035 import org.apache.directory.server.core.interceptor.context.GetMatchedNameOperationContext; 036 import org.apache.directory.server.core.interceptor.context.GetRootDSEOperationContext; 037 import org.apache.directory.server.core.interceptor.context.GetSuffixOperationContext; 038 import org.apache.directory.server.core.interceptor.context.ListOperationContext; 039 import org.apache.directory.server.core.interceptor.context.ListSuffixOperationContext; 040 import org.apache.directory.server.core.interceptor.context.LookupOperationContext; 041 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext; 042 import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext; 043 import org.apache.directory.server.core.interceptor.context.MoveOperationContext; 044 import org.apache.directory.server.core.interceptor.context.OperationContext; 045 import org.apache.directory.server.core.interceptor.context.RenameOperationContext; 046 import org.apache.directory.server.core.interceptor.context.SearchOperationContext; 047 import org.apache.directory.server.core.interceptor.context.UnbindOperationContext; 048 import org.apache.directory.server.core.invocation.InvocationStack; 049 import org.apache.directory.server.i18n.I18n; 050 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException; 051 import org.apache.directory.shared.ldap.constants.SchemaConstants; 052 import org.apache.directory.shared.ldap.entry.EntryAttribute; 053 import org.apache.directory.shared.ldap.entry.ServerEntry; 054 import org.apache.directory.shared.ldap.entry.Value; 055 import org.apache.directory.shared.ldap.exception.LdapAffectMultipleDsaException; 056 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException; 057 import org.apache.directory.shared.ldap.exception.LdapPartialResultException; 058 import org.apache.directory.shared.ldap.exception.LdapReferralException; 059 import org.apache.directory.shared.ldap.exception.LdapServiceUnavailableException; 060 import org.apache.directory.shared.ldap.filter.SearchScope; 061 import org.apache.directory.shared.ldap.message.ResultCodeEnum; 062 import org.apache.directory.shared.ldap.name.DN; 063 import org.apache.directory.shared.ldap.util.LdapURL; 064 import org.slf4j.Logger; 065 import org.slf4j.LoggerFactory; 066 067 068 /** 069 * The default implementation of an OperationManager. 070 * 071 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 072 * @version $Rev$, $Date$ 073 */ 074 public class DefaultOperationManager implements OperationManager 075 { 076 /** The logger */ 077 private static final Logger LOG = LoggerFactory.getLogger( DefaultOperationManager.class ); 078 079 /** A logger specifically for change operations */ 080 private static final Logger LOG_CHANGES = LoggerFactory.getLogger( "LOG_CHANGES" ); 081 082 /** The directory service instance */ 083 private final DirectoryService directoryService; 084 085 086 public DefaultOperationManager( DirectoryService directoryService ) 087 { 088 this.directoryService = directoryService; 089 } 090 091 092 private LdapReferralException buildReferralException( ServerEntry parentEntry, DN childDn ) 093 throws LdapInvalidDnException, LdapURLEncodingException 094 { 095 // Get the Ref attributeType 096 EntryAttribute refs = parentEntry.get( SchemaConstants.REF_AT ); 097 098 List<String> urls = new ArrayList<String>(); 099 100 // manage each Referral, building the correct URL for each of them 101 for ( Value<?> url:refs ) 102 { 103 // we have to replace the parent by the referral 104 LdapURL ldapUrl = new LdapURL( url.getString() ); 105 106 // We have a problem with the DN : we can't use the UpName, 107 // as we may have some spaces around the ',' and '+'. 108 // So we have to take the RDN one by one, and create a 109 // new DN with the type and value UP form 110 111 DN urlDn = (DN)ldapUrl.getDn().addAll( childDn ); 112 113 ldapUrl.setDn( urlDn ); 114 urls.add( ldapUrl.toString() ); 115 } 116 117 // Return with an exception 118 LdapReferralException lre = new LdapReferralException( urls ); 119 lre.setRemainingDn( childDn ); 120 lre.setResolvedDn( parentEntry.getDn() ); 121 lre.setResolvedObject( parentEntry ); 122 123 return lre; 124 } 125 126 127 private LdapReferralException buildReferralExceptionForSearch( 128 ServerEntry parentEntry, DN childDn, SearchScope scope ) 129 throws LdapInvalidDnException, LdapURLEncodingException 130 { 131 // Get the Ref attributeType 132 EntryAttribute refs = parentEntry.get( SchemaConstants.REF_AT ); 133 134 List<String> urls = new ArrayList<String>(); 135 136 // manage each Referral, building the correct URL for each of them 137 for ( Value<?> url:refs ) 138 { 139 // we have to replace the parent by the referral 140 try 141 { 142 LdapURL ldapUrl = new LdapURL( url.getString() ); 143 144 StringBuilder urlString = new StringBuilder(); 145 146 if ( ( ldapUrl.getDn() == null ) || ( ldapUrl.getDn() == DN.EMPTY_DN) ) 147 { 148 ldapUrl.setDn( parentEntry.getDn() ); 149 } 150 else 151 { 152 // We have a problem with the DN : we can't use the UpName, 153 // as we may have some spaces around the ',' and '+'. 154 // So we have to take the RDN one by one, and create a 155 // new DN with the type and value UP form 156 157 DN urlDn = (DN)ldapUrl.getDn().addAll( childDn ); 158 159 ldapUrl.setDn( urlDn ); 160 } 161 162 urlString.append( ldapUrl.toString() ).append( "??" ); 163 164 switch ( scope ) 165 { 166 case OBJECT : 167 urlString.append( "base" ); 168 break; 169 170 case SUBTREE : 171 urlString.append( "sub" ); 172 break; 173 174 case ONELEVEL : 175 urlString.append( "one" ); 176 break; 177 } 178 179 urls.add( urlString.toString() ); 180 } 181 catch ( LdapURLEncodingException luee ) 182 { 183 // The URL is not correct, returns it as is 184 urls.add( url.getString() ); 185 } 186 } 187 188 // Return with an exception 189 LdapReferralException lre = new LdapReferralException( urls ); 190 lre.setRemainingDn( childDn ); 191 lre.setResolvedDn( parentEntry.getDn() ); 192 lre.setResolvedObject( parentEntry ); 193 194 return lre; 195 } 196 197 198 private LdapPartialResultException buildLdapPartialResultException( DN childDn ) 199 { 200 LdapPartialResultException lpre = new LdapPartialResultException( I18n.err( I18n.ERR_315 ) ); 201 202 lpre.setRemainingDn( childDn ); 203 lpre.setResolvedDn( DN.EMPTY_DN ); 204 205 return lpre; 206 } 207 208 209 /** 210 * {@inheritDoc} 211 */ 212 public void add( AddOperationContext opContext ) throws Exception 213 { 214 LOG.debug( ">> AddOperation : {}", opContext ); 215 LOG_CHANGES.debug( ">> AddOperation : {}", opContext ); 216 217 ensureStarted(); 218 push( opContext ); 219 220 try 221 { 222 // Normalize the opContext DN 223 DN dn = opContext.getDn(); 224 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 225 226 // We have to deal with the referral first 227 directoryService.getReferralManager().lockRead(); 228 229 if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 230 { 231 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 232 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 233 234 // Depending on the Context.REFERRAL property value, we will throw 235 // a different exception. 236 if ( opContext.isReferralIgnored() ) 237 { 238 directoryService.getReferralManager().unlock(); 239 240 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 241 throw exception; 242 } 243 else 244 { 245 // Unlock the referral manager 246 directoryService.getReferralManager().unlock(); 247 248 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 249 throw exception; 250 } 251 } 252 else 253 { 254 // Unlock the ReferralManager 255 directoryService.getReferralManager().unlock(); 256 257 // Call the Add method 258 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 259 interceptorChain.add( opContext ); 260 } 261 } 262 finally 263 { 264 pop(); 265 } 266 267 LOG.debug( "<< AddOperation successful" ); 268 LOG_CHANGES.debug( "<< AddOperation successful" ); 269 } 270 271 272 /** 273 * {@inheritDoc} 274 */ 275 public void bind( BindOperationContext opContext ) throws Exception 276 { 277 LOG.debug( ">> BindOperation : {}", opContext ); 278 279 ensureStarted(); 280 push( opContext ); 281 282 try 283 { 284 directoryService.getInterceptorChain().bind( opContext ); 285 } 286 finally 287 { 288 pop(); 289 290 LOG.debug( "<< BindOperation successful" ); 291 } 292 } 293 294 295 /** 296 * {@inheritDoc} 297 */ 298 public boolean compare( CompareOperationContext opContext ) throws Exception 299 { 300 LOG.debug( ">> CompareOperation : {}", opContext ); 301 302 ensureStarted(); 303 push( opContext ); 304 305 try 306 { 307 // Normalize the opContext DN 308 DN dn = opContext.getDn(); 309 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 310 311 // We have to deal with the referral first 312 directoryService.getReferralManager().lockRead(); 313 314 // Check if we have an ancestor for this DN 315 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 316 317 if ( parentEntry != null ) 318 { 319 // We have found a parent referral for the current DN 320 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 321 322 if ( directoryService.getReferralManager().isReferral( dn ) ) 323 { 324 // This is a referral. We can delete it if the ManageDsaIt flag is true 325 // Otherwise, we just throw a LdapReferralException 326 if ( !opContext.isReferralIgnored() ) 327 { 328 // Throw a Referral Exception 329 // Unlock the referral manager 330 directoryService.getReferralManager().unlock(); 331 332 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 333 throw exception; 334 } 335 } 336 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 337 { 338 // Depending on the Context.REFERRAL property value, we will throw 339 // a different exception. 340 if ( opContext.isReferralIgnored() ) 341 { 342 directoryService.getReferralManager().unlock(); 343 344 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 345 throw exception; 346 } 347 else 348 { 349 // Unlock the referral manager 350 directoryService.getReferralManager().unlock(); 351 352 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 353 throw exception; 354 } 355 } 356 } 357 358 // Unlock the ReferralManager 359 directoryService.getReferralManager().unlock(); 360 361 // Call the Add method 362 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 363 return interceptorChain.compare( opContext ); 364 } 365 finally 366 { 367 pop(); 368 369 LOG.debug( "<< CompareOperation successful" ); 370 } 371 } 372 373 374 /** 375 * {@inheritDoc} 376 */ 377 public void delete( DeleteOperationContext opContext ) throws Exception 378 { 379 LOG.debug( ">> DeleteOperation : {}", opContext ); 380 LOG_CHANGES.debug( ">> DeleteOperation : {}", opContext ); 381 382 ensureStarted(); 383 push( opContext ); 384 385 try 386 { 387 // Normalize the opContext DN 388 DN dn = opContext.getDn(); 389 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 390 391 // We have to deal with the referral first 392 directoryService.getReferralManager().lockRead(); 393 394 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 395 396 if ( parentEntry != null ) 397 { 398 // We have found a parent referral for the current DN 399 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 400 401 if ( directoryService.getReferralManager().isReferral( dn ) ) 402 { 403 // This is a referral. We can delete it if the ManageDsaIt flag is true 404 // Otherwise, we just throw a LdapReferralException 405 if ( !opContext.isReferralIgnored() ) 406 { 407 // Throw a Referral Exception 408 // Unlock the referral manager 409 directoryService.getReferralManager().unlock(); 410 411 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 412 throw exception; 413 } 414 } 415 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 416 { 417 // We can't delete an entry which has an ancestor referral 418 419 // Depending on the Context.REFERRAL property value, we will throw 420 // a different exception. 421 if ( opContext.isReferralIgnored() ) 422 { 423 directoryService.getReferralManager().unlock(); 424 425 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 426 throw exception; 427 } 428 else 429 { 430 // Unlock the referral manager 431 directoryService.getReferralManager().unlock(); 432 433 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 434 throw exception; 435 } 436 } 437 } 438 439 // Unlock the ReferralManager 440 directoryService.getReferralManager().unlock(); 441 442 // Call the Add method 443 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 444 interceptorChain.delete( opContext ); 445 } 446 finally 447 { 448 pop(); 449 } 450 451 LOG.debug( "<< DeleteOperation successful" ); 452 LOG_CHANGES.debug( "<< DeleteOperation successful" ); 453 } 454 455 456 /** 457 * {@inheritDoc} 458 */ 459 public DN getMatchedName( GetMatchedNameOperationContext opContext ) throws Exception 460 { 461 LOG.debug( ">> GetMatchedNameOperation : {}", opContext ); 462 463 ensureStarted(); 464 push( opContext ); 465 466 try 467 { 468 return directoryService.getInterceptorChain().getMatchedName( opContext ); 469 } 470 finally 471 { 472 pop(); 473 474 LOG.debug( "<< GetMatchedNameOperation successful" ); 475 } 476 } 477 478 479 /** 480 * {@inheritDoc} 481 */ 482 public ClonedServerEntry getRootDSE( GetRootDSEOperationContext opContext ) 483 throws Exception 484 { 485 LOG.debug( ">> GetRootDSEOperation : {}", opContext ); 486 487 ensureStarted(); 488 push( opContext ); 489 490 try 491 { 492 InterceptorChain chain = directoryService.getInterceptorChain(); 493 return chain.getRootDSE( opContext ); 494 } 495 finally 496 { 497 pop(); 498 499 LOG.debug( "<< getRootDSEOperation successful" ); 500 } 501 } 502 503 504 /** 505 * {@inheritDoc} 506 */ 507 public DN getSuffix( GetSuffixOperationContext opContext ) throws Exception 508 { 509 LOG.debug( ">> GetSuffixOperation : {}", opContext ); 510 511 ensureStarted(); 512 push( opContext ); 513 514 try 515 { 516 return directoryService.getInterceptorChain().getSuffix( opContext ); 517 } 518 finally 519 { 520 pop(); 521 522 LOG.debug( "<< GetSuffixOperation successful" ); 523 } 524 } 525 526 527 /** 528 * {@inheritDoc} 529 */ 530 public boolean hasEntry( EntryOperationContext opContext ) throws Exception 531 { 532 LOG.debug( ">> hasEntryOperation : {}", opContext ); 533 534 ensureStarted(); 535 push( opContext ); 536 537 try 538 { 539 return directoryService.getInterceptorChain().hasEntry( opContext ); 540 } 541 finally 542 { 543 pop(); 544 545 LOG.debug( "<< HasEntryOperation successful" ); 546 } 547 } 548 549 550 /** 551 * {@inheritDoc} 552 */ 553 public EntryFilteringCursor list( ListOperationContext opContext ) throws Exception 554 { 555 LOG.debug( ">> ListOperation : {}", opContext ); 556 557 ensureStarted(); 558 push( opContext ); 559 560 try 561 { 562 return directoryService.getInterceptorChain().list( opContext ); 563 } 564 finally 565 { 566 pop(); 567 568 LOG.debug( "<< ListOperation successful" ); 569 } 570 } 571 572 573 /** 574 * {@inheritDoc} 575 */ 576 public Set<String> listSuffixes( ListSuffixOperationContext opContext ) 577 throws Exception 578 { 579 LOG.debug( ">> ListSuffixesOperation : {}", opContext ); 580 581 ensureStarted(); 582 push( opContext ); 583 584 try 585 { 586 return directoryService.getInterceptorChain().listSuffixes( opContext ); 587 } 588 finally 589 { 590 pop(); 591 592 LOG.debug( "<< ListSuffixesOperation successful" ); 593 } 594 } 595 596 597 /** 598 * {@inheritDoc} 599 */ 600 public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception 601 { 602 LOG.debug( ">> LookupOperation : {}", opContext ); 603 604 ensureStarted(); 605 push( opContext ); 606 607 try 608 { 609 return directoryService.getInterceptorChain().lookup( opContext ); 610 } 611 finally 612 { 613 pop(); 614 615 LOG.debug( "<< LookupOperation successful" ); 616 } 617 } 618 619 620 /** 621 * {@inheritDoc} 622 */ 623 public void modify( ModifyOperationContext opContext ) throws Exception 624 { 625 LOG.debug( ">> ModifyOperation : {}", opContext ); 626 LOG_CHANGES.debug( ">> ModifyOperation : {}", opContext ); 627 628 ensureStarted(); 629 push( opContext ); 630 631 try 632 { 633 // Normalize the opContext DN 634 DN dn = opContext.getDn(); 635 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 636 637 // We have to deal with the referral first 638 directoryService.getReferralManager().lockRead(); 639 640 // Check if we have an ancestor for this DN 641 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 642 643 if ( parentEntry != null ) 644 { 645 // We have found a parent referral for the current DN 646 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 647 648 if ( directoryService.getReferralManager().isReferral( dn ) ) 649 { 650 // This is a referral. We can delete it if the ManageDsaIt flag is true 651 // Otherwise, we just throw a LdapReferralException 652 if ( !opContext.isReferralIgnored() ) 653 { 654 // Throw a Referral Exception 655 // Unlock the referral manager 656 directoryService.getReferralManager().unlock(); 657 658 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 659 throw exception; 660 } 661 } 662 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 663 { 664 // We can't delete an entry which has an ancestor referral 665 666 // Depending on the Context.REFERRAL property value, we will throw 667 // a different exception. 668 if ( opContext.isReferralIgnored() ) 669 { 670 directoryService.getReferralManager().unlock(); 671 672 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 673 throw exception; 674 } 675 else 676 { 677 // Unlock the referral manager 678 directoryService.getReferralManager().unlock(); 679 680 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 681 throw exception; 682 } 683 } 684 } 685 686 // Unlock the ReferralManager 687 directoryService.getReferralManager().unlock(); 688 689 // Call the Add method 690 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 691 interceptorChain.modify( opContext ); 692 } 693 finally 694 { 695 pop(); 696 697 LOG.debug( "<< ModifyOperation successful" ); 698 LOG_CHANGES.debug( "<< ModifyOperation successful" ); 699 } 700 } 701 702 703 /** 704 * {@inheritDoc} 705 */ 706 public void move( MoveOperationContext opContext ) throws Exception 707 { 708 LOG.debug( ">> MoveOperation : {}", opContext ); 709 LOG_CHANGES.debug( ">> MoveOperation : {}", opContext ); 710 711 ensureStarted(); 712 push( opContext ); 713 714 try 715 { 716 // Normalize the opContext DN 717 DN dn = opContext.getDn(); 718 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 719 720 // We have to deal with the referral first 721 directoryService.getReferralManager().lockRead(); 722 723 // Check if we have an ancestor for this DN 724 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 725 726 if ( parentEntry != null ) 727 { 728 // We have found a parent referral for the current DN 729 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 730 731 if ( directoryService.getReferralManager().isReferral( dn ) ) 732 { 733 // This is a referral. We can delete it if the ManageDsaIt flag is true 734 // Otherwise, we just throw a LdapReferralException 735 if ( !opContext.isReferralIgnored() ) 736 { 737 // Throw a Referral Exception 738 // Unlock the referral manager 739 directoryService.getReferralManager().unlock(); 740 741 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 742 throw exception; 743 } 744 } 745 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 746 { 747 // We can't delete an entry which has an ancestor referral 748 749 // Depending on the Context.REFERRAL property value, we will throw 750 // a different exception. 751 if ( opContext.isReferralIgnored() ) 752 { 753 directoryService.getReferralManager().unlock(); 754 755 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 756 throw exception; 757 } 758 else 759 { 760 // Unlock the referral manager 761 directoryService.getReferralManager().unlock(); 762 763 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 764 throw exception; 765 } 766 } 767 } 768 769 // Now, check the destination 770 // Normalize the opContext DN 771 DN parentDn = opContext.getParent(); 772 parentDn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 773 774 // If he parent DN is a referral, or has a referral ancestor, we have to issue a AffectMultipleDsas result 775 // as stated by RFC 3296 Section 5.6.2 776 if ( directoryService.getReferralManager().isReferral( parentDn ) || 777 directoryService.getReferralManager().hasParentReferral( parentDn ) ) 778 { 779 // Unlock the referral manager 780 directoryService.getReferralManager().unlock(); 781 782 LdapAffectMultipleDsaException exception = new LdapAffectMultipleDsaException(); 783 //exception.setRemainingName( dn ); 784 785 throw exception; 786 } 787 788 // Unlock the ReferralManager 789 directoryService.getReferralManager().unlock(); 790 791 // Call the Add method 792 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 793 interceptorChain.move( opContext ); 794 } 795 finally 796 { 797 pop(); 798 799 LOG.debug( "<< MoveOperation successful" ); 800 LOG_CHANGES.debug( "<< MoveOperation successful" ); 801 } 802 } 803 804 805 /** 806 * {@inheritDoc} 807 */ 808 public void moveAndRename( MoveAndRenameOperationContext opContext ) throws Exception 809 { 810 LOG.debug( ">> MoveAndRenameOperation : {}", opContext ); 811 LOG_CHANGES.debug( ">> MoveAndRenameOperation : {}", opContext ); 812 813 ensureStarted(); 814 push( opContext ); 815 816 try 817 { 818 // Normalize the opContext DN 819 DN dn = opContext.getDn(); 820 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 821 822 // We have to deal with the referral first 823 directoryService.getReferralManager().lockRead(); 824 825 // Check if we have an ancestor for this DN 826 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 827 828 if ( parentEntry != null ) 829 { 830 // We have found a parent referral for the current DN 831 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 832 833 if ( directoryService.getReferralManager().isReferral( dn ) ) 834 { 835 // This is a referral. We can delete it if the ManageDsaIt flag is true 836 // Otherwise, we just throw a LdapReferralException 837 if ( !opContext.isReferralIgnored() ) 838 { 839 // Throw a Referral Exception 840 // Unlock the referral manager 841 directoryService.getReferralManager().unlock(); 842 843 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 844 throw exception; 845 } 846 } 847 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 848 { 849 // We can't delete an entry which has an ancestor referral 850 851 // Depending on the Context.REFERRAL property value, we will throw 852 // a different exception. 853 if ( opContext.isReferralIgnored() ) 854 { 855 directoryService.getReferralManager().unlock(); 856 857 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 858 throw exception; 859 } 860 else 861 { 862 // Unlock the referral manager 863 directoryService.getReferralManager().unlock(); 864 865 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 866 throw exception; 867 } 868 } 869 } 870 871 // Now, check the destination 872 // Normalize the opContext DN 873 DN parentDn = opContext.getParent(); 874 parentDn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 875 876 // If he parent DN is a referral, or has a referral ancestor, we have to issue a AffectMultipleDsas result 877 // as stated by RFC 3296 Section 5.6.2 878 if ( directoryService.getReferralManager().isReferral( parentDn ) || 879 directoryService.getReferralManager().hasParentReferral( parentDn ) ) 880 { 881 // Unlock the referral manager 882 directoryService.getReferralManager().unlock(); 883 884 // The parent DN is a referral, we have to issue a AffectMultipleDsas result 885 // as stated by RFC 3296 Section 5.6.2 886 LdapAffectMultipleDsaException exception = new LdapAffectMultipleDsaException(); 887 //exception.setRemainingName( dn ); 888 889 throw exception; 890 } 891 892 // Unlock the ReferralManager 893 directoryService.getReferralManager().unlock(); 894 895 // Call the Add method 896 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 897 interceptorChain.moveAndRename( opContext ); 898 } 899 finally 900 { 901 pop(); 902 903 LOG.debug( "<< MoveAndRenameOperation successful" ); 904 LOG_CHANGES.debug( "<< MoveAndRenameOperation successful" ); 905 } 906 } 907 908 909 /** 910 * {@inheritDoc} 911 */ 912 public void rename( RenameOperationContext opContext ) throws Exception 913 { 914 LOG.debug( ">> RenameOperation : {}", opContext ); 915 LOG_CHANGES.debug( ">> RenameOperation : {}", opContext ); 916 917 ensureStarted(); 918 push( opContext ); 919 920 try 921 { 922 // Normalize the opContext DN 923 DN dn = opContext.getDn(); 924 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 925 926 // Inject the newDn into the operation context 927 // Inject the new DN into the context 928 if ( !dn.isEmpty() ) 929 { 930 DN newDn = (DN)dn.clone(); 931 newDn.remove( dn.size() - 1 ); 932 newDn.add( opContext.getNewRdn() ); 933 opContext.setNewDn( newDn ); 934 } 935 936 // We have to deal with the referral first 937 directoryService.getReferralManager().lockRead(); 938 939 // Check if we have an ancestor for this DN 940 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 941 942 if ( parentEntry != null ) 943 { 944 // We have found a parent referral for the current DN 945 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 946 947 if ( directoryService.getReferralManager().isReferral( dn ) ) 948 { 949 // This is a referral. We can delete it if the ManageDsaIt flag is true 950 // Otherwise, we just throw a LdapReferralException 951 if ( !opContext.isReferralIgnored() ) 952 { 953 // Throw a Referral Exception 954 // Unlock the referral manager 955 directoryService.getReferralManager().unlock(); 956 957 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 958 throw exception; 959 } 960 } 961 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 962 { 963 // We can't delete an entry which has an ancestor referral 964 965 // Depending on the Context.REFERRAL property value, we will throw 966 // a different exception. 967 if ( opContext.isReferralIgnored() ) 968 { 969 directoryService.getReferralManager().unlock(); 970 971 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 972 throw exception; 973 } 974 else 975 { 976 // Unlock the referral manager 977 directoryService.getReferralManager().unlock(); 978 979 LdapReferralException exception = buildReferralException( parentEntry, childDn ); 980 throw exception; 981 } 982 } 983 } 984 985 // Unlock the ReferralManager 986 directoryService.getReferralManager().unlock(); 987 988 // Call the Add method 989 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 990 interceptorChain.rename( opContext ); 991 } 992 finally 993 { 994 pop(); 995 996 LOG.debug( "<< RenameOperation successful" ); 997 LOG_CHANGES.debug( "<< RenameOperation successful" ); 998 } 999 } 1000 1001 1002 /** 1003 * {@inheritDoc} 1004 */ 1005 public EntryFilteringCursor search( SearchOperationContext opContext ) throws Exception 1006 { 1007 LOG.debug( ">> SearchOperation : {}", opContext ); 1008 1009 ensureStarted(); 1010 push( opContext ); 1011 1012 try 1013 { 1014 // Normalize the opContext DN 1015 DN dn = opContext.getDn(); 1016 dn.normalize( directoryService.getSchemaManager().getNormalizerMapping() ); 1017 1018 // We have to deal with the referral first 1019 directoryService.getReferralManager().lockRead(); 1020 1021 // Check if we have an ancestor for this DN 1022 ServerEntry parentEntry = directoryService.getReferralManager().getParentReferral( dn ); 1023 1024 if ( parentEntry != null ) 1025 { 1026 // We have found a parent referral for the current DN 1027 DN childDn = (DN)dn.getSuffix( parentEntry.getDn().size() ); 1028 1029 if ( directoryService.getReferralManager().isReferral( dn ) ) 1030 { 1031 // This is a referral. We can return it if the ManageDsaIt flag is true 1032 // Otherwise, we just throw a LdapReferralException 1033 if ( !opContext.isReferralIgnored() ) 1034 { 1035 // Throw a Referral Exception 1036 // Unlock the referral manager 1037 directoryService.getReferralManager().unlock(); 1038 1039 LdapReferralException exception = buildReferralExceptionForSearch( parentEntry, childDn, opContext.getScope() ); 1040 throw exception; 1041 } 1042 } 1043 else if ( directoryService.getReferralManager().hasParentReferral( dn ) ) 1044 { 1045 // We can't search an entry which has an ancestor referral 1046 1047 // Depending on the Context.REFERRAL property value, we will throw 1048 // a different exception. 1049 if ( opContext.isReferralIgnored() ) 1050 { 1051 directoryService.getReferralManager().unlock(); 1052 1053 LdapPartialResultException exception = buildLdapPartialResultException( childDn ); 1054 throw exception; 1055 } 1056 else 1057 { 1058 // Unlock the referral manager 1059 directoryService.getReferralManager().unlock(); 1060 1061 LdapReferralException exception = buildReferralExceptionForSearch( parentEntry, childDn, opContext.getScope() ); 1062 throw exception; 1063 } 1064 } 1065 } 1066 1067 // Unlock the ReferralManager 1068 directoryService.getReferralManager().unlock(); 1069 1070 // Call the Add method 1071 InterceptorChain interceptorChain = directoryService.getInterceptorChain(); 1072 return interceptorChain.search( opContext ); 1073 } 1074 finally 1075 { 1076 pop(); 1077 1078 LOG.debug( "<< SearchOperation successful" ); 1079 } 1080 } 1081 1082 1083 /** 1084 * {@inheritDoc} 1085 */ 1086 public void unbind( UnbindOperationContext opContext ) throws Exception 1087 { 1088 LOG.debug( ">> UnbindOperation : {}", opContext ); 1089 1090 ensureStarted(); 1091 push( opContext ); 1092 1093 try 1094 { 1095 directoryService.getInterceptorChain().unbind( opContext ); 1096 } 1097 finally 1098 { 1099 pop(); 1100 } 1101 1102 LOG.debug( "<< UnbindOperation successful" ); 1103 } 1104 1105 1106 private void ensureStarted() throws LdapServiceUnavailableException 1107 { 1108 if ( ! directoryService.isStarted() ) 1109 { 1110 throw new LdapServiceUnavailableException( ResultCodeEnum.UNAVAILABLE, I18n.err( I18n.ERR_316 ) ); 1111 } 1112 } 1113 1114 1115 private void pop() 1116 { 1117 // TODO - need to remove Context caller and PartitionNexusProxy from Invocations 1118 InvocationStack stack = InvocationStack.getInstance(); 1119 stack.pop(); 1120 } 1121 1122 1123 private void push( OperationContext opContext ) 1124 { 1125 // TODO - need to remove Context caller and PartitionNexusProxy from Invocations 1126 InvocationStack stack = InvocationStack.getInstance(); 1127 stack.push( opContext ); 1128 } 1129 }