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 029 030 031import java.util.Collection; 032import java.util.Collections; 033import java.util.LinkedList; 034import java.util.List; 035import java.util.Set; 036import java.util.SortedSet; 037import java.util.TreeSet; 038 039import org.forgerock.i18n.LocalizableMessage; 040import org.opends.server.admin.AbstractManagedObjectDefinition; 041import org.opends.server.admin.Configuration; 042import org.opends.server.admin.ConfigurationClient; 043import org.opends.server.admin.Constraint; 044import org.opends.server.admin.PropertyException; 045import org.opends.server.admin.DefaultManagedObject; 046import org.opends.server.admin.DefinitionDecodingException; 047import org.opends.server.admin.InstantiableRelationDefinition; 048import org.opends.server.admin.ManagedObjectAlreadyExistsException; 049import org.opends.server.admin.ManagedObjectDefinition; 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.PropertyOption; 055import org.opends.server.admin.RelationDefinition; 056import org.opends.server.admin.RelationDefinitionVisitor; 057import org.opends.server.admin.SetRelationDefinition; 058import org.opends.server.admin.SingletonRelationDefinition; 059import org.opends.server.admin.DefinitionDecodingException.Reason; 060import org.opends.server.admin.client.AuthorizationException; 061import org.opends.server.admin.client.ClientConstraintHandler; 062import org.opends.server.admin.client.CommunicationException; 063import org.opends.server.admin.client.ConcurrentModificationException; 064import org.opends.server.admin.client.IllegalManagedObjectNameException; 065import org.opends.server.admin.client.ManagedObject; 066import org.opends.server.admin.client.ManagedObjectDecodingException; 067import org.opends.server.admin.client.ManagementContext; 068import org.opends.server.admin.client.MissingMandatoryPropertiesException; 069import org.opends.server.admin.client.OperationRejectedException; 070import org.opends.server.admin.client.OperationRejectedException.OperationType; 071 072 073 074/** 075 * An abstract managed object implementation. 076 * 077 * @param <T> 078 * The type of client configuration represented by the client 079 * managed object. 080 */ 081public abstract class AbstractManagedObject<T extends ConfigurationClient> 082 implements ManagedObject<T> { 083 084 /** 085 * Creates any default managed objects associated with a relation 086 * definition. 087 */ 088 private final class DefaultManagedObjectFactory implements 089 RelationDefinitionVisitor<Void, Void> { 090 091 /** Possible exceptions. */ 092 private AuthorizationException ae; 093 private ManagedObjectAlreadyExistsException moaee; 094 private MissingMandatoryPropertiesException mmpe; 095 private ConcurrentModificationException cme; 096 private OperationRejectedException ore; 097 private CommunicationException ce; 098 099 /** {@inheritDoc} */ 100 public <C extends ConfigurationClient, S extends Configuration> 101 Void visitInstantiable( 102 InstantiableRelationDefinition<C, S> rd, Void p) { 103 for (String name : rd.getDefaultManagedObjectNames()) { 104 DefaultManagedObject<? extends C, ? extends S> dmo = rd 105 .getDefaultManagedObject(name); 106 ManagedObjectDefinition<? extends C, ? extends S> d = dmo 107 .getManagedObjectDefinition(); 108 ManagedObject<? extends C> child; 109 try { 110 child = createChild(rd, d, name, null); 111 } catch (IllegalManagedObjectNameException e) { 112 // This should not happen. 113 throw new RuntimeException(e); 114 } 115 createDefaultManagedObject(d, child, dmo); 116 } 117 return null; 118 } 119 120 121 122 /** {@inheritDoc} */ 123 public <C extends ConfigurationClient, S extends Configuration> 124 Void visitOptional( 125 OptionalRelationDefinition<C, S> rd, Void p) { 126 if (rd.getDefaultManagedObject() != null) { 127 DefaultManagedObject<? extends C, ? extends S> dmo = rd 128 .getDefaultManagedObject(); 129 ManagedObjectDefinition<? extends C, ? extends S> d = dmo 130 .getManagedObjectDefinition(); 131 ManagedObject<? extends C> child = createChild(rd, d, null); 132 createDefaultManagedObject(d, child, dmo); 133 } 134 return null; 135 } 136 137 138 139 /** {@inheritDoc} */ 140 public <C extends ConfigurationClient, S extends Configuration> 141 Void visitSingleton( 142 SingletonRelationDefinition<C, S> rd, Void p) { 143 // Do nothing - not possible to create singletons 144 // dynamically. 145 return null; 146 } 147 148 149 150 /** {@inheritDoc} */ 151 public <C extends ConfigurationClient, S extends Configuration> 152 Void visitSet( 153 SetRelationDefinition<C, S> rd, Void p) { 154 for (String name : rd.getDefaultManagedObjectNames()) { 155 DefaultManagedObject<? extends C, ? extends S> dmo = rd 156 .getDefaultManagedObject(name); 157 ManagedObjectDefinition<? extends C, ? extends S> d = dmo 158 .getManagedObjectDefinition(); 159 ManagedObject<? extends C> child = createChild(rd, d, null); 160 createDefaultManagedObject(d, child, dmo); 161 } 162 return null; 163 } 164 165 166 167 /** Create the child managed object. */ 168 private void createDefaultManagedObject(ManagedObjectDefinition<?, ?> d, 169 ManagedObject<?> child, DefaultManagedObject<?, ?> dmo) { 170 for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { 171 setPropertyValues(child, pd, dmo); 172 } 173 174 try { 175 child.commit(); 176 } catch (AuthorizationException e) { 177 ae = e; 178 } catch (ManagedObjectAlreadyExistsException e) { 179 moaee = e; 180 } catch (MissingMandatoryPropertiesException e) { 181 mmpe = e; 182 } catch (ConcurrentModificationException e) { 183 cme = e; 184 } catch (OperationRejectedException e) { 185 ore = e; 186 } catch (CommunicationException e) { 187 ce = e; 188 } 189 } 190 191 192 193 /** 194 * Creates the default managed objects associated with the 195 * provided relation definition. 196 * 197 * @param rd 198 * The relation definition. 199 */ 200 private void createDefaultManagedObjects(RelationDefinition<?, ?> rd) 201 throws AuthorizationException, CommunicationException, 202 ConcurrentModificationException, MissingMandatoryPropertiesException, 203 ManagedObjectAlreadyExistsException, OperationRejectedException { 204 rd.accept(this, null); 205 206 if (ae != null) { 207 throw ae; 208 } else if (ce != null) { 209 throw ce; 210 } else if (cme != null) { 211 throw cme; 212 } else if (mmpe != null) { 213 throw mmpe; 214 } else if (moaee != null) { 215 throw moaee; 216 } else if (ore != null) { 217 throw ore; 218 } 219 } 220 221 222 223 /** Set property values. */ 224 private <PD> void setPropertyValues(ManagedObject<?> mo, 225 PropertyDefinition<PD> pd, DefaultManagedObject<?, ?> dmo) { 226 mo.setPropertyValues(pd, dmo.getPropertyValues(pd)); 227 } 228 } 229 230 231 232 /** The managed object definition associated with this managed object. */ 233 private final ManagedObjectDefinition<T, ? extends Configuration> definition; 234 235 /** 236 * Indicates whether or not this managed object exists on the server 237 * (false means the managed object is new and has not been committed). 238 */ 239 private boolean existsOnServer; 240 241 /** Optional naming property definition. */ 242 private final PropertyDefinition<?> namingPropertyDefinition; 243 244 /** The path associated with this managed object. */ 245 private ManagedObjectPath<T, ? extends Configuration> path; 246 247 /** The managed object's properties. */ 248 private final PropertySet properties; 249 250 251 252 /** 253 * Creates a new abstract managed object. 254 * 255 * @param d 256 * The managed object's definition. 257 * @param path 258 * The managed object's path. 259 * @param properties 260 * The managed object's properties. 261 * @param existsOnServer 262 * Indicates whether or not the managed object exists on 263 * the server (false means the managed object is new and 264 * has not been committed). 265 * @param namingPropertyDefinition 266 * Optional naming property definition. 267 */ 268 protected AbstractManagedObject( 269 ManagedObjectDefinition<T, ? extends Configuration> d, 270 ManagedObjectPath<T, ? extends Configuration> path, 271 PropertySet properties, boolean existsOnServer, 272 PropertyDefinition<?> namingPropertyDefinition) { 273 this.definition = d; 274 this.path = path; 275 this.properties = properties; 276 this.existsOnServer = existsOnServer; 277 this.namingPropertyDefinition = namingPropertyDefinition; 278 } 279 280 281 282 /** {@inheritDoc} */ 283 public final void commit() throws ManagedObjectAlreadyExistsException, 284 MissingMandatoryPropertiesException, ConcurrentModificationException, 285 OperationRejectedException, AuthorizationException, 286 CommunicationException { 287 // First make sure all mandatory properties are defined. 288 List<PropertyException> exceptions = new LinkedList<>(); 289 290 for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) { 291 Property<?> p = getProperty(pd); 292 if (pd.hasOption(PropertyOption.MANDATORY) 293 && p.getEffectiveValues().isEmpty()) { 294 exceptions.add(PropertyException.propertyIsMandatoryException(pd)); 295 } 296 } 297 298 if (!exceptions.isEmpty()) { 299 throw new MissingMandatoryPropertiesException(definition 300 .getUserFriendlyName(), exceptions, !existsOnServer); 301 } 302 303 // Now enforce any constraints. 304 List<LocalizableMessage> messages = new LinkedList<>(); 305 boolean isAcceptable = true; 306 ManagementContext context = getDriver().getManagementContext(); 307 308 for (Constraint constraint : definition.getAllConstraints()) { 309 for (ClientConstraintHandler handler : constraint 310 .getClientConstraintHandlers()) { 311 if (existsOnServer) { 312 if (!handler.isModifyAcceptable(context, this, messages)) { 313 isAcceptable = false; 314 } 315 } else { 316 if (!handler.isAddAcceptable(context, this, messages)) { 317 isAcceptable = false; 318 } 319 } 320 } 321 if (!isAcceptable) { 322 break; 323 } 324 } 325 326 if (!isAcceptable) { 327 if (existsOnServer) { 328 throw new OperationRejectedException(OperationType.MODIFY, definition 329 .getUserFriendlyName(), messages); 330 } else { 331 throw new OperationRejectedException(OperationType.CREATE, definition 332 .getUserFriendlyName(), messages); 333 } 334 } 335 336 // Commit the managed object. 337 if (existsOnServer) { 338 modifyExistingManagedObject(); 339 } else { 340 addNewManagedObject(); 341 } 342 343 // Make all pending property values active. 344 properties.commit(); 345 346 // If the managed object was created make sure that any default 347 // subordinate managed objects are also created. 348 if (!existsOnServer) { 349 DefaultManagedObjectFactory factory = new DefaultManagedObjectFactory(); 350 for (RelationDefinition<?, ?> rd : 351 definition.getAllRelationDefinitions()) { 352 factory.createDefaultManagedObjects(rd); 353 } 354 355 existsOnServer = true; 356 } 357 } 358 359 360 361 /** {@inheritDoc} */ 362 public final <C extends ConfigurationClient, S extends Configuration, 363 CC extends C> 364 ManagedObject<CC> createChild( 365 InstantiableRelationDefinition<C, S> r, 366 ManagedObjectDefinition<CC, ? extends S> d, String name, 367 Collection<PropertyException> exceptions) 368 throws IllegalManagedObjectNameException, IllegalArgumentException { 369 validateRelationDefinition(r); 370 371 // Empty names are not allowed. 372 if (name.trim().length() == 0) { 373 throw new IllegalManagedObjectNameException(name); 374 } 375 376 // If the relation uses a naming property definition then it must 377 // be a valid value. 378 PropertyDefinition<?> pd = r.getNamingPropertyDefinition(); 379 if (pd != null) { 380 try { 381 pd.decodeValue(name); 382 } catch (PropertyException e) { 383 throw new IllegalManagedObjectNameException(name, pd); 384 } 385 } 386 387 ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d, name); 388 return createNewManagedObject(d, childPath, pd, name, exceptions); 389 } 390 391 392 393 /** {@inheritDoc} */ 394 public final <C extends ConfigurationClient, 395 S extends Configuration, CC extends C> 396 ManagedObject<CC> createChild( 397 OptionalRelationDefinition<C, S> r, 398 ManagedObjectDefinition<CC, ? extends S> d, 399 Collection<PropertyException> exceptions) 400 throws IllegalArgumentException { 401 validateRelationDefinition(r); 402 ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d); 403 return createNewManagedObject(d, childPath, null, null, exceptions); 404 } 405 406 407 408 /** {@inheritDoc} */ 409 public final <C extends ConfigurationClient, S extends Configuration, 410 CC extends C> 411 ManagedObject<CC> createChild( 412 SetRelationDefinition<C, S> r, 413 ManagedObjectDefinition<CC, ? extends S> d, 414 Collection<PropertyException> exceptions) 415 throws IllegalArgumentException { 416 validateRelationDefinition(r); 417 418 ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d); 419 return createNewManagedObject(d, childPath, null, null, exceptions); 420 } 421 422 423 424 /** {@inheritDoc} */ 425 public final <C extends ConfigurationClient, S extends Configuration> 426 ManagedObject<? extends C> getChild( 427 InstantiableRelationDefinition<C, S> r, String name) 428 throws IllegalArgumentException, DefinitionDecodingException, 429 ManagedObjectDecodingException, ManagedObjectNotFoundException, 430 ConcurrentModificationException, AuthorizationException, 431 CommunicationException { 432 validateRelationDefinition(r); 433 ensureThisManagedObjectExists(); 434 Driver ctx = getDriver(); 435 return ctx.getManagedObject(path.child(r, name)); 436 } 437 438 439 440 /** {@inheritDoc} */ 441 public final <C extends ConfigurationClient, S extends Configuration> 442 ManagedObject<? extends C> getChild( 443 OptionalRelationDefinition<C, S> r) throws IllegalArgumentException, 444 DefinitionDecodingException, ManagedObjectDecodingException, 445 ManagedObjectNotFoundException, ConcurrentModificationException, 446 AuthorizationException, CommunicationException { 447 validateRelationDefinition(r); 448 ensureThisManagedObjectExists(); 449 Driver ctx = getDriver(); 450 return ctx.getManagedObject(path.child(r)); 451 } 452 453 454 455 /** {@inheritDoc} */ 456 public final <C extends ConfigurationClient, S extends Configuration> 457 ManagedObject<? extends C> getChild( 458 SingletonRelationDefinition<C, S> r) throws IllegalArgumentException, 459 DefinitionDecodingException, ManagedObjectDecodingException, 460 ManagedObjectNotFoundException, ConcurrentModificationException, 461 AuthorizationException, CommunicationException { 462 validateRelationDefinition(r); 463 ensureThisManagedObjectExists(); 464 Driver ctx = getDriver(); 465 return ctx.getManagedObject(path.child(r)); 466 } 467 468 469 470 /** {@inheritDoc} */ 471 public final <C extends ConfigurationClient, S extends Configuration> 472 ManagedObject<? extends C> getChild( 473 SetRelationDefinition<C, S> r, String name) 474 throws IllegalArgumentException, DefinitionDecodingException, 475 ManagedObjectDecodingException, ManagedObjectNotFoundException, 476 ConcurrentModificationException, AuthorizationException, 477 CommunicationException { 478 validateRelationDefinition(r); 479 ensureThisManagedObjectExists(); 480 Driver ctx = getDriver(); 481 482 AbstractManagedObjectDefinition<C, S> d = r.getChildDefinition(); 483 AbstractManagedObjectDefinition<? extends C, ? extends S> cd; 484 485 try 486 { 487 cd = d.getChild(name); 488 } 489 catch (IllegalArgumentException e) 490 { 491 // Unrecognized definition name - report this as a decoding 492 // exception. 493 throw new DefinitionDecodingException(d, 494 Reason.WRONG_TYPE_INFORMATION); 495 } 496 497 return ctx.getManagedObject(path.child(r, cd)); 498 } 499 500 501 502 /** {@inheritDoc} */ 503 public final T getConfiguration() { 504 return definition.createClientConfiguration(this); 505 } 506 507 508 509 /** {@inheritDoc} */ 510 public final ManagedObjectDefinition<T, ? extends Configuration> 511 getManagedObjectDefinition() { 512 return definition; 513 } 514 515 516 517 /** {@inheritDoc} */ 518 public final ManagedObjectPath<T, ? extends Configuration> 519 getManagedObjectPath() { 520 return path; 521 } 522 523 524 525 /** {@inheritDoc} */ 526 public final <PD> SortedSet<PD> getPropertyDefaultValues( 527 PropertyDefinition<PD> pd) throws IllegalArgumentException { 528 return new TreeSet<>(getProperty(pd).getDefaultValues()); 529 } 530 531 532 533 /** {@inheritDoc} */ 534 public final <PD> PD getPropertyValue(PropertyDefinition<PD> pd) 535 throws IllegalArgumentException { 536 Set<PD> values = getProperty(pd).getEffectiveValues(); 537 if (!values.isEmpty()) { 538 return values.iterator().next(); 539 } 540 return null; 541 } 542 543 544 545 /** {@inheritDoc} */ 546 public final <PD> SortedSet<PD> getPropertyValues(PropertyDefinition<PD> pd) 547 throws IllegalArgumentException { 548 return new TreeSet<>(getProperty(pd).getEffectiveValues()); 549 } 550 551 552 553 /** {@inheritDoc} */ 554 public final <C extends ConfigurationClient, S extends Configuration> 555 boolean hasChild( 556 OptionalRelationDefinition<C, S> r) throws IllegalArgumentException, 557 ConcurrentModificationException, AuthorizationException, 558 CommunicationException { 559 validateRelationDefinition(r); 560 Driver ctx = getDriver(); 561 try { 562 return ctx.managedObjectExists(path.child(r)); 563 } catch (ManagedObjectNotFoundException e) { 564 throw new ConcurrentModificationException(); 565 } 566 } 567 568 569 570 /** {@inheritDoc} */ 571 public final boolean isPropertyPresent(PropertyDefinition<?> pd) 572 throws IllegalArgumentException { 573 return !getProperty(pd).isEmpty(); 574 } 575 576 577 578 /** {@inheritDoc} */ 579 public final <C extends ConfigurationClient, S extends Configuration> 580 String[] listChildren( 581 InstantiableRelationDefinition<C, S> r) throws IllegalArgumentException, 582 ConcurrentModificationException, AuthorizationException, 583 CommunicationException { 584 return listChildren(r, r.getChildDefinition()); 585 } 586 587 588 589 /** {@inheritDoc} */ 590 public final <C extends ConfigurationClient, S extends Configuration> 591 String[] listChildren( 592 InstantiableRelationDefinition<C, S> r, 593 AbstractManagedObjectDefinition<? extends C, ? extends S> d) 594 throws IllegalArgumentException, ConcurrentModificationException, 595 AuthorizationException, CommunicationException { 596 validateRelationDefinition(r); 597 Driver ctx = getDriver(); 598 try { 599 return ctx.listManagedObjects(path, r, d); 600 } catch (ManagedObjectNotFoundException e) { 601 throw new ConcurrentModificationException(); 602 } 603 } 604 605 606 607 /** {@inheritDoc} */ 608 public final <C extends ConfigurationClient, S extends Configuration> 609 String[] listChildren( 610 SetRelationDefinition<C, S> r) throws IllegalArgumentException, 611 ConcurrentModificationException, AuthorizationException, 612 CommunicationException { 613 return listChildren(r, r.getChildDefinition()); 614 } 615 616 617 618 /** {@inheritDoc} */ 619 public final <C extends ConfigurationClient, S extends Configuration> 620 String[] listChildren( 621 SetRelationDefinition<C, S> r, 622 AbstractManagedObjectDefinition<? extends C, ? extends S> d) 623 throws IllegalArgumentException, ConcurrentModificationException, 624 AuthorizationException, CommunicationException { 625 validateRelationDefinition(r); 626 Driver ctx = getDriver(); 627 try { 628 return ctx.listManagedObjects(path, r, d); 629 } catch (ManagedObjectNotFoundException e) { 630 throw new ConcurrentModificationException(); 631 } 632 } 633 634 635 636 /** {@inheritDoc} */ 637 public final <C extends ConfigurationClient, S extends Configuration> 638 void removeChild( 639 InstantiableRelationDefinition<C, S> r, String name) 640 throws IllegalArgumentException, ManagedObjectNotFoundException, 641 OperationRejectedException, ConcurrentModificationException, 642 AuthorizationException, CommunicationException { 643 validateRelationDefinition(r); 644 Driver ctx = getDriver(); 645 boolean found; 646 647 try { 648 found = ctx.deleteManagedObject(path, r, name); 649 } catch (ManagedObjectNotFoundException e) { 650 throw new ConcurrentModificationException(); 651 } 652 653 if (!found) { 654 throw new ManagedObjectNotFoundException(); 655 } 656 } 657 658 659 660 /** {@inheritDoc} */ 661 public final <C extends ConfigurationClient, S extends Configuration> 662 void removeChild( 663 OptionalRelationDefinition<C, S> r) throws IllegalArgumentException, 664 ManagedObjectNotFoundException, OperationRejectedException, 665 ConcurrentModificationException, AuthorizationException, 666 CommunicationException { 667 validateRelationDefinition(r); 668 Driver ctx = getDriver(); 669 boolean found; 670 671 try { 672 found = ctx.deleteManagedObject(path, r); 673 } catch (ManagedObjectNotFoundException e) { 674 throw new ConcurrentModificationException(); 675 } 676 677 if (!found) { 678 throw new ManagedObjectNotFoundException(); 679 } 680 } 681 682 683 684 /** {@inheritDoc} */ 685 public final <C extends ConfigurationClient, S extends Configuration> 686 void removeChild( 687 SetRelationDefinition<C, S> r, String name) 688 throws IllegalArgumentException, ManagedObjectNotFoundException, 689 OperationRejectedException, ConcurrentModificationException, 690 AuthorizationException, CommunicationException { 691 validateRelationDefinition(r); 692 Driver ctx = getDriver(); 693 boolean found; 694 695 try { 696 found = ctx.deleteManagedObject(path, r, name); 697 } catch (ManagedObjectNotFoundException e) { 698 throw new ConcurrentModificationException(); 699 } 700 701 if (!found) { 702 throw new ManagedObjectNotFoundException(); 703 } 704 } 705 706 707 708 /** {@inheritDoc} */ 709 public final <PD> void setPropertyValue(PropertyDefinition<PD> pd, PD value) 710 throws PropertyException, PropertyException, 711 PropertyException, IllegalArgumentException { 712 if (value == null) { 713 setPropertyValues(pd, Collections.<PD> emptySet()); 714 } else { 715 setPropertyValues(pd, Collections.singleton(value)); 716 } 717 } 718 719 720 721 /** {@inheritDoc} */ 722 public final <PD> void setPropertyValues(PropertyDefinition<PD> pd, 723 Collection<PD> values) throws PropertyException, 724 PropertyException, PropertyException, 725 PropertyException, IllegalArgumentException { 726 if (pd.hasOption(PropertyOption.MONITORING)) { 727 throw PropertyException.propertyIsReadOnlyException(pd); 728 } 729 730 if (existsOnServer && pd.hasOption(PropertyOption.READ_ONLY)) { 731 throw PropertyException.propertyIsReadOnlyException(pd); 732 } 733 734 properties.setPropertyValues(pd, values); 735 736 // If this is a naming property then update the name. 737 if (pd.equals(namingPropertyDefinition)) { 738 // The property must be single-valued and mandatory. 739 String newName = pd.encodeValue(values.iterator().next()); 740 path = path.rename(newName); 741 } 742 } 743 744 745 746 /** {@inheritDoc} */ 747 @Override 748 public String toString() { 749 StringBuilder builder = new StringBuilder(); 750 751 builder.append("{ TYPE="); 752 builder.append(definition.getName()); 753 builder.append(", PATH=\""); 754 builder.append(path); 755 builder.append('\"'); 756 for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) { 757 builder.append(", "); 758 builder.append(pd.getName()); 759 builder.append('='); 760 builder.append(getPropertyValues(pd)); 761 } 762 builder.append(" }"); 763 764 return builder.toString(); 765 } 766 767 768 769 /** 770 * Adds this new managed object. 771 * 772 * @throws ManagedObjectAlreadyExistsException 773 * If the managed object cannot be added to the server 774 * because it already exists. 775 * @throws ConcurrentModificationException 776 * If the managed object's parent has been removed by 777 * another client. 778 * @throws OperationRejectedException 779 * If the managed object cannot be added due to some 780 * client-side or server-side constraint which cannot be 781 * satisfied. 782 * @throws AuthorizationException 783 * If the server refuses to add this managed object 784 * because the client does not have the correct 785 * privileges. 786 * @throws CommunicationException 787 * If the client cannot contact the server due to an 788 * underlying communication problem. 789 */ 790 protected abstract void addNewManagedObject() throws AuthorizationException, 791 CommunicationException, OperationRejectedException, 792 ConcurrentModificationException, ManagedObjectAlreadyExistsException; 793 794 795 796 /** 797 * Gets the management context driver associated with this managed 798 * object. 799 * 800 * @return Returns the management context driver associated with 801 * this managed object. 802 */ 803 protected abstract Driver getDriver(); 804 805 806 807 /** 808 * Gets the naming property definition associated with this managed 809 * object. 810 * 811 * @return Returns the naming property definition associated with 812 * this managed object, or <code>null</code> if this 813 * managed object does not have a naming property. 814 */ 815 protected final PropertyDefinition<?> getNamingPropertyDefinition() { 816 return namingPropertyDefinition; 817 } 818 819 820 821 /** 822 * Gets the property associated with the specified property 823 * definition. 824 * 825 * @param <PD> 826 * The underlying type of the property. 827 * @param pd 828 * The Property definition. 829 * @return Returns the property associated with the specified 830 * property definition. 831 * @throws IllegalArgumentException 832 * If this property provider does not recognize the 833 * requested property definition. 834 */ 835 protected final <PD> Property<PD> getProperty(PropertyDefinition<PD> pd) 836 throws IllegalArgumentException { 837 return properties.getProperty(pd); 838 } 839 840 841 842 /** 843 * Applies changes made to this managed object. 844 * 845 * @throws ConcurrentModificationException 846 * If this managed object has been removed from the server 847 * by another client. 848 * @throws OperationRejectedException 849 * If the managed object cannot be added due to some 850 * client-side or server-side constraint which cannot be 851 * satisfied. 852 * @throws AuthorizationException 853 * If the server refuses to modify this managed object 854 * because the client does not have the correct 855 * privileges. 856 * @throws CommunicationException 857 * If the client cannot contact the server due to an 858 * underlying communication problem. 859 */ 860 protected abstract void modifyExistingManagedObject() 861 throws ConcurrentModificationException, OperationRejectedException, 862 AuthorizationException, CommunicationException; 863 864 865 866 /** 867 * Creates a new managed object. 868 * 869 * @param <M> 870 * The type of client configuration represented by the 871 * client managed object. 872 * @param d 873 * The managed object's definition. 874 * @param path 875 * The managed object's path. 876 * @param properties 877 * The managed object's properties. 878 * @param existsOnServer 879 * Indicates whether or not the managed object exists on 880 * the server (false means the managed object is new and 881 * has not been committed). 882 * @param namingPropertyDefinition 883 * Optional naming property definition. 884 * @return Returns the new managed object. 885 */ 886 protected abstract <M extends ConfigurationClient> 887 ManagedObject<M> newInstance( 888 ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> path, 889 PropertySet properties, boolean existsOnServer, 890 PropertyDefinition<?> namingPropertyDefinition); 891 892 893 894 /** 895 * Creates a new managed object with no active values, just default 896 * values. 897 */ 898 private <M extends ConfigurationClient, PD> ManagedObject<M> 899 createNewManagedObject( 900 ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> p, 901 PropertyDefinition<PD> namingPropertyDefinition, String name, 902 Collection<PropertyException> exceptions) { 903 PropertySet childProperties = new PropertySet(); 904 for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { 905 try { 906 createProperty(childProperties, p, pd); 907 } catch (PropertyException e) { 908 // Add the exception if requested. 909 if (exceptions != null) { 910 exceptions.add(e); 911 } 912 } 913 } 914 915 // Set the naming property if there is one. 916 if (namingPropertyDefinition != null) { 917 PD value = namingPropertyDefinition.decodeValue(name); 918 childProperties.setPropertyValues(namingPropertyDefinition, Collections 919 .singleton(value)); 920 } 921 922 return newInstance(d, p, childProperties, false, namingPropertyDefinition); 923 } 924 925 926 927 /** Create an empty property. */ 928 private <PD> void createProperty(PropertySet properties, 929 ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd) 930 throws PropertyException { 931 try { 932 Driver context = getDriver(); 933 Collection<PD> defaultValues = context.findDefaultValues(p, pd, true); 934 properties.addProperty(pd, defaultValues, Collections.<PD> emptySet()); 935 } catch (PropertyException e) { 936 // Make sure that we have still created the property. 937 properties.addProperty(pd, Collections.<PD> emptySet(), Collections 938 .<PD> emptySet()); 939 throw e; 940 } 941 } 942 943 944 945 /** Makes sure that this managed object exists. */ 946 private void ensureThisManagedObjectExists() 947 throws ConcurrentModificationException, CommunicationException, 948 AuthorizationException { 949 if (!path.isEmpty()) { 950 Driver ctx = getDriver(); 951 952 try { 953 if (!ctx.managedObjectExists(path)) { 954 throw new ConcurrentModificationException(); 955 } 956 } catch (ManagedObjectNotFoundException e) { 957 throw new ConcurrentModificationException(); 958 } 959 } 960 } 961 962 963 964 /** Validate that a relation definition belongs to this managed object. */ 965 private void validateRelationDefinition(RelationDefinition<?, ?> rd) 966 throws IllegalArgumentException { 967 ManagedObjectDefinition<T, ?> d = getManagedObjectDefinition(); 968 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName()); 969 if (tmp != rd) { 970 throw new IllegalArgumentException("The relation " + rd.getName() 971 + " is not associated with a " + d.getName()); 972 } 973 } 974 975}