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 */ 020package org.apache.directory.server.core.api.interceptor; 021 022 023import java.util.HashSet; 024import java.util.Set; 025 026import org.apache.directory.api.ldap.model.entry.Entry; 027import org.apache.directory.api.ldap.model.exception.LdapException; 028import org.apache.directory.api.ldap.model.schema.AttributeType; 029import org.apache.directory.api.ldap.model.schema.SchemaManager; 030import org.apache.directory.server.core.api.DirectoryService; 031import org.apache.directory.server.core.api.DnFactory; 032import org.apache.directory.server.core.api.InterceptorEnum; 033import org.apache.directory.server.core.api.LdapPrincipal; 034import org.apache.directory.server.core.api.filtering.EntryFilteringCursor; 035import org.apache.directory.server.core.api.interceptor.context.AddOperationContext; 036import org.apache.directory.server.core.api.interceptor.context.BindOperationContext; 037import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext; 038import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext; 039import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext; 040import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext; 041import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext; 042import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext; 043import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext; 044import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext; 045import org.apache.directory.server.core.api.interceptor.context.OperationContext; 046import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext; 047import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext; 048import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext; 049import org.apache.directory.server.core.api.partition.PartitionNexus; 050 051 052/** 053 * A easy-to-use implementation of {@link Interceptor}. All methods are 054 * implemented to pass the flow of control to next interceptor by defaults. 055 * Please override the methods you have concern in. 056 * 057 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 058 */ 059public abstract class BaseInterceptor implements Interceptor 060{ 061 /** The interceptor's name. Default to the class name */ 062 private String name; 063 064 /** A reference to the DirectoryService instance */ 065 protected DirectoryService directoryService; 066 067 /** A reference to the SchemaManager instance */ 068 protected SchemaManager schemaManager; 069 070 /** The DN factory */ 071 protected DnFactory dnFactory; 072 073 /** set of operational attribute types used for representing the password policy state of a user entry */ 074 protected static final Set<AttributeType> PWD_POLICY_STATE_ATTRIBUTE_TYPES = new HashSet<>(); 075 076 /** 077 * The final interceptor which acts as a proxy in charge to dialog with the nexus partition. 078 */ 079 private final Interceptor finalInterceptor = new Interceptor() 080 { 081 private PartitionNexus nexus; 082 083 084 public String getName() 085 { 086 return "FINAL"; 087 } 088 089 090 public void init( DirectoryService directoryService ) 091 { 092 this.nexus = directoryService.getPartitionNexus(); 093 } 094 095 096 public void destroy() 097 { 098 // unused 099 } 100 101 102 /** 103 * {@inheritDoc} 104 */ 105 public void add( AddOperationContext addContext ) throws LdapException 106 { 107 nexus.add( addContext ); 108 } 109 110 111 /** 112 * {@inheritDoc} 113 */ 114 public void bind( BindOperationContext bindContext ) throws LdapException 115 { 116 // Do nothing here : there is no support for the Bind operation in Partition 117 } 118 119 120 /** 121 * {@inheritDoc} 122 */ 123 public boolean compare( CompareOperationContext compareContext ) throws LdapException 124 { 125 return nexus.compare( compareContext ); 126 } 127 128 129 /** 130 * {@inheritDoc} 131 */ 132 public void delete( DeleteOperationContext deleteContext ) throws LdapException 133 { 134 nexus.delete( deleteContext ); 135 } 136 137 138 /** 139 * {@inheritDoc} 140 */ 141 public Entry getRootDse( GetRootDseOperationContext getRootDseContext ) throws LdapException 142 { 143 return nexus.getRootDse( getRootDseContext ); 144 } 145 146 147 /** 148 * {@inheritDoc} 149 */ 150 public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException 151 { 152 return nexus.hasEntry( hasEntryContext ); 153 } 154 155 156 /** 157 * {@inheritDoc} 158 */ 159 public Entry lookup( LookupOperationContext lookupContext ) throws LdapException 160 { 161 return nexus.lookup( lookupContext ); 162 } 163 164 165 /** 166 * {@inheritDoc} 167 */ 168 public void modify( ModifyOperationContext modifyContext ) throws LdapException 169 { 170 nexus.modify( modifyContext ); 171 } 172 173 174 /** 175 * {@inheritDoc} 176 */ 177 public void move( MoveOperationContext moveContext ) throws LdapException 178 { 179 nexus.move( moveContext ); 180 } 181 182 183 /** 184 * {@inheritDoc} 185 */ 186 public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException 187 { 188 nexus.moveAndRename( moveAndRenameContext ); 189 } 190 191 192 /** 193 * {@inheritDoc} 194 */ 195 public void rename( RenameOperationContext renameContext ) throws LdapException 196 { 197 nexus.rename( renameContext ); 198 } 199 200 201 /** 202 * {@inheritDoc} 203 */ 204 public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException 205 { 206 return nexus.search( searchContext ); 207 } 208 209 210 /** 211 * {@inheritDoc} 212 */ 213 public void unbind( UnbindOperationContext unbindContext ) throws LdapException 214 { 215 nexus.unbind( unbindContext ); 216 } 217 }; 218 219 220 /** 221 * default interceptor name is its class, preventing accidental duplication of interceptors by naming 222 * instances differently 223 * @return (default, class name) interceptor name 224 */ 225 public String getName() 226 { 227 return name; 228 } 229 230 231 /** 232 * Returns {@link LdapPrincipal} of current context. 233 * 234 * @param opContext TODO 235 * @return the authenticated principal 236 */ 237 public static LdapPrincipal getPrincipal( OperationContext opContext ) 238 { 239 return opContext.getSession().getEffectivePrincipal(); 240 } 241 242 243 /** 244 * Creates a new instance with a default name : the class name itself. 245 */ 246 protected BaseInterceptor() 247 { 248 name = getClass().getSimpleName(); 249 } 250 251 252 /** 253 * Creates a new instance with a given name. 254 * 255 * @param name the Interceptor name 256 */ 257 protected BaseInterceptor( String name ) 258 { 259 this.name = name; 260 } 261 262 263 /** 264 * Creates a new instance with a given name. 265 * 266 * @param interceptor the Interceptor type 267 */ 268 protected BaseInterceptor( InterceptorEnum interceptor ) 269 { 270 this.name = interceptor.getName(); 271 } 272 273 274 /** 275 * This method does nothing by default. 276 * 277 * @param directoryService The DirectoryService instance 278 * @throws LdapException If the initialization failed 279 */ 280 public void init( DirectoryService directoryService ) throws LdapException 281 { 282 // Initialize the fields that will be used by all the interceptors 283 this.directoryService = directoryService; 284 schemaManager = directoryService.getSchemaManager(); 285 dnFactory = directoryService.getDnFactory(); 286 287 finalInterceptor.init( directoryService ); 288 } 289 290 291 /** 292 * This method does nothing by default. 293 */ 294 public void destroy() 295 { 296 } 297 298 299 /** 300 * Computes the next interceptor to call for a given operation. If we find none, 301 * we return the proxy to the nexus. 302 * 303 * @param operationContext The operation context 304 * @return The next interceptor in the list for this operation 305 */ 306 protected Interceptor getNextInterceptor( OperationContext operationContext ) 307 { 308 String currentInterceptor = operationContext.getNextInterceptor(); 309 310 if ( currentInterceptor.equals( "FINAL" ) ) 311 { 312 return finalInterceptor; 313 } 314 315 return directoryService.getInterceptor( currentInterceptor ); 316 } 317 318 319 // ------------------------------------------------------------------------ 320 // Interceptor's Invoke Method 321 // ------------------------------------------------------------------------ 322 /** 323 * {@inheritDoc} 324 */ 325 public void add( AddOperationContext addContext ) throws LdapException 326 { 327 // Do nothing 328 } 329 330 331 /** 332 * Calls the next interceptor for the add operation. 333 * 334 * @param addContext The context in which we are executing this operation 335 * @throws LdapException If something went wrong 336 */ 337 protected final void next( AddOperationContext addContext ) throws LdapException 338 { 339 Interceptor interceptor = getNextInterceptor( addContext ); 340 341 interceptor.add( addContext ); 342 } 343 344 345 /** 346 * {@inheritDoc} 347 */ 348 public void bind( BindOperationContext bindContext ) throws LdapException 349 { 350 // Do nothing 351 } 352 353 354 /** 355 * Calls the next interceptor for the bind operation. 356 * 357 * @param bindContext The context in which we are executing this operation 358 * @throws LdapException If something went wrong 359 */ 360 protected final void next( BindOperationContext bindContext ) throws LdapException 361 { 362 Interceptor interceptor = getNextInterceptor( bindContext ); 363 364 interceptor.bind( bindContext ); 365 } 366 367 368 public boolean compare( CompareOperationContext compareContext ) throws LdapException 369 { 370 // Return false in any case 371 return false; 372 } 373 374 375 /** 376 * Calls the next interceptor for the compare operation. 377 * 378 * @param compareContext The context in which we are executing this operation 379 * @return a boolean indicating if the comparison is successfull 380 * @throws LdapException If something went wrong 381 */ 382 protected final boolean next( CompareOperationContext compareContext ) throws LdapException 383 { 384 Interceptor interceptor = getNextInterceptor( compareContext ); 385 386 return interceptor.compare( compareContext ); 387 } 388 389 390 /** 391 * {@inheritDoc} 392 */ 393 public void delete( DeleteOperationContext deleteContext ) throws LdapException 394 { 395 // Do nothing 396 } 397 398 399 /** 400 * Calls the next interceptor for the delete operation. 401 * 402 * @param deleteContext The context in which we are executing this operation 403 * @throws LdapException If something went wrong 404 */ 405 protected final void next( DeleteOperationContext deleteContext ) throws LdapException 406 { 407 Interceptor interceptor = getNextInterceptor( deleteContext ); 408 409 interceptor.delete( deleteContext ); 410 } 411 412 413 /** 414 * {@inheritDoc} 415 */ 416 public Entry getRootDse( GetRootDseOperationContext getRootDseContext ) throws LdapException 417 { 418 // Nothing to do 419 return null; 420 } 421 422 423 /** 424 * Calls the next interceptor for the getRootDse operation. 425 * 426 * @param getRootDseContext The context in which we are executing this operation 427 * @return the rootDSE 428 * @throws LdapException If something went wrong 429 */ 430 protected final Entry next( GetRootDseOperationContext getRootDseContext ) throws LdapException 431 { 432 Interceptor interceptor = getNextInterceptor( getRootDseContext ); 433 434 return interceptor.getRootDse( getRootDseContext ); 435 } 436 437 438 /** 439 * {@inheritDoc} 440 */ 441 public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException 442 { 443 // Return false in any case 444 return false; 445 } 446 447 448 /** 449 * Calls the next interceptor for the hasEntry operation. 450 * 451 * @param hasEntryContext The context in which we are executing this operation 452 * @return a boolean indicating if the entry exists on the server 453 * @throws LdapException If something went wrong 454 */ 455 protected final boolean next( HasEntryOperationContext hasEntryContext ) throws LdapException 456 { 457 Interceptor interceptor = getNextInterceptor( hasEntryContext ); 458 459 return interceptor.hasEntry( hasEntryContext ); 460 } 461 462 463 /** 464 * {@inheritDoc} 465 */ 466 public Entry lookup( LookupOperationContext lookupContext ) throws LdapException 467 { 468 return next( lookupContext ); 469 } 470 471 472 /** 473 * Calls the next interceptor for the lookup operation. 474 * 475 * @param lookupContext The context in which we are executing this operation 476 * @return the Entry containing the found entry 477 * @throws LdapException If something went wrong 478 */ 479 protected final Entry next( LookupOperationContext lookupContext ) throws LdapException 480 { 481 Interceptor interceptor = getNextInterceptor( lookupContext ); 482 483 return interceptor.lookup( lookupContext ); 484 } 485 486 487 /** 488 * {@inheritDoc} 489 */ 490 public void modify( ModifyOperationContext modifyContext ) throws LdapException 491 { 492 // Nothing to do 493 } 494 495 496 /** 497 * Calls the next interceptor for the modify operation. 498 * 499 * @param modifyContext The context in which we are executing this operation 500 * @throws LdapException If something went wrong 501 */ 502 protected final void next( ModifyOperationContext modifyContext ) throws LdapException 503 { 504 Interceptor interceptor = getNextInterceptor( modifyContext ); 505 506 interceptor.modify( modifyContext ); 507 } 508 509 510 /** 511 * {@inheritDoc} 512 */ 513 public void move( MoveOperationContext moveContext ) throws LdapException 514 { 515 // Do nothing 516 } 517 518 519 /** 520 * Calls the next interceptor for the move operation. 521 * 522 * @param moveContext The context in which we are executing this operation 523 * @throws LdapException If something went wrong 524 */ 525 protected final void next( MoveOperationContext moveContext ) throws LdapException 526 { 527 Interceptor interceptor = getNextInterceptor( moveContext ); 528 529 interceptor.move( moveContext ); 530 } 531 532 533 public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException 534 { 535 // Do nothing 536 } 537 538 539 /** 540 * Calls the next interceptor for the moveAndRename operation. 541 * 542 * @param moveAndRenameContext The context in which we are executing this operation 543 * @throws LdapException If something went wrong 544 */ 545 protected final void next( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException 546 { 547 Interceptor interceptor = getNextInterceptor( moveAndRenameContext ); 548 549 interceptor.moveAndRename( moveAndRenameContext ); 550 } 551 552 553 /** 554 * {@inheritDoc} 555 */ 556 public void rename( RenameOperationContext renameContext ) throws LdapException 557 { 558 // Nothing to do 559 } 560 561 562 /** 563 * Calls the next interceptor for the rename operation. 564 * 565 * @param renameContext The context in which we are executing this operation 566 * @throws LdapException If something went wrong 567 */ 568 protected final void next( RenameOperationContext renameContext ) throws LdapException 569 { 570 Interceptor interceptor = getNextInterceptor( renameContext ); 571 572 interceptor.rename( renameContext ); 573 } 574 575 576 /** 577 * {@inheritDoc} 578 */ 579 public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException 580 { 581 return null; 582 } 583 584 585 /** 586 * Calls the next interceptor for the search operation. 587 * 588 * @param searchContext The context in which we are executing this operation 589 * @return the cursor containing the found entries 590 * @throws LdapException If something went wrong 591 */ 592 protected final EntryFilteringCursor next( SearchOperationContext searchContext ) throws LdapException 593 { 594 Interceptor interceptor = getNextInterceptor( searchContext ); 595 596 return interceptor.search( searchContext ); 597 } 598 599 600 /** 601 * {@inheritDoc} 602 */ 603 public void unbind( UnbindOperationContext unbindContext ) throws LdapException 604 { 605 // Nothing to do 606 } 607 608 609 /** 610 * Compute the next interceptor for the unbind operation. 611 * 612 * @param unbindContext The context in which we are executing this operation 613 * @throws LdapException If something went wrong 614 */ 615 protected final void next( UnbindOperationContext unbindContext ) throws LdapException 616 { 617 Interceptor interceptor = getNextInterceptor( unbindContext ); 618 619 interceptor.unbind( unbindContext ); 620 } 621}