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