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