001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027 028package org.opends.server.admin.server; 029 030 031 032import static org.opends.messages.AdminMessages.*; 033import static org.opends.server.util.StaticUtils.*; 034 035import java.util.Collections; 036import java.util.LinkedList; 037import java.util.List; 038import java.util.Map; 039import java.util.Set; 040import java.util.SortedSet; 041 042import org.forgerock.i18n.LocalizableMessage; 043import org.opends.server.admin.Configuration; 044import org.opends.server.admin.Constraint; 045import org.opends.server.admin.InstantiableRelationDefinition; 046import org.opends.server.admin.ManagedObjectDefinition; 047import org.opends.server.admin.ManagedObjectPath; 048import org.opends.server.admin.OptionalRelationDefinition; 049import org.opends.server.admin.PropertyDefinition; 050import org.opends.server.admin.PropertyProvider; 051import org.opends.server.admin.RelationDefinition; 052import org.opends.server.admin.SetRelationDefinition; 053import org.opends.server.admin.SingletonRelationDefinition; 054import org.opends.server.api.ConfigAddListener; 055import org.opends.server.api.ConfigChangeListener; 056import org.opends.server.api.ConfigDeleteListener; 057import org.opends.server.config.ConfigEntry; 058import org.forgerock.opendj.config.server.ConfigException; 059import org.opends.server.core.DirectoryServer; 060import org.forgerock.i18n.slf4j.LocalizedLogger; 061import org.opends.server.types.DN; 062 063 064 065/** 066 * A server-side managed object. 067 * 068 * @param <S> 069 * The type of server configuration represented by the server 070 * managed object. 071 */ 072public final class ServerManagedObject<S extends Configuration> implements 073 PropertyProvider { 074 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 075 076 /** 077 * The configuration entry associated with this server managed 078 * object (null if root). 079 */ 080 private ConfigEntry configEntry; 081 082 /** The management context. */ 083 private final ServerManagementContext context = ServerManagementContext 084 .getInstance(); 085 086 /** The managed object's definition. */ 087 private final ManagedObjectDefinition<?, S> definition; 088 089 /** The managed object path identifying this managed object's location. */ 090 private final ManagedObjectPath<?, S> path; 091 092 /** The managed object's properties. */ 093 private final Map<PropertyDefinition<?>, SortedSet<?>> properties; 094 095 096 097 /** 098 * Creates an new server side managed object. 099 * 100 * @param path 101 * The managed object path. 102 * @param d 103 * The managed object definition. 104 * @param properties 105 * The managed object's properties. 106 * @param configEntry 107 * The configuration entry associated with the managed 108 * object. 109 */ 110 ServerManagedObject(ManagedObjectPath<?, S> path, 111 ManagedObjectDefinition<?, S> d, 112 Map<PropertyDefinition<?>, SortedSet<?>> properties, 113 ConfigEntry configEntry) { 114 this.definition = d; 115 this.path = path; 116 this.properties = properties; 117 this.configEntry = configEntry; 118 } 119 120 121 122 /** 123 * Deregisters an existing configuration add listener. 124 * 125 * @param <M> 126 * The type of the child server configuration object. 127 * @param d 128 * The instantiable relation definition. 129 * @param listener 130 * The configuration add listener. 131 * @throws IllegalArgumentException 132 * If the instantiable relation definition is not 133 * associated with this managed object's definition. 134 */ 135 public <M extends Configuration> void deregisterAddListener( 136 InstantiableRelationDefinition<?, M> d, 137 ConfigurationAddListener<M> listener) throws IllegalArgumentException { 138 validateRelationDefinition(d); 139 140 DN baseDN = DNBuilder.create(path, d); 141 deregisterAddListener(baseDN, listener); 142 } 143 144 145 146 /** 147 * Deregisters an existing server managed object add listener. 148 * 149 * @param <M> 150 * The type of the child server configuration object. 151 * @param d 152 * The instantiable relation definition. 153 * @param listener 154 * The server managed object add listener. 155 * @throws IllegalArgumentException 156 * If the instantiable relation definition is not 157 * associated with this managed object's definition. 158 */ 159 public <M extends Configuration> void deregisterAddListener( 160 InstantiableRelationDefinition<?, M> d, 161 ServerManagedObjectAddListener<M> listener) 162 throws IllegalArgumentException { 163 validateRelationDefinition(d); 164 165 DN baseDN = DNBuilder.create(path, d); 166 deregisterAddListener(baseDN, listener); 167 } 168 169 170 171 /** 172 * Deregisters an existing configuration add listener. 173 * 174 * @param <M> 175 * The type of the child server configuration object. 176 * @param d 177 * The optional relation definition. 178 * @param listener 179 * The configuration add listener. 180 * @throws IllegalArgumentException 181 * If the optional relation definition is not associated 182 * with this managed object's definition. 183 */ 184 public <M extends Configuration> void deregisterAddListener( 185 OptionalRelationDefinition<?, M> d, ConfigurationAddListener<M> listener) 186 throws IllegalArgumentException { 187 validateRelationDefinition(d); 188 189 DN baseDN = DNBuilder.create(path, d).parent(); 190 deregisterAddListener(baseDN, listener); 191 } 192 193 194 195 /** 196 * Deregisters an existing server managed object add listener. 197 * 198 * @param <M> 199 * The type of the child server configuration object. 200 * @param d 201 * The optional relation definition. 202 * @param listener 203 * The server managed object add listener. 204 * @throws IllegalArgumentException 205 * If the optional relation definition is not associated 206 * with this managed object's definition. 207 */ 208 public <M extends Configuration> void deregisterAddListener( 209 OptionalRelationDefinition<?, M> d, 210 ServerManagedObjectAddListener<M> listener) 211 throws IllegalArgumentException { 212 validateRelationDefinition(d); 213 214 DN baseDN = DNBuilder.create(path, d).parent(); 215 deregisterAddListener(baseDN, listener); 216 } 217 218 219 220 /** 221 * Deregisters an existing configuration add listener. 222 * 223 * @param <M> 224 * The type of the child server configuration object. 225 * @param d 226 * The set relation definition. 227 * @param listener 228 * The configuration add listener. 229 * @throws IllegalArgumentException 230 * If the set relation definition is not 231 * associated with this managed object's definition. 232 */ 233 public <M extends Configuration> void deregisterAddListener( 234 SetRelationDefinition<?, M> d, 235 ConfigurationAddListener<M> listener) throws IllegalArgumentException { 236 validateRelationDefinition(d); 237 238 DN baseDN = DNBuilder.create(path, d); 239 deregisterAddListener(baseDN, listener); 240 } 241 242 243 244 /** 245 * Deregisters an existing server managed object add listener. 246 * 247 * @param <M> 248 * The type of the child server configuration object. 249 * @param d 250 * The set relation definition. 251 * @param listener 252 * The server managed object add listener. 253 * @throws IllegalArgumentException 254 * If the set relation definition is not 255 * associated with this managed object's definition. 256 */ 257 public <M extends Configuration> void deregisterAddListener( 258 SetRelationDefinition<?, M> d, 259 ServerManagedObjectAddListener<M> listener) 260 throws IllegalArgumentException { 261 validateRelationDefinition(d); 262 263 DN baseDN = DNBuilder.create(path, d); 264 deregisterAddListener(baseDN, listener); 265 } 266 267 268 269 /** 270 * Deregisters an existing configuration change listener. 271 * 272 * @param listener 273 * The configuration change listener. 274 */ 275 public void deregisterChangeListener( 276 ConfigurationChangeListener<? super S> listener) { 277 for (ConfigChangeListener l : configEntry.getChangeListeners()) { 278 if (l instanceof ConfigChangeListenerAdaptor) { 279 ConfigChangeListenerAdaptor<?> adaptor = 280 (ConfigChangeListenerAdaptor<?>) l; 281 ServerManagedObjectChangeListener<?> l2 = adaptor 282 .getServerManagedObjectChangeListener(); 283 if (l2 instanceof ServerManagedObjectChangeListenerAdaptor<?>) { 284 ServerManagedObjectChangeListenerAdaptor<?> adaptor2 = 285 (ServerManagedObjectChangeListenerAdaptor<?>) l2; 286 if (adaptor2.getConfigurationChangeListener() == listener) { 287 adaptor.finalizeChangeListener(); 288 configEntry.deregisterChangeListener(adaptor); 289 } 290 } 291 } 292 } 293 } 294 295 296 297 /** 298 * Deregisters an existing server managed object change listener. 299 * 300 * @param listener 301 * The server managed object change listener. 302 */ 303 public void deregisterChangeListener( 304 ServerManagedObjectChangeListener<? super S> listener) { 305 for (ConfigChangeListener l : configEntry.getChangeListeners()) { 306 if (l instanceof ConfigChangeListenerAdaptor) { 307 ConfigChangeListenerAdaptor<?> adaptor = 308 (ConfigChangeListenerAdaptor<?>) l; 309 if (adaptor.getServerManagedObjectChangeListener() == listener) { 310 adaptor.finalizeChangeListener(); 311 configEntry.deregisterChangeListener(adaptor); 312 } 313 } 314 } 315 } 316 317 318 319 /** 320 * Deregisters an existing configuration delete listener. 321 * 322 * @param <M> 323 * The type of the child server configuration object. 324 * @param d 325 * The instantiable relation definition. 326 * @param listener 327 * The configuration delete listener. 328 * @throws IllegalArgumentException 329 * If the instantiable relation definition is not 330 * associated with this managed object's definition. 331 */ 332 public <M extends Configuration> void deregisterDeleteListener( 333 InstantiableRelationDefinition<?, M> d, 334 ConfigurationDeleteListener<M> listener) throws IllegalArgumentException { 335 validateRelationDefinition(d); 336 337 DN baseDN = DNBuilder.create(path, d); 338 deregisterDeleteListener(baseDN, listener); 339 } 340 341 342 343 /** 344 * Deregisters an existing server managed object delete listener. 345 * 346 * @param <M> 347 * The type of the child server configuration object. 348 * @param d 349 * The instantiable relation definition. 350 * @param listener 351 * The server managed object delete listener. 352 * @throws IllegalArgumentException 353 * If the instantiable relation definition is not 354 * associated with this managed object's definition. 355 */ 356 public <M extends Configuration> void deregisterDeleteListener( 357 InstantiableRelationDefinition<?, M> d, 358 ServerManagedObjectDeleteListener<M> listener) 359 throws IllegalArgumentException { 360 validateRelationDefinition(d); 361 362 DN baseDN = DNBuilder.create(path, d); 363 deregisterDeleteListener(baseDN, listener); 364 } 365 366 367 368 /** 369 * Deregisters an existing configuration delete listener. 370 * 371 * @param <M> 372 * The type of the child server configuration object. 373 * @param d 374 * The optional relation definition. 375 * @param listener 376 * The configuration delete listener. 377 * @throws IllegalArgumentException 378 * If the optional relation definition is not associated 379 * with this managed object's definition. 380 */ 381 public <M extends Configuration> void deregisterDeleteListener( 382 OptionalRelationDefinition<?, M> d, 383 ConfigurationDeleteListener<M> listener) throws IllegalArgumentException { 384 validateRelationDefinition(d); 385 386 DN baseDN = DNBuilder.create(path, d).parent(); 387 deregisterDeleteListener(baseDN, listener); 388 } 389 390 391 392 /** 393 * Deregisters an existing server managed object delete listener. 394 * 395 * @param <M> 396 * The type of the child server configuration object. 397 * @param d 398 * The optional relation definition. 399 * @param listener 400 * The server managed object delete listener. 401 * @throws IllegalArgumentException 402 * If the optional relation definition is not associated 403 * with this managed object's definition. 404 */ 405 public <M extends Configuration> void deregisterDeleteListener( 406 OptionalRelationDefinition<?, M> d, 407 ServerManagedObjectDeleteListener<M> listener) 408 throws IllegalArgumentException { 409 validateRelationDefinition(d); 410 411 DN baseDN = DNBuilder.create(path, d).parent(); 412 deregisterDeleteListener(baseDN, listener); 413 } 414 415 416 417 /** 418 * Deregisters an existing configuration delete listener. 419 * 420 * @param <M> 421 * The type of the child server configuration object. 422 * @param d 423 * The set relation definition. 424 * @param listener 425 * The configuration delete listener. 426 * @throws IllegalArgumentException 427 * If the set relation definition is not 428 * associated with this managed object's definition. 429 */ 430 public <M extends Configuration> void deregisterDeleteListener( 431 SetRelationDefinition<?, M> d, 432 ConfigurationDeleteListener<M> listener) throws IllegalArgumentException { 433 validateRelationDefinition(d); 434 435 DN baseDN = DNBuilder.create(path, d); 436 deregisterDeleteListener(baseDN, listener); 437 } 438 439 440 441 /** 442 * Deregisters an existing server managed object delete listener. 443 * 444 * @param <M> 445 * The type of the child server configuration object. 446 * @param d 447 * The set relation definition. 448 * @param listener 449 * The server managed object delete listener. 450 * @throws IllegalArgumentException 451 * If the set relation definition is not 452 * associated with this managed object's definition. 453 */ 454 public <M extends Configuration> void deregisterDeleteListener( 455 SetRelationDefinition<?, M> d, 456 ServerManagedObjectDeleteListener<M> listener) 457 throws IllegalArgumentException { 458 validateRelationDefinition(d); 459 460 DN baseDN = DNBuilder.create(path, d); 461 deregisterDeleteListener(baseDN, listener); 462 } 463 464 465 466 /** 467 * Retrieve an instantiable child managed object. 468 * 469 * @param <M> 470 * The requested type of the child server managed object 471 * configuration. 472 * @param d 473 * The instantiable relation definition. 474 * @param name 475 * The name of the child managed object. 476 * @return Returns the instantiable child managed object. 477 * @throws IllegalArgumentException 478 * If the relation definition is not associated with this 479 * managed object's definition. 480 * @throws ConfigException 481 * If the child managed object could not be found or if it 482 * could not be decoded. 483 */ 484 public <M extends Configuration> ServerManagedObject<? extends M> getChild( 485 InstantiableRelationDefinition<?, M> d, String name) 486 throws IllegalArgumentException, ConfigException { 487 validateRelationDefinition(d); 488 return context.getManagedObject(path.child(d, name)); 489 } 490 491 492 493 /** 494 * Retrieve an optional child managed object. 495 * 496 * @param <M> 497 * The requested type of the child server managed object 498 * configuration. 499 * @param d 500 * The optional relation definition. 501 * @return Returns the optional child managed object. 502 * @throws IllegalArgumentException 503 * If the optional relation definition is not associated 504 * with this managed object's definition. 505 * @throws ConfigException 506 * If the child managed object could not be found or if it 507 * could not be decoded. 508 */ 509 public <M extends Configuration> ServerManagedObject<? extends M> getChild( 510 OptionalRelationDefinition<?, M> d) throws IllegalArgumentException, 511 ConfigException { 512 validateRelationDefinition(d); 513 return context.getManagedObject(path.child(d)); 514 } 515 516 517 518 /** 519 * Retrieve a set child managed object. 520 * 521 * @param <M> 522 * The requested type of the child server managed object 523 * configuration. 524 * @param d 525 * The set relation definition. 526 * @param name 527 * The name of the child managed object. 528 * @return Returns the set child managed object. 529 * @throws IllegalArgumentException 530 * If the relation definition is not associated with this 531 * managed object's definition or if {@code name} specifies 532 * a managed object definition which is not a sub-type of 533 * the relation's child definition. 534 * @throws ConfigException 535 * If the child managed object could not be found or if it 536 * could not be decoded. 537 */ 538 public <M extends Configuration> ServerManagedObject<? extends M> getChild( 539 SetRelationDefinition<?, M> d, String name) 540 throws IllegalArgumentException, ConfigException 541 { 542 validateRelationDefinition(d); 543 544 return context.getManagedObject(path.child(d, name)); 545 } 546 547 548 549 /** 550 * Retrieve a singleton child managed object. 551 * 552 * @param <M> 553 * The requested type of the child server managed object 554 * configuration. 555 * @param d 556 * The singleton relation definition. 557 * @return Returns the singleton child managed object. 558 * @throws IllegalArgumentException 559 * If the relation definition is not associated with this 560 * managed object's definition. 561 * @throws ConfigException 562 * If the child managed object could not be found or if it 563 * could not be decoded. 564 */ 565 public <M extends Configuration> ServerManagedObject<? extends M> getChild( 566 SingletonRelationDefinition<?, M> d) throws IllegalArgumentException, 567 ConfigException { 568 validateRelationDefinition(d); 569 return context.getManagedObject(path.child(d)); 570 } 571 572 573 574 /** 575 * Creates a server configuration view of this managed object. 576 * 577 * @return Returns the server configuration view of this managed 578 * object. 579 */ 580 public S getConfiguration() { 581 return definition.createServerConfiguration(this); 582 } 583 584 585 586 /** 587 * Get the DN of the LDAP entry associated with this server managed 588 * object. 589 * 590 * @return Returns the DN of the LDAP entry associated with this 591 * server managed object, or an null DN if this is the root 592 * managed object. 593 */ 594 public DN getDN() { 595 if (configEntry != null) { 596 return configEntry.getDN(); 597 } else { 598 return DN.rootDN(); 599 } 600 } 601 602 603 604 /** 605 * Get the definition associated with this server managed object. 606 * 607 * @return Returns the definition associated with this server 608 * managed object. 609 */ 610 public ManagedObjectDefinition<?, S> getManagedObjectDefinition() { 611 return definition; 612 } 613 614 615 616 /** 617 * Get the path of this server managed object. 618 * 619 * @return Returns the path of this server managed object. 620 */ 621 public ManagedObjectPath<?, S> getManagedObjectPath() { 622 return path; 623 } 624 625 626 627 /** 628 * Get the effective value of the specified property. If the 629 * property is multi-valued then just the first value is returned. 630 * If the property does not have a value then its default value is 631 * returned if it has one, or <code>null</code> indicating that 632 * any default behavior is applicable. 633 * 634 * @param <T> 635 * The type of the property to be retrieved. 636 * @param d 637 * The property to be retrieved. 638 * @return Returns the property's effective value, or 639 * <code>null</code> indicating that any default behavior 640 * is applicable. 641 * @throws IllegalArgumentException 642 * If the property definition is not associated with this 643 * managed object's definition. 644 */ 645 public <T> T getPropertyValue(PropertyDefinition<T> d) 646 throws IllegalArgumentException { 647 Set<T> values = getPropertyValues(d); 648 if (values.isEmpty()) { 649 return null; 650 } else { 651 return values.iterator().next(); 652 } 653 } 654 655 656 657 /** 658 * Get the effective values of the specified property. If the 659 * property does not have any values then its default values are 660 * returned if it has any, or an empty set indicating that any 661 * default behavior is applicable. 662 * 663 * @param <T> 664 * The type of the property to be retrieved. 665 * @param d 666 * The property to be retrieved. 667 * @return Returns an unmodifiable set containing the property's 668 * effective values. An empty set indicates that the 669 * property has no default values defined and any default 670 * behavior is applicable. 671 * @throws IllegalArgumentException 672 * If the property definition is not associated with this 673 * managed object's definition. 674 */ 675 @SuppressWarnings("unchecked") 676 public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d) 677 throws IllegalArgumentException { 678 if (!properties.containsKey(d)) { 679 throw new IllegalArgumentException("Unknown property " + d.getName()); 680 } 681 return Collections.unmodifiableSortedSet((SortedSet<T>) properties.get(d)); 682 } 683 684 685 686 /** 687 * Determines whether or not the optional managed object associated 688 * with the specified optional relations exists. 689 * 690 * @param d 691 * The optional relation definition. 692 * @return Returns <code>true</code> if the optional managed 693 * object exists, <code>false</code> otherwise. 694 * @throws IllegalArgumentException 695 * If the optional relation definition is not associated 696 * with this managed object's definition. 697 */ 698 public boolean hasChild(OptionalRelationDefinition<?, ?> d) 699 throws IllegalArgumentException { 700 validateRelationDefinition(d); 701 return context.managedObjectExists(path.child(d)); 702 } 703 704 705 706 /** 707 * Lists the child managed objects associated with the specified 708 * instantiable relation. 709 * 710 * @param d 711 * The instantiable relation definition. 712 * @return Returns the names of the child managed objects. 713 * @throws IllegalArgumentException 714 * If the relation definition is not associated with this 715 * managed object's definition. 716 */ 717 public String[] listChildren(InstantiableRelationDefinition<?, ?> d) 718 throws IllegalArgumentException { 719 validateRelationDefinition(d); 720 return context.listManagedObjects(path, d); 721 } 722 723 724 725 /** 726 * Lists the child managed objects associated with the specified 727 * set relation. 728 * 729 * @param d 730 * The set relation definition. 731 * @return Returns the names of the child managed objects. 732 * @throws IllegalArgumentException 733 * If the relation definition is not associated with this 734 * managed object's definition. 735 */ 736 public String[] listChildren(SetRelationDefinition<?, ?> d) 737 throws IllegalArgumentException { 738 validateRelationDefinition(d); 739 return context.listManagedObjects(path, d); 740 } 741 742 743 744 /** 745 * Register to be notified when new child configurations are added 746 * beneath an instantiable relation. 747 * 748 * @param <M> 749 * The type of the child server configuration object. 750 * @param d 751 * The instantiable relation definition. 752 * @param listener 753 * The configuration add listener. 754 * @throws IllegalArgumentException 755 * If the instantiable relation definition is not 756 * associated with this managed object's definition. 757 * @throws ConfigException 758 * If the configuration entry associated with the 759 * instantiable relation could not be retrieved. 760 */ 761 public <M extends Configuration> void registerAddListener( 762 InstantiableRelationDefinition<?, M> d, 763 ConfigurationAddListener<M> listener) throws IllegalArgumentException, 764 ConfigException { 765 registerAddListener(d, new ServerManagedObjectAddListenerAdaptor<M>( 766 listener)); 767 } 768 769 770 771 /** 772 * Register to be notified when new child server managed object are 773 * added beneath an instantiable relation. 774 * 775 * @param <M> 776 * The type of the child server configuration object. 777 * @param d 778 * The instantiable relation definition. 779 * @param listener 780 * The server managed object add listener. 781 * @throws IllegalArgumentException 782 * If the instantiable relation definition is not 783 * associated with this managed object's definition. 784 * @throws ConfigException 785 * If the configuration entry associated with the 786 * instantiable relation could not be retrieved. 787 */ 788 public <M extends Configuration> void registerAddListener( 789 InstantiableRelationDefinition<?, M> d, 790 ServerManagedObjectAddListener<M> listener) 791 throws IllegalArgumentException, ConfigException { 792 validateRelationDefinition(d); 793 DN baseDN = DNBuilder.create(path, d); 794 ConfigAddListener adaptor = new ConfigAddListenerAdaptor<>(path, d, listener); 795 registerAddListener(baseDN, adaptor); 796 } 797 798 799 800 /** 801 * Register to be notified when a new child configurations is added 802 * beneath an optional relation. 803 * 804 * @param <M> 805 * The type of the child server configuration object. 806 * @param d 807 * The optional relation definition. 808 * @param listener 809 * The configuration add listener. 810 * @throws IllegalArgumentException 811 * If the optional relation definition is not associated 812 * with this managed object's definition. 813 * @throws ConfigException 814 * If the configuration entry associated with the optional 815 * relation could not be retrieved. 816 */ 817 public <M extends Configuration> void registerAddListener( 818 OptionalRelationDefinition<?, M> d, ConfigurationAddListener<M> listener) 819 throws IllegalArgumentException, ConfigException { 820 registerAddListener(d, new ServerManagedObjectAddListenerAdaptor<M>(listener)); 821 } 822 823 824 825 /** 826 * Register to be notified when a new child server managed object is 827 * added beneath an optional relation. 828 * 829 * @param <M> 830 * The type of the child server configuration object. 831 * @param d 832 * The optional relation definition. 833 * @param listener 834 * The server managed object add listener. 835 * @throws IllegalArgumentException 836 * If the optional relation definition is not associated 837 * with this managed object's definition. 838 * @throws ConfigException 839 * If the configuration entry associated with the optional 840 * relation could not be retrieved. 841 */ 842 public <M extends Configuration> void registerAddListener( 843 OptionalRelationDefinition<?, M> d, 844 ServerManagedObjectAddListener<M> listener) 845 throws IllegalArgumentException, ConfigException { 846 validateRelationDefinition(d); 847 DN baseDN = DNBuilder.create(path, d).parent(); 848 ConfigAddListener adaptor = new ConfigAddListenerAdaptor<>(path, d, listener); 849 registerAddListener(baseDN, adaptor); 850 } 851 852 853 854 /** 855 * Register to be notified when new child configurations are added 856 * beneath a set relation. 857 * 858 * @param <M> 859 * The type of the child server configuration object. 860 * @param d 861 * The set relation definition. 862 * @param listener 863 * The configuration add listener. 864 * @throws IllegalArgumentException 865 * If the set relation definition is not 866 * associated with this managed object's definition. 867 * @throws ConfigException 868 * If the configuration entry associated with the 869 * set relation could not be retrieved. 870 */ 871 public <M extends Configuration> void registerAddListener( 872 SetRelationDefinition<?, M> d, 873 ConfigurationAddListener<M> listener) throws IllegalArgumentException, 874 ConfigException { 875 registerAddListener(d, new ServerManagedObjectAddListenerAdaptor<M>( 876 listener)); 877 } 878 879 880 881 /** 882 * Register to be notified when new child server managed object are 883 * added beneath a set relation. 884 * 885 * @param <M> 886 * The type of the child server configuration object. 887 * @param d 888 * The set relation definition. 889 * @param listener 890 * The server managed object add listener. 891 * @throws IllegalArgumentException 892 * If the set relation definition is not 893 * associated with this managed object's definition. 894 * @throws ConfigException 895 * If the configuration entry associated with the 896 * set relation could not be retrieved. 897 */ 898 public <M extends Configuration> void registerAddListener( 899 SetRelationDefinition<?, M> d, 900 ServerManagedObjectAddListener<M> listener) 901 throws IllegalArgumentException, ConfigException { 902 validateRelationDefinition(d); 903 DN baseDN = DNBuilder.create(path, d); 904 ConfigAddListener adaptor = new ConfigAddListenerAdaptor<>(path, d, listener); 905 registerAddListener(baseDN, adaptor); 906 } 907 908 909 910 /** 911 * Register to be notified when this server managed object is 912 * changed. 913 * 914 * @param listener 915 * The configuration change listener. 916 */ 917 public void registerChangeListener( 918 ConfigurationChangeListener<? super S> listener) { 919 registerChangeListener(new ServerManagedObjectChangeListenerAdaptor<S>( 920 listener)); 921 } 922 923 924 925 /** 926 * Register to be notified when this server managed object is 927 * changed. 928 * 929 * @param listener 930 * The server managed object change listener. 931 */ 932 public void registerChangeListener( 933 ServerManagedObjectChangeListener<? super S> listener) { 934 ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<>(path, listener); 935 configEntry.registerChangeListener(adaptor); 936 937 // Change listener registration usually signifies that a managed 938 // object has been accepted and added to the server configuration 939 // during initialization post-add. 940 941 // FIXME: we should prevent multiple invocations in the case where 942 // multiple change listeners are registered for the same object. 943 for (Constraint constraint : definition.getAllConstraints()) { 944 for (ServerConstraintHandler handler : constraint 945 .getServerConstraintHandlers()) { 946 try { 947 handler.performPostAdd(this); 948 } catch (ConfigException e) { 949 logger.traceException(e); 950 } 951 } 952 } 953 } 954 955 956 957 /** 958 * Register to be notified when existing child configurations are 959 * deleted beneath an instantiable relation. 960 * 961 * @param <M> 962 * The type of the child server configuration object. 963 * @param d 964 * The instantiable relation definition. 965 * @param listener 966 * The configuration delete listener. 967 * @throws IllegalArgumentException 968 * If the instantiable relation definition is not 969 * associated with this managed object's definition. 970 * @throws ConfigException 971 * If the configuration entry associated with the 972 * instantiable relation could not be retrieved. 973 */ 974 public <M extends Configuration> void registerDeleteListener( 975 InstantiableRelationDefinition<?, M> d, 976 ConfigurationDeleteListener<M> listener) throws IllegalArgumentException, 977 ConfigException { 978 registerDeleteListener(d, new ServerManagedObjectDeleteListenerAdaptor<M>( 979 listener)); 980 } 981 982 983 984 /** 985 * Register to be notified when existing child server managed 986 * objects are deleted beneath an instantiable relation. 987 * 988 * @param <M> 989 * The type of the child server configuration object. 990 * @param d 991 * The instantiable relation definition. 992 * @param listener 993 * The server managed objects delete listener. 994 * @throws IllegalArgumentException 995 * If the instantiable relation definition is not 996 * associated with this managed object's definition. 997 * @throws ConfigException 998 * If the configuration entry associated with the 999 * instantiable relation could not be retrieved. 1000 */ 1001 public <M extends Configuration> void registerDeleteListener( 1002 InstantiableRelationDefinition<?, M> d, 1003 ServerManagedObjectDeleteListener<M> listener) 1004 throws IllegalArgumentException, ConfigException { 1005 validateRelationDefinition(d); 1006 DN baseDN = DNBuilder.create(path, d); 1007 ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<>(path, d, listener); 1008 registerDeleteListener(baseDN, adaptor); 1009 } 1010 1011 1012 1013 /** 1014 * Register to be notified when an existing child configuration is 1015 * deleted beneath an optional relation. 1016 * 1017 * @param <M> 1018 * The type of the child server configuration object. 1019 * @param d 1020 * The optional relation definition. 1021 * @param listener 1022 * The configuration delete listener. 1023 * @throws IllegalArgumentException 1024 * If the optional relation definition is not associated 1025 * with this managed object's definition. 1026 * @throws ConfigException 1027 * If the configuration entry associated with the optional 1028 * relation could not be retrieved. 1029 */ 1030 public <M extends Configuration> void registerDeleteListener( 1031 OptionalRelationDefinition<?, M> d, 1032 ConfigurationDeleteListener<M> listener) throws IllegalArgumentException, 1033 ConfigException { 1034 registerDeleteListener(d, new ServerManagedObjectDeleteListenerAdaptor<M>( 1035 listener)); 1036 } 1037 1038 1039 1040 /** 1041 * Register to be notified when an existing child server managed 1042 * object is deleted beneath an optional relation. 1043 * 1044 * @param <M> 1045 * The type of the child server configuration object. 1046 * @param d 1047 * The optional relation definition. 1048 * @param listener 1049 * The server managed object delete listener. 1050 * @throws IllegalArgumentException 1051 * If the optional relation definition is not associated 1052 * with this managed object's definition. 1053 * @throws ConfigException 1054 * If the configuration entry associated with the optional 1055 * relation could not be retrieved. 1056 */ 1057 public <M extends Configuration> void registerDeleteListener( 1058 OptionalRelationDefinition<?, M> d, 1059 ServerManagedObjectDeleteListener<M> listener) 1060 throws IllegalArgumentException, ConfigException { 1061 validateRelationDefinition(d); 1062 DN baseDN = DNBuilder.create(path, d).parent(); 1063 ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<>(path, d, listener); 1064 registerDeleteListener(baseDN, adaptor); 1065 } 1066 1067 1068 1069 /** 1070 * Register to be notified when existing child configurations are 1071 * deleted beneath a set relation. 1072 * 1073 * @param <M> 1074 * The type of the child server configuration object. 1075 * @param d 1076 * The set relation definition. 1077 * @param listener 1078 * The configuration delete listener. 1079 * @throws IllegalArgumentException 1080 * If the set relation definition is not 1081 * associated with this managed object's definition. 1082 * @throws ConfigException 1083 * If the configuration entry associated with the 1084 * set relation could not be retrieved. 1085 */ 1086 public <M extends Configuration> void registerDeleteListener( 1087 SetRelationDefinition<?, M> d, 1088 ConfigurationDeleteListener<M> listener) throws IllegalArgumentException, 1089 ConfigException { 1090 registerDeleteListener(d, new ServerManagedObjectDeleteListenerAdaptor<M>( 1091 listener)); 1092 } 1093 1094 1095 1096 /** 1097 * Register to be notified when existing child server managed 1098 * objects are deleted beneath a set relation. 1099 * 1100 * @param <M> 1101 * The type of the child server configuration object. 1102 * @param d 1103 * The set relation definition. 1104 * @param listener 1105 * The server managed objects delete listener. 1106 * @throws IllegalArgumentException 1107 * If the set relation definition is not 1108 * associated with this managed object's definition. 1109 * @throws ConfigException 1110 * If the configuration entry associated with the 1111 * set relation could not be retrieved. 1112 */ 1113 public <M extends Configuration> void registerDeleteListener( 1114 SetRelationDefinition<?, M> d, 1115 ServerManagedObjectDeleteListener<M> listener) 1116 throws IllegalArgumentException, ConfigException { 1117 validateRelationDefinition(d); 1118 DN baseDN = DNBuilder.create(path, d); 1119 ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<>(path, d, listener); 1120 registerDeleteListener(baseDN, adaptor); 1121 } 1122 1123 1124 1125 /** {@inheritDoc} */ 1126 @Override 1127 public String toString() { 1128 StringBuilder builder = new StringBuilder(); 1129 1130 builder.append("{ TYPE="); 1131 builder.append(definition.getName()); 1132 builder.append(", DN=\""); 1133 builder.append(getDN()); 1134 builder.append('\"'); 1135 for (Map.Entry<PropertyDefinition<?>, SortedSet<?>> value : properties 1136 .entrySet()) { 1137 builder.append(", "); 1138 builder.append(value.getKey().getName()); 1139 builder.append('='); 1140 builder.append(value.getValue()); 1141 } 1142 builder.append(" }"); 1143 1144 return builder.toString(); 1145 } 1146 1147 1148 1149 /** 1150 * Determines whether or not this managed object can be used by the 1151 * server. 1152 * 1153 * @throws ConstraintViolationException 1154 * If one or more constraints determined that this managed 1155 * object cannot be used by the server. 1156 */ 1157 void ensureIsUsable() throws ConstraintViolationException { 1158 // Enforce any constraints. 1159 boolean isUsable = true; 1160 List<LocalizableMessage> reasons = new LinkedList<>(); 1161 for (Constraint constraint : definition.getAllConstraints()) { 1162 for (ServerConstraintHandler handler : constraint 1163 .getServerConstraintHandlers()) { 1164 try { 1165 if (!handler.isUsable(this, reasons)) { 1166 isUsable = false; 1167 } 1168 } catch (ConfigException e) { 1169 LocalizableMessage message = ERR_SERVER_CONSTRAINT_EXCEPTION.get(e 1170 .getMessageObject()); 1171 reasons.add(message); 1172 isUsable = false; 1173 } 1174 } 1175 } 1176 1177 if (!isUsable) { 1178 throw new ConstraintViolationException(this, reasons); 1179 } 1180 } 1181 1182 1183 1184 /** 1185 * Update the config entry associated with this server managed 1186 * object. This is only intended to be used by change listener call 1187 * backs in order to update the managed object with the correct 1188 * config entry. 1189 * 1190 * @param configEntry 1191 * The configuration entry. 1192 */ 1193 void setConfigEntry(ConfigEntry configEntry) { 1194 this.configEntry = configEntry; 1195 } 1196 1197 1198 1199 /** Deregister an add listener. */ 1200 private <M extends Configuration> void deregisterAddListener(DN baseDN, 1201 ConfigurationAddListener<M> listener) { 1202 try { 1203 ConfigEntry configEntry = getListenerConfigEntry(baseDN); 1204 if (configEntry != null) { 1205 for (ConfigAddListener l : configEntry.getAddListeners()) { 1206 if (l instanceof ConfigAddListenerAdaptor) { 1207 ConfigAddListenerAdaptor<?> adaptor = 1208 (ConfigAddListenerAdaptor<?>) l; 1209 ServerManagedObjectAddListener<?> l2 = adaptor 1210 .getServerManagedObjectAddListener(); 1211 if (l2 instanceof ServerManagedObjectAddListenerAdaptor<?>) { 1212 ServerManagedObjectAddListenerAdaptor<?> adaptor2 = 1213 (ServerManagedObjectAddListenerAdaptor<?>) l2; 1214 if (adaptor2.getConfigurationAddListener() == listener) { 1215 configEntry.deregisterAddListener(adaptor); 1216 } 1217 } 1218 } 1219 } 1220 } 1221 else 1222 { 1223 // The relation entry does not exist so check for and deregister 1224 // delayed add listener. 1225 deregisterDelayedAddListener(baseDN, listener); 1226 } 1227 } catch (ConfigException e) { 1228 // Ignore the exception since this implies deregistration. 1229 logger.traceException(e); 1230 } 1231 } 1232 1233 1234 1235 /** Deregister an add listener. */ 1236 private <M extends Configuration> void deregisterAddListener(DN baseDN, 1237 ServerManagedObjectAddListener<M> listener) { 1238 try { 1239 ConfigEntry configEntry = getListenerConfigEntry(baseDN); 1240 if (configEntry != null) { 1241 for (ConfigAddListener l : configEntry.getAddListeners()) { 1242 if (l instanceof ConfigAddListenerAdaptor) { 1243 ConfigAddListenerAdaptor<?> adaptor = 1244 (ConfigAddListenerAdaptor<?>) l; 1245 if (adaptor.getServerManagedObjectAddListener() == listener) { 1246 configEntry.deregisterAddListener(adaptor); 1247 } 1248 } 1249 } 1250 } 1251 else 1252 { 1253 // The relation entry does not exist so check for and deregister 1254 // delayed add listener. 1255 deregisterDelayedAddListener(baseDN, listener); 1256 } 1257 } catch (ConfigException e) { 1258 // Ignore the exception since this implies deregistration. 1259 logger.traceException(e); 1260 } 1261 } 1262 1263 1264 1265 /** Deregister a delete listener. */ 1266 private <M extends Configuration> void deregisterDeleteListener(DN baseDN, 1267 ConfigurationDeleteListener<M> listener) { 1268 try { 1269 ConfigEntry configEntry = getListenerConfigEntry(baseDN); 1270 if (configEntry != null) { 1271 for (ConfigDeleteListener l : configEntry.getDeleteListeners()) { 1272 if (l instanceof ConfigDeleteListenerAdaptor) { 1273 ConfigDeleteListenerAdaptor<?> adaptor = 1274 (ConfigDeleteListenerAdaptor<?>) l; 1275 ServerManagedObjectDeleteListener<?> l2 = adaptor 1276 .getServerManagedObjectDeleteListener(); 1277 if (l2 instanceof ServerManagedObjectDeleteListenerAdaptor<?>) { 1278 ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 = 1279 (ServerManagedObjectDeleteListenerAdaptor<?>) l2; 1280 if (adaptor2.getConfigurationDeleteListener() == listener) { 1281 configEntry.deregisterDeleteListener(adaptor); 1282 } 1283 } 1284 } 1285 } 1286 } 1287 else 1288 { 1289 // The relation entry does not exist so check for and deregister 1290 // delayed add listener. 1291 deregisterDelayedDeleteListener(baseDN, listener); 1292 } 1293 } catch (ConfigException e) { 1294 // Ignore the exception since this implies deregistration. 1295 logger.traceException(e); 1296 } 1297 } 1298 1299 1300 1301 /** Deregister a delete listener. */ 1302 private <M extends Configuration> void deregisterDeleteListener(DN baseDN, 1303 ServerManagedObjectDeleteListener<M> listener) { 1304 try { 1305 ConfigEntry configEntry = getListenerConfigEntry(baseDN); 1306 if (configEntry != null) { 1307 for (ConfigDeleteListener l : configEntry.getDeleteListeners()) { 1308 if (l instanceof ConfigDeleteListenerAdaptor) { 1309 ConfigDeleteListenerAdaptor<?> adaptor = 1310 (ConfigDeleteListenerAdaptor<?>) l; 1311 if (adaptor.getServerManagedObjectDeleteListener() == listener) { 1312 configEntry.deregisterDeleteListener(adaptor); 1313 } 1314 } 1315 } 1316 } 1317 else 1318 { 1319 // The relation entry does not exist so check for and deregister 1320 // delayed add listener. 1321 deregisterDelayedDeleteListener(baseDN, listener); 1322 } 1323 } catch (ConfigException e) { 1324 // Ignore the exception since this implies deregistration. 1325 logger.traceException(e); 1326 } 1327 } 1328 1329 1330 1331 /** 1332 * Gets a config entry required for a listener and throws a config 1333 * exception on failure or returns null if the entry does not exist. 1334 */ 1335 private ConfigEntry getListenerConfigEntry(DN dn) throws ConfigException { 1336 // Attempt to retrieve the listener base entry. 1337 ConfigEntry configEntry; 1338 try { 1339 configEntry = DirectoryServer.getConfigEntry(dn); 1340 } catch (ConfigException e) { 1341 logger.traceException(e); 1342 1343 LocalizableMessage message = ERR_ADMIN_CANNOT_GET_LISTENER_BASE.get( 1344 dn, stackTraceToSingleLineString(e)); 1345 throw new ConfigException(message, e); 1346 } 1347 1348 return configEntry; 1349 } 1350 1351 1352 1353 /** Register an instantiable or optional relation add listener. */ 1354 private void registerAddListener(DN baseDN, ConfigAddListener adaptor) 1355 throws IllegalArgumentException, ConfigException { 1356 ConfigEntry relationEntry = getListenerConfigEntry(baseDN); 1357 1358 if (relationEntry != null) { 1359 relationEntry.registerAddListener(adaptor); 1360 } else { 1361 // The relation entry does not exist yet so register a delayed 1362 // add listener. 1363 ConfigAddListener delayedListener = new DelayedConfigAddListener(baseDN, 1364 adaptor); 1365 registerDelayedListener(baseDN, delayedListener); 1366 } 1367 } 1368 1369 1370 1371 /** 1372 * Register a delayed listener with the nearest existing parent 1373 * entry to the provided base DN. 1374 */ 1375 private void registerDelayedListener(DN baseDN, 1376 ConfigAddListener delayedListener) throws ConfigException { 1377 DN parentDN = baseDN.parent(); 1378 while (parentDN != null) { 1379 ConfigEntry relationEntry = getListenerConfigEntry(parentDN); 1380 if (relationEntry == null) { 1381 delayedListener = new DelayedConfigAddListener(parentDN, 1382 delayedListener); 1383 parentDN = parentDN.parent(); 1384 } else { 1385 relationEntry.registerAddListener(delayedListener); 1386 return; 1387 } 1388 } 1389 1390 // No parent entry could be found. 1391 LocalizableMessage message = ERR_ADMIN_UNABLE_TO_REGISTER_LISTENER.get(baseDN); 1392 throw new ConfigException(message); 1393 } 1394 1395 /** 1396 * Deregister a delayed listener with the nearest existing parent 1397 * entry to the provided base DN. 1398 */ 1399 private <M extends Configuration> void deregisterDelayedAddListener(DN baseDN, 1400 ConfigurationAddListener<M> listener) throws ConfigException { 1401 DN parentDN = baseDN.parent(); 1402 int delayWrappers = 0; 1403 while (parentDN != null) { 1404 ConfigEntry relationEntry = getListenerConfigEntry(parentDN); 1405 if (relationEntry == null) { 1406 parentDN = parentDN.parent(); 1407 delayWrappers++; 1408 } else { 1409 for (ConfigAddListener l : relationEntry.getAddListeners()) { 1410 if(l instanceof DelayedConfigAddListener) 1411 { 1412 DelayedConfigAddListener delayListener = 1413 (DelayedConfigAddListener) l; 1414 ConfigAddListener wrappedListener; 1415 1416 int i = delayWrappers; 1417 for(; i > 0; i--) 1418 { 1419 wrappedListener = delayListener.getDelayedAddListener(); 1420 if(wrappedListener instanceof DelayedConfigAddListener) 1421 { 1422 delayListener = (DelayedConfigAddListener) l; 1423 } 1424 else 1425 { 1426 break; 1427 } 1428 } 1429 1430 if(i > 0) 1431 { 1432 // There are not enough level of wrapping so this can't be 1433 // the listener we are looking for. 1434 continue; 1435 } 1436 1437 ConfigAddListener delayedListener = 1438 delayListener.getDelayedAddListener(); 1439 1440 if (delayedListener instanceof ConfigAddListenerAdaptor) { 1441 ConfigAddListenerAdaptor<?> adaptor = 1442 (ConfigAddListenerAdaptor<?>) delayedListener; 1443 ServerManagedObjectAddListener<?> l2 = adaptor 1444 .getServerManagedObjectAddListener(); 1445 if (l2 instanceof ServerManagedObjectAddListenerAdaptor<?>) { 1446 ServerManagedObjectAddListenerAdaptor<?> adaptor2 = 1447 (ServerManagedObjectAddListenerAdaptor<?>) l2; 1448 if (adaptor2.getConfigurationAddListener() == listener) { 1449 relationEntry.deregisterAddListener(l); 1450 } 1451 } 1452 } 1453 } 1454 } 1455 return; 1456 } 1457 } 1458 } 1459 1460 1461 /** 1462 * Deregister a delayed listener with the nearest existing parent 1463 * entry to the provided base DN. 1464 */ 1465 private <M extends Configuration> void deregisterDelayedDeleteListener( 1466 DN baseDN, ConfigurationDeleteListener<M> listener) 1467 throws ConfigException { 1468 DN parentDN = baseDN.parent(); 1469 int delayWrappers = 0; 1470 while (parentDN != null) { 1471 ConfigEntry relationEntry = getListenerConfigEntry(parentDN); 1472 if (relationEntry == null) { 1473 parentDN = parentDN.parent(); 1474 delayWrappers++; 1475 } else { 1476 for (ConfigAddListener l : relationEntry.getAddListeners()) { 1477 if(l instanceof DelayedConfigAddListener) 1478 { 1479 DelayedConfigAddListener delayListener = 1480 (DelayedConfigAddListener) l; 1481 ConfigAddListener wrappedListener; 1482 1483 int i = delayWrappers; 1484 for(; i > 0; i--) 1485 { 1486 wrappedListener = delayListener.getDelayedAddListener(); 1487 if(wrappedListener instanceof DelayedConfigAddListener) 1488 { 1489 delayListener = (DelayedConfigAddListener) l; 1490 } 1491 else 1492 { 1493 break; 1494 } 1495 } 1496 1497 if(i > 0) 1498 { 1499 // There are not enough level of wrapping so this can't be 1500 // the listener we are looking for. 1501 continue; 1502 } 1503 1504 ConfigDeleteListener delayedListener = 1505 delayListener.getDelayedDeleteListener(); 1506 1507 if (delayedListener instanceof ConfigDeleteListenerAdaptor) { 1508 ConfigDeleteListenerAdaptor<?> adaptor = 1509 (ConfigDeleteListenerAdaptor<?>) delayedListener; 1510 ServerManagedObjectDeleteListener<?> l2 = adaptor 1511 .getServerManagedObjectDeleteListener(); 1512 if (l2 instanceof ServerManagedObjectDeleteListenerAdaptor<?>) { 1513 ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 = 1514 (ServerManagedObjectDeleteListenerAdaptor<?>) l2; 1515 if (adaptor2.getConfigurationDeleteListener() == listener) { 1516 relationEntry.deregisterAddListener(l); 1517 } 1518 } 1519 } 1520 } 1521 } 1522 return; 1523 } 1524 } 1525 } 1526 1527 /** 1528 * Deregister a delayed listener with the nearest existing parent 1529 * entry to the provided base DN. 1530 */ 1531 private <M extends Configuration> void deregisterDelayedAddListener(DN baseDN, 1532 ServerManagedObjectAddListener<M> listener) throws ConfigException { 1533 DN parentDN = baseDN.parent(); 1534 int delayWrappers = 0; 1535 while (parentDN != null) { 1536 ConfigEntry relationEntry = getListenerConfigEntry(parentDN); 1537 if (relationEntry == null) { 1538 parentDN = parentDN.parent(); 1539 delayWrappers++; 1540 } else { 1541 for (ConfigAddListener l : relationEntry.getAddListeners()) { 1542 if(l instanceof DelayedConfigAddListener) 1543 { 1544 DelayedConfigAddListener delayListener = 1545 (DelayedConfigAddListener) l; 1546 ConfigAddListener wrappedListener; 1547 1548 int i = delayWrappers; 1549 for(; i > 0; i--) 1550 { 1551 wrappedListener = delayListener.getDelayedAddListener(); 1552 if(wrappedListener instanceof DelayedConfigAddListener) 1553 { 1554 delayListener = (DelayedConfigAddListener) l; 1555 } 1556 else 1557 { 1558 break; 1559 } 1560 } 1561 1562 if(i > 0) 1563 { 1564 // There are not enough level of wrapping so this can't be 1565 // the listener we are looking for. 1566 continue; 1567 } 1568 1569 ConfigAddListener delayedListener = 1570 delayListener.getDelayedAddListener(); 1571 1572 if (delayedListener instanceof ConfigAddListenerAdaptor) { 1573 ConfigAddListenerAdaptor<?> adaptor = 1574 (ConfigAddListenerAdaptor<?>) delayedListener; 1575 if (adaptor.getServerManagedObjectAddListener() == listener) { 1576 relationEntry.deregisterAddListener(l); 1577 } 1578 } 1579 } 1580 } 1581 return; 1582 } 1583 } 1584 } 1585 1586 1587 /** 1588 * Deregister a delayed listener with the nearest existing parent 1589 * entry to the provided base DN. 1590 */ 1591 private <M extends Configuration> void deregisterDelayedDeleteListener( 1592 DN baseDN, ServerManagedObjectDeleteListener<M> listener) 1593 throws ConfigException { 1594 DN parentDN = baseDN.parent(); 1595 int delayWrappers = 0; 1596 while (parentDN != null) { 1597 ConfigEntry relationEntry = getListenerConfigEntry(parentDN); 1598 if (relationEntry == null) { 1599 parentDN = parentDN.parent(); 1600 delayWrappers++; 1601 } else { 1602 for (ConfigAddListener l : relationEntry.getAddListeners()) { 1603 if(l instanceof DelayedConfigAddListener) 1604 { 1605 DelayedConfigAddListener delayListener = 1606 (DelayedConfigAddListener) l; 1607 ConfigAddListener wrappedListener; 1608 1609 int i = delayWrappers; 1610 for(; i > 0; i--) 1611 { 1612 wrappedListener = delayListener.getDelayedAddListener(); 1613 if(wrappedListener instanceof DelayedConfigAddListener) 1614 { 1615 delayListener = (DelayedConfigAddListener) l; 1616 } 1617 else 1618 { 1619 break; 1620 } 1621 } 1622 1623 if(i > 0) 1624 { 1625 // There are not enough level of wrapping so this can't be 1626 // the listener we are looking for. 1627 continue; 1628 } 1629 1630 ConfigDeleteListener delayedListener = 1631 delayListener.getDelayedDeleteListener(); 1632 1633 if (delayedListener instanceof ConfigDeleteListenerAdaptor) { 1634 ConfigDeleteListenerAdaptor<?> adaptor = 1635 (ConfigDeleteListenerAdaptor<?>) delayedListener; 1636 if (adaptor.getServerManagedObjectDeleteListener() == listener) { 1637 relationEntry.deregisterAddListener(l); 1638 } 1639 } 1640 } 1641 } 1642 return; 1643 } 1644 } 1645 } 1646 1647 1648 /** Register an instantiable or optional relation delete listener. */ 1649 private void registerDeleteListener(DN baseDN, ConfigDeleteListener adaptor) 1650 throws ConfigException { 1651 ConfigEntry relationEntry = getListenerConfigEntry(baseDN); 1652 1653 if (relationEntry != null) { 1654 relationEntry.registerDeleteListener(adaptor); 1655 } else { 1656 // The relation entry does not exist yet so register a delayed 1657 // add listener. 1658 ConfigAddListener delayedListener = new DelayedConfigAddListener(baseDN, 1659 adaptor); 1660 registerDelayedListener(baseDN, delayedListener); 1661 } 1662 } 1663 1664 1665 1666 /** Validate that a relation definition belongs to this managed object. */ 1667 private void validateRelationDefinition(RelationDefinition<?, ?> rd) 1668 throws IllegalArgumentException { 1669 RelationDefinition<?, ?> tmp = definition.getRelationDefinition(rd 1670 .getName()); 1671 if (tmp != rd) { 1672 throw new IllegalArgumentException("The relation " + rd.getName() 1673 + " is not associated with a " + definition.getName()); 1674 } 1675 } 1676}