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