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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.admin.client.spi; 029 030 031 032 import java.util.ArrayList; 033 import java.util.Collection; 034 import java.util.Collections; 035 import java.util.LinkedList; 036 import java.util.List; 037 import java.util.Set; 038 import java.util.SortedSet; 039 040 import org.opends.messages.Message; 041 import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider; 042 import org.opends.server.admin.AbstractManagedObjectDefinition; 043 import org.opends.server.admin.AliasDefaultBehaviorProvider; 044 import org.opends.server.admin.Configuration; 045 import org.opends.server.admin.ConfigurationClient; 046 import org.opends.server.admin.Constraint; 047 import org.opends.server.admin.DefaultBehaviorException; 048 import org.opends.server.admin.DefaultBehaviorProviderVisitor; 049 import org.opends.server.admin.DefinedDefaultBehaviorProvider; 050 import org.opends.server.admin.DefinitionDecodingException; 051 import org.opends.server.admin.IllegalPropertyValueStringException; 052 import org.opends.server.admin.InstantiableRelationDefinition; 053 import org.opends.server.admin.ManagedObjectNotFoundException; 054 import org.opends.server.admin.ManagedObjectPath; 055 import org.opends.server.admin.OptionalRelationDefinition; 056 import org.opends.server.admin.PropertyDefinition; 057 import org.opends.server.admin.PropertyException; 058 import org.opends.server.admin.PropertyIsSingleValuedException; 059 import org.opends.server.admin.PropertyNotFoundException; 060 import org.opends.server.admin.PropertyOption; 061 import org.opends.server.admin.RelationDefinition; 062 import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider; 063 import org.opends.server.admin.UndefinedDefaultBehaviorProvider; 064 import org.opends.server.admin.DefinitionDecodingException.Reason; 065 import org.opends.server.admin.client.AuthorizationException; 066 import org.opends.server.admin.client.ClientConstraintHandler; 067 import org.opends.server.admin.client.CommunicationException; 068 import org.opends.server.admin.client.ManagedObject; 069 import org.opends.server.admin.client.ManagedObjectDecodingException; 070 import org.opends.server.admin.client.ManagementContext; 071 import org.opends.server.admin.client.OperationRejectedException; 072 import org.opends.server.admin.client.OperationRejectedException.OperationType; 073 import org.opends.server.admin.std.client.RootCfgClient; 074 075 076 077 /** 078 * An abstract management connection context driver which should form 079 * the basis of driver implementations. 080 */ 081 public abstract class Driver { 082 083 /** 084 * A default behavior visitor used for retrieving the default values 085 * of a property. 086 * 087 * @param <T> 088 * The type of the property. 089 */ 090 private class DefaultValueFinder<T> implements 091 DefaultBehaviorProviderVisitor<T, Collection<T>, Void> { 092 093 // Any exception that occurred whilst retrieving inherited default 094 // values. 095 private DefaultBehaviorException exception = null; 096 097 // The path of the managed object containing the first property. 098 private final ManagedObjectPath<?, ?> firstPath; 099 100 // Indicates whether the managed object has been created yet. 101 private final boolean isCreate; 102 103 // The path of the managed object containing the next property. 104 private ManagedObjectPath<?, ?> nextPath = null; 105 106 // The next property whose default values were required. 107 private PropertyDefinition<T> nextProperty = null; 108 109 110 111 // Private constructor. 112 private DefaultValueFinder(ManagedObjectPath<?, ?> p, boolean isCreate) { 113 this.firstPath = p; 114 this.isCreate = isCreate; 115 } 116 117 118 119 /** 120 * {@inheritDoc} 121 */ 122 public Collection<T> visitAbsoluteInherited( 123 AbsoluteInheritedDefaultBehaviorProvider<T> d, Void p) { 124 try { 125 return getInheritedProperty(d.getManagedObjectPath(), d 126 .getManagedObjectDefinition(), d.getPropertyName()); 127 } catch (DefaultBehaviorException e) { 128 exception = e; 129 return Collections.emptySet(); 130 } 131 } 132 133 134 135 /** 136 * {@inheritDoc} 137 */ 138 public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d, Void p) { 139 return Collections.emptySet(); 140 } 141 142 143 144 /** 145 * {@inheritDoc} 146 */ 147 public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d, 148 Void p) { 149 Collection<String> stringValues = d.getDefaultValues(); 150 List<T> values = new ArrayList<T>(stringValues.size()); 151 152 for (String stringValue : stringValues) { 153 try { 154 values.add(nextProperty.decodeValue(stringValue)); 155 } catch (IllegalPropertyValueStringException e) { 156 exception = new DefaultBehaviorException(nextProperty, e); 157 break; 158 } 159 } 160 161 return values; 162 } 163 164 165 166 /** 167 * {@inheritDoc} 168 */ 169 public Collection<T> visitRelativeInherited( 170 RelativeInheritedDefaultBehaviorProvider<T> d, Void p) { 171 try { 172 return getInheritedProperty(d.getManagedObjectPath(nextPath), d 173 .getManagedObjectDefinition(), d.getPropertyName()); 174 } catch (DefaultBehaviorException e) { 175 exception = e; 176 return Collections.emptySet(); 177 } 178 } 179 180 181 182 /** 183 * {@inheritDoc} 184 */ 185 public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d, 186 Void p) { 187 return Collections.emptySet(); 188 } 189 190 191 192 // Find the default values for the next path/property. 193 private Collection<T> find(ManagedObjectPath<?, ?> p, 194 PropertyDefinition<T> pd) throws DefaultBehaviorException { 195 this.nextPath = p; 196 this.nextProperty = pd; 197 198 Collection<T> values = nextProperty.getDefaultBehaviorProvider().accept( 199 this, null); 200 201 if (exception != null) { 202 throw exception; 203 } 204 205 if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) { 206 throw new DefaultBehaviorException(pd, 207 new PropertyIsSingleValuedException(pd)); 208 } 209 210 return values; 211 } 212 213 214 215 // Get an inherited property value. 216 @SuppressWarnings("unchecked") 217 private Collection<T> getInheritedProperty(ManagedObjectPath target, 218 AbstractManagedObjectDefinition<?, ?> d, String propertyName) 219 throws DefaultBehaviorException { 220 // First check that the requested type of managed object 221 // corresponds to the path. 222 AbstractManagedObjectDefinition<?, ?> supr = target 223 .getManagedObjectDefinition(); 224 if (!supr.isParentOf(d)) { 225 throw new DefaultBehaviorException( 226 nextProperty, new DefinitionDecodingException(supr, 227 Reason.WRONG_TYPE_INFORMATION)); 228 } 229 230 // Save the current property in case of recursion. 231 PropertyDefinition<T> pd1 = nextProperty; 232 233 try { 234 // Determine the requested property definition. 235 PropertyDefinition<T> pd2; 236 try { 237 // FIXME: we use the definition taken from the default 238 // behavior here when we should really use the exact 239 // definition of the component being created. 240 PropertyDefinition<?> pdTmp = d.getPropertyDefinition(propertyName); 241 pd2 = pd1.getClass().cast(pdTmp); 242 } catch (IllegalArgumentException e) { 243 throw new PropertyNotFoundException(propertyName); 244 } catch (ClassCastException e) { 245 // FIXME: would be nice to throw a better exception here. 246 throw new PropertyNotFoundException(propertyName); 247 } 248 249 // If the path relates to the current managed object and the 250 // managed object is in the process of being created it won't 251 // exist, so we should just use the default values of the 252 // referenced property. 253 if (isCreate && firstPath.equals(target)) { 254 // Recursively retrieve this property's default values. 255 Collection<T> tmp = find(target, pd2); 256 Collection<T> values = new ArrayList<T>(tmp.size()); 257 for (T value : tmp) { 258 pd1.validateValue(value); 259 values.add(value); 260 } 261 return values; 262 } else { 263 // FIXME: issue 2481 - this is broken if the referenced property 264 // inherits its defaults from the newly created managed object. 265 return getPropertyValues(target, pd2); 266 } 267 } catch (DefaultBehaviorException e) { 268 // Wrap any errors due to recursion. 269 throw new DefaultBehaviorException(pd1, e); 270 } catch (DefinitionDecodingException e) { 271 throw new DefaultBehaviorException(pd1, e); 272 } catch (PropertyNotFoundException e) { 273 throw new DefaultBehaviorException(pd1, e); 274 } catch (AuthorizationException e) { 275 throw new DefaultBehaviorException(pd1, e); 276 } catch (ManagedObjectNotFoundException e) { 277 throw new DefaultBehaviorException(pd1, e); 278 } catch (CommunicationException e) { 279 throw new DefaultBehaviorException(pd1, e); 280 } catch (PropertyException e) { 281 throw new DefaultBehaviorException(pd1, e); 282 } 283 } 284 }; 285 286 287 288 /** 289 * Creates a new abstract management context. 290 */ 291 protected Driver() { 292 // No implementation required. 293 } 294 295 296 297 /** 298 * Closes any context associated with this management context 299 * driver. 300 */ 301 public void close() { 302 // do nothing by default 303 } 304 305 306 307 /** 308 * Deletes the named instantiable child managed object from the 309 * named parent managed object. 310 * 311 * @param <C> 312 * The type of client managed object configuration that the 313 * relation definition refers to. 314 * @param <S> 315 * The type of server managed object configuration that the 316 * relation definition refers to. 317 * @param parent 318 * The path of the parent managed object. 319 * @param rd 320 * The instantiable relation definition. 321 * @param name 322 * The name of the child managed object to be removed. 323 * @return Returns <code>true</code> if the named instantiable 324 * child managed object was found, or <code>false</code> 325 * if it was not found. 326 * @throws IllegalArgumentException 327 * If the relation definition is not associated with the 328 * parent managed object's definition. 329 * @throws ManagedObjectNotFoundException 330 * If the parent managed object could not be found. 331 * @throws OperationRejectedException 332 * If the managed object cannot be removed due to some 333 * client-side or server-side constraint which cannot be 334 * satisfied (for example, if it is referenced by another 335 * managed object). 336 * @throws AuthorizationException 337 * If the server refuses to remove the managed objects 338 * because the client does not have the correct 339 * privileges. 340 * @throws CommunicationException 341 * If the client cannot contact the server due to an 342 * underlying communication problem. 343 */ 344 public final <C extends ConfigurationClient, S extends Configuration> 345 boolean deleteManagedObject( 346 ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd, 347 String name) throws IllegalArgumentException, 348 ManagedObjectNotFoundException, OperationRejectedException, 349 AuthorizationException, CommunicationException { 350 validateRelationDefinition(parent, rd); 351 ManagedObjectPath<?, ?> child = parent.child(rd, name); 352 return doDeleteManagedObject(child); 353 } 354 355 356 357 /** 358 * Deletes the optional child managed object from the named parent 359 * managed object. 360 * 361 * @param <C> 362 * The type of client managed object configuration that the 363 * relation definition refers to. 364 * @param <S> 365 * The type of server managed object configuration that the 366 * relation definition refers to. 367 * @param parent 368 * The path of the parent managed object. 369 * @param rd 370 * The optional relation definition. 371 * @return Returns <code>true</code> if the optional child managed 372 * object was found, or <code>false</code> if it was not 373 * found. 374 * @throws IllegalArgumentException 375 * If the relation definition is not associated with the 376 * parent managed object's definition. 377 * @throws ManagedObjectNotFoundException 378 * If the parent managed object could not be found. 379 * @throws OperationRejectedException 380 * If the managed object cannot be removed due to some 381 * client-side or server-side constraint which cannot be 382 * satisfied (for example, if it is referenced by another 383 * managed object). 384 * @throws AuthorizationException 385 * If the server refuses to remove the managed objects 386 * because the client does not have the correct 387 * privileges. 388 * @throws CommunicationException 389 * If the client cannot contact the server due to an 390 * underlying communication problem. 391 */ 392 public final <C extends ConfigurationClient, S extends Configuration> 393 boolean deleteManagedObject( 394 ManagedObjectPath<?, ?> parent, OptionalRelationDefinition<C, S> rd) 395 throws IllegalArgumentException, ManagedObjectNotFoundException, 396 OperationRejectedException, AuthorizationException, 397 CommunicationException { 398 validateRelationDefinition(parent, rd); 399 ManagedObjectPath<?, ?> child = parent.child(rd); 400 return doDeleteManagedObject(child); 401 } 402 403 404 405 /** 406 * Gets the named managed object. The path is guaranteed to be 407 * non-empty, so implementations do not need to worry about handling 408 * this special case. 409 * 410 * @param <C> 411 * The type of client managed object configuration that the 412 * path definition refers to. 413 * @param <S> 414 * The type of server managed object configuration that the 415 * path definition refers to. 416 * @param path 417 * The non-empty path of the managed object. 418 * @return Returns the named managed object. 419 * @throws DefinitionDecodingException 420 * If the managed object was found but its type could not 421 * be determined. 422 * @throws ManagedObjectDecodingException 423 * If the managed object was found but one or more of its 424 * properties could not be decoded. 425 * @throws ManagedObjectNotFoundException 426 * If the requested managed object could not be found on 427 * the server. 428 * @throws AuthorizationException 429 * If the server refuses to retrieve the managed object 430 * because the client does not have the correct 431 * privileges. 432 * @throws CommunicationException 433 * If the client cannot contact the server due to an 434 * underlying communication problem. 435 */ 436 public abstract <C extends ConfigurationClient, S extends Configuration> 437 ManagedObject<? extends C> getManagedObject( 438 ManagedObjectPath<C, S> path) throws DefinitionDecodingException, 439 ManagedObjectDecodingException, ManagedObjectNotFoundException, 440 AuthorizationException, CommunicationException; 441 442 443 444 /** 445 * Gets the effective value of a property in the named managed 446 * object. 447 * 448 * @param <C> 449 * The type of client managed object configuration that the 450 * path definition refers to. 451 * @param <S> 452 * The type of server managed object configuration that the 453 * path definition refers to. 454 * @param <PD> 455 * The type of the property to be retrieved. 456 * @param path 457 * The path of the managed object containing the property. 458 * @param pd 459 * The property to be retrieved. 460 * @return Returns the property's effective value, or 461 * <code>null</code> if there are no values defined. 462 * @throws IllegalArgumentException 463 * If the property definition is not associated with the 464 * referenced managed object's definition. 465 * @throws DefinitionDecodingException 466 * If the managed object was found but its type could not 467 * be determined. 468 * @throws PropertyException 469 * If the managed object was found but the requested 470 * property could not be decoded. 471 * @throws ManagedObjectNotFoundException 472 * If the requested managed object could not be found on 473 * the server. 474 * @throws AuthorizationException 475 * If the server refuses to retrieve the managed object 476 * because the client does not have the correct 477 * privileges. 478 * @throws CommunicationException 479 * If the client cannot contact the server due to an 480 * underlying communication problem. 481 */ 482 public final <C extends ConfigurationClient, S extends Configuration, PD> 483 PD getPropertyValue(ManagedObjectPath<C, S> path, 484 PropertyDefinition<PD> pd) throws IllegalArgumentException, 485 DefinitionDecodingException, AuthorizationException, 486 ManagedObjectNotFoundException, CommunicationException, 487 PropertyException { 488 Set<PD> values = getPropertyValues(path, pd); 489 if (values.isEmpty()) { 490 return null; 491 } else { 492 return values.iterator().next(); 493 } 494 } 495 496 497 498 /** 499 * Gets the effective values of a property in the named managed 500 * object. 501 * <p> 502 * Implementations MUST NOT not use 503 * {@link #getManagedObject(ManagedObjectPath)} to read the 504 * referenced managed object in its entirety. Specifically, 505 * implementations MUST only attempt to resolve the default values 506 * for the requested property and its dependencies (if it uses 507 * inherited defaults). This is to avoid infinite recursion where a 508 * managed object contains a property which inherits default values 509 * from another property in the same managed object. 510 * 511 * @param <C> 512 * The type of client managed object configuration that the 513 * path definition refers to. 514 * @param <S> 515 * The type of server managed object configuration that the 516 * path definition refers to. 517 * @param <PD> 518 * The type of the property to be retrieved. 519 * @param path 520 * The path of the managed object containing the property. 521 * @param pd 522 * The property to be retrieved. 523 * @return Returns the property's effective values, or an empty set 524 * if there are no values defined. 525 * @throws IllegalArgumentException 526 * If the property definition is not associated with the 527 * referenced managed object's definition. 528 * @throws DefinitionDecodingException 529 * If the managed object was found but its type could not 530 * be determined. 531 * @throws PropertyException 532 * If the managed object was found but the requested 533 * property could not be decoded. 534 * @throws ManagedObjectNotFoundException 535 * If the requested managed object could not be found on 536 * the server. 537 * @throws AuthorizationException 538 * If the server refuses to retrieve the managed object 539 * because the client does not have the correct 540 * privileges. 541 * @throws CommunicationException 542 * If the client cannot contact the server due to an 543 * underlying communication problem. 544 */ 545 public abstract <C extends ConfigurationClient, S extends Configuration, PD> 546 SortedSet<PD> getPropertyValues( 547 ManagedObjectPath<C, S> path, PropertyDefinition<PD> pd) 548 throws IllegalArgumentException, DefinitionDecodingException, 549 AuthorizationException, ManagedObjectNotFoundException, 550 CommunicationException, PropertyException; 551 552 553 554 /** 555 * Gets the root configuration managed object associated with this 556 * management context driver. 557 * 558 * @return Returns the root configuration managed object associated 559 * with this management context driver. 560 */ 561 public abstract 562 ManagedObject<RootCfgClient> getRootConfigurationManagedObject(); 563 564 565 566 /** 567 * Lists the child managed objects of the named parent managed 568 * object. 569 * 570 * @param <C> 571 * The type of client managed object configuration that the 572 * relation definition refers to. 573 * @param <S> 574 * The type of server managed object configuration that the 575 * relation definition refers to. 576 * @param parent 577 * The path of the parent managed object. 578 * @param rd 579 * The instantiable relation definition. 580 * @return Returns the names of the child managed objects. 581 * @throws IllegalArgumentException 582 * If the relation definition is not associated with the 583 * parent managed object's definition. 584 * @throws ManagedObjectNotFoundException 585 * If the parent managed object could not be found. 586 * @throws AuthorizationException 587 * If the server refuses to list the managed objects 588 * because the client does not have the correct 589 * privileges. 590 * @throws CommunicationException 591 * If the client cannot contact the server due to an 592 * underlying communication problem. 593 */ 594 public final <C extends ConfigurationClient, S extends Configuration> 595 String[] listManagedObjects( 596 ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd) 597 throws IllegalArgumentException, ManagedObjectNotFoundException, 598 AuthorizationException, CommunicationException { 599 return listManagedObjects(parent, rd, rd.getChildDefinition()); 600 } 601 602 603 604 /** 605 * Lists the child managed objects of the named parent managed 606 * object which are a sub-type of the specified managed object 607 * definition. 608 * 609 * @param <C> 610 * The type of client managed object configuration that the 611 * relation definition refers to. 612 * @param <S> 613 * The type of server managed object configuration that the 614 * relation definition refers to. 615 * @param parent 616 * The path of the parent managed object. 617 * @param rd 618 * The instantiable relation definition. 619 * @param d 620 * The managed object definition. 621 * @return Returns the names of the child managed objects which are 622 * a sub-type of the specified managed object definition. 623 * @throws IllegalArgumentException 624 * If the relation definition is not associated with the 625 * parent managed object's definition. 626 * @throws ManagedObjectNotFoundException 627 * If the parent managed object could not be found. 628 * @throws AuthorizationException 629 * If the server refuses to list the managed objects 630 * because the client does not have the correct 631 * privileges. 632 * @throws CommunicationException 633 * If the client cannot contact the server due to an 634 * underlying communication problem. 635 */ 636 public abstract <C extends ConfigurationClient, S extends Configuration> 637 String[] listManagedObjects( 638 ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd, 639 AbstractManagedObjectDefinition<? extends C, ? extends S> d) 640 throws IllegalArgumentException, ManagedObjectNotFoundException, 641 AuthorizationException, CommunicationException; 642 643 644 645 /** 646 * Determines whether or not the named managed object exists. 647 * <p> 648 * Implementations should always return <code>true</code> when the 649 * provided path is empty. 650 * 651 * @param path 652 * The path of the named managed object. 653 * @return Returns <code>true</code> if the named managed object 654 * exists, <code>false</code> otherwise. 655 * @throws ManagedObjectNotFoundException 656 * If the parent managed object could not be found. 657 * @throws AuthorizationException 658 * If the server refuses to make the determination because 659 * the client does not have the correct privileges. 660 * @throws CommunicationException 661 * If the client cannot contact the server due to an 662 * underlying communication problem. 663 */ 664 public abstract boolean managedObjectExists(ManagedObjectPath<?, ?> path) 665 throws ManagedObjectNotFoundException, AuthorizationException, 666 CommunicationException; 667 668 669 670 /** 671 * Deletes the named managed object. 672 * <p> 673 * Implementations do not need check whether the named managed 674 * object exists, nor do they need to enforce client constraints. 675 * 676 * @param <C> 677 * The type of client managed object configuration that the 678 * relation definition refers to. 679 * @param <S> 680 * The type of server managed object configuration that the 681 * relation definition refers to. 682 * @param path 683 * The path of the managed object to be deleted. 684 * @throws OperationRejectedException 685 * If the managed object cannot be removed due to some 686 * server-side constraint which cannot be satisfied (for 687 * example, if it is referenced by another managed 688 * object). 689 * @throws AuthorizationException 690 * If the server refuses to remove the managed objects 691 * because the client does not have the correct 692 * privileges. 693 * @throws CommunicationException 694 * If the client cannot contact the server due to an 695 * underlying communication problem. 696 */ 697 protected abstract <C extends ConfigurationClient, S extends Configuration> 698 void deleteManagedObject( 699 ManagedObjectPath<C, S> path) throws OperationRejectedException, 700 AuthorizationException, CommunicationException; 701 702 703 704 /** 705 * Gets the default values for the specified property. 706 * 707 * @param <PD> 708 * The type of the property. 709 * @param p 710 * The managed object path of the current managed object. 711 * @param pd 712 * The property definition. 713 * @param isCreate 714 * Indicates whether the managed object has been created 715 * yet. 716 * @return Returns the default values for the specified property. 717 * @throws DefaultBehaviorException 718 * If the default values could not be retrieved or decoded 719 * properly. 720 */ 721 protected final <PD> Collection<PD> findDefaultValues( 722 ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd, boolean isCreate) 723 throws DefaultBehaviorException { 724 DefaultValueFinder<PD> v = new DefaultValueFinder<PD>(p, isCreate); 725 return v.find(p, pd); 726 } 727 728 729 730 /** 731 * Gets the management context associated with this driver. 732 * 733 * @return Returns the management context associated with this 734 * driver. 735 */ 736 protected abstract ManagementContext getManagementContext(); 737 738 739 740 /** 741 * Validate that a relation definition belongs to the managed object 742 * referenced by the provided path. 743 * 744 * @param path 745 * The parent managed object path. 746 * @param rd 747 * The relation definition. 748 * @throws IllegalArgumentException 749 * If the relation definition does not belong to the 750 * managed object definition. 751 */ 752 protected final void validateRelationDefinition(ManagedObjectPath<?, ?> path, 753 RelationDefinition<?, ?> rd) throws IllegalArgumentException { 754 AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition(); 755 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName()); 756 if (tmp != rd) { 757 throw new IllegalArgumentException("The relation " + rd.getName() 758 + " is not associated with a " + d.getName()); 759 } 760 } 761 762 763 764 // Remove a managed object, first ensuring that the parent exists, 765 // then ensuring that the child exists, before ensuring that any 766 // constraints are satisfied. 767 private <C extends ConfigurationClient, S extends Configuration> 768 boolean doDeleteManagedObject( 769 ManagedObjectPath<C, S> path) throws ManagedObjectNotFoundException, 770 OperationRejectedException, AuthorizationException, 771 CommunicationException { 772 // First make sure that the parent exists. 773 if (!managedObjectExists(path.parent())) { 774 throw new ManagedObjectNotFoundException(); 775 } 776 777 // Make sure that the targeted managed object exists. 778 if (!managedObjectExists(path)) { 779 return false; 780 } 781 782 // The targeted managed object is guaranteed to exist, so enforce 783 // any constraints. 784 AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition(); 785 List<Message> messages = new LinkedList<Message>(); 786 boolean isAcceptable = true; 787 788 for (Constraint constraint : d.getAllConstraints()) { 789 for (ClientConstraintHandler handler : constraint 790 .getClientConstraintHandlers()) { 791 ManagementContext context = getManagementContext(); 792 if (!handler.isDeleteAcceptable(context, path, messages)) { 793 isAcceptable = false; 794 } 795 } 796 } 797 798 if (!isAcceptable) { 799 throw new OperationRejectedException(OperationType.DELETE, d 800 .getUserFriendlyName(), messages); 801 } 802 803 deleteManagedObject(path); 804 return true; 805 } 806 807 }