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 }