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