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